@dunnewold-labs/mr-manager 0.4.26 → 0.4.28

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 +45 -12
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -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.26",
188
+ version: "0.4.28",
189
189
  description: "Mr. Manager - Task and project management CLI",
190
190
  bin: {
191
191
  mr: "./dist/index.mjs"
@@ -1354,6 +1354,18 @@ If a scenario name matches the feature you're testing (by name or keyword):
1354
1354
  3. Note in your test plan summary which scenario you used.
1355
1355
 
1356
1356
  If no matching scenario exists, infer interactions from the codebase as normal.`;
1357
+ var SYSTEM_SECTION_QUIET_MODE = `## Quiet Mode \u2014 CRITICAL
1358
+
1359
+ You are running in **quiet mode**. This means:
1360
+
1361
+ 1. **DO NOT** write any explanatory text, conversation, commentary, or summaries outside of tool calls.
1362
+ 2. **DO NOT** describe what you are about to do or what you just did in prose.
1363
+ 3. **ONLY** output text when using \`mr update\` for status updates (keep these to 1 short sentence each).
1364
+ 4. All your work must happen through tool calls (Read, Edit, Write, Bash, etc.) \u2014 not through conversational output.
1365
+ 5. When you would normally explain your reasoning or next steps, simply proceed silently with the tool calls.
1366
+ 6. After completing work, exit immediately without a summary.
1367
+
1368
+ 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
1369
  var SYSTEM_SECTIONS = {
1358
1370
  "status-updates": SYSTEM_SECTION_STATUS_UPDATES,
1359
1371
  "screenshots": SYSTEM_SECTION_SCREENSHOTS,
@@ -1362,7 +1374,8 @@ var SYSTEM_SECTIONS = {
1362
1374
  "features-workflow": SYSTEM_SECTION_FEATURES_WORKFLOW,
1363
1375
  "prd-format": SYSTEM_SECTION_PRD_FORMAT,
1364
1376
  "prd-open-questions": SYSTEM_SECTION_PRD_OPEN_QUESTIONS,
1365
- "mr-tests": SYSTEM_SECTION_MR_TESTS
1377
+ "mr-tests": SYSTEM_SECTION_MR_TESTS,
1378
+ "quiet-mode": SYSTEM_SECTION_QUIET_MODE
1366
1379
  };
1367
1380
  function composeSystemPrompt(sections) {
1368
1381
  return sections.map((s) => SYSTEM_SECTIONS[s]).join("\n\n");
@@ -2498,9 +2511,7 @@ ${systemPrompt}` : prompt2;
2498
2511
  if (mode === "plan") {
2499
2512
  return { bin: "claude", args: [...sessionArgs, ...nameArgs, ...systemArgs, ...turnsArgs, ...modelArgs, "--permission-mode", "plan", "-p", prompt2] };
2500
2513
  }
2501
- const cfg = loadConfig();
2502
- const permissionMode = cfg.claudePermissionMode ?? "auto";
2503
- const permissionArgs = permissionMode === "dangerously-skip-permissions" ? ["--dangerously-skip-permissions"] : ["--permission-mode", "auto", "--enable-auto-mode"];
2514
+ const permissionArgs = ["--dangerously-skip-permissions"];
2504
2515
  return { bin: "claude", args: [...sessionArgs, ...nameArgs, ...systemArgs, ...turnsArgs, ...modelArgs, ...permissionArgs, "-p", prompt2] };
2505
2516
  }
2506
2517
  function commandExists(cmd) {
@@ -2573,7 +2584,7 @@ function askYesNo(question) {
2573
2584
  });
2574
2585
  });
2575
2586
  }
2576
- function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name, resumeSession = false, onSpawnError, systemPrompt, maxTurns, claudeModel) {
2587
+ function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name, resumeSession = false, onSpawnError, systemPrompt, maxTurns, claudeModel, onOutputBytes) {
2577
2588
  const jobLabel = name ?? "unknown";
2578
2589
  console.log(`${timestamp()} ${prefix} ${paint("dim", tokenLogLine("agent", jobLabel, prompt2, systemPrompt))}`);
2579
2590
  const { bin, args } = buildAgentArgs(agent, prompt2, "execute", sessionId, name, resumeSession, systemPrompt, maxTurns, claudeModel);
@@ -2592,12 +2603,14 @@ function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name
2592
2603
  }
2593
2604
  child.stdout?.on("data", (data) => {
2594
2605
  onActivity?.();
2606
+ onOutputBytes?.(data.length);
2595
2607
  for (const line of data.toString().split("\n")) {
2596
2608
  if (line) console.log(`${timestamp()} ${prefix} ${paint("dim", line)}`);
2597
2609
  }
2598
2610
  });
2599
2611
  child.stderr?.on("data", (data) => {
2600
2612
  onActivity?.();
2613
+ onOutputBytes?.(data.length);
2601
2614
  for (const line of data.toString().split("\n")) {
2602
2615
  if (line) logError(prefix, paint("dim", line));
2603
2616
  }
@@ -2606,13 +2619,14 @@ function spawnAgent(agent, repoDir, prompt2, prefix, onActivity, sessionId, name
2606
2619
  }
2607
2620
  var watchCommand = new Command8("watch").description(
2608
2621
  "Watch for in-progress tasks and autonomously dispatch an AI coding agent to work on them"
2609
- ).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 gemini", "claude").option("--scan-at <HH:MM>", "Run a product scan daily at this time (e.g., 02:00)").action(async (opts) => {
2622
+ ).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 gemini", "claude").option("--scan-at <HH:MM>", "Run a product scan daily at this time (e.g., 02:00)").option("--quiet", "Run all tasks in quiet mode (agent outputs only status updates, no conversation)", false).action(async (opts) => {
2610
2623
  const intervalMs = parseInt(opts.interval, 10) * 1e3;
2611
2624
  const dryRun = opts.dryRun;
2612
2625
  const planApproval = opts.planApproval;
2613
2626
  const rootDir = opts.root ? resolve2(opts.root) : process.cwd();
2614
2627
  const agent = opts.agent === "codex" ? "codex" : opts.agent === "gemini" ? "gemini" : "claude";
2615
2628
  const scanAt = opts.scanAt;
2629
+ const globalQuietMode = opts.quiet;
2616
2630
  const taskStallTimeoutMs = getTaskStallTimeoutMs();
2617
2631
  const hungTaskTimeoutMinutes = Math.max(5, parseInt(process.env.MR_WATCH_HUNG_TASK_TIMEOUT_MINUTES ?? "60", 10) || 60);
2618
2632
  const hungTaskTimeoutMs = hungTaskTimeoutMinutes * 6e4;
@@ -2633,6 +2647,7 @@ var watchCommand = new Command8("watch").description(
2633
2647
  `stall-timeout=${paint("cyan", formatTimeoutMinutes(taskStallTimeoutMs))}`,
2634
2648
  ...planApproval ? [paint("yellow", "plan-approval")] : [],
2635
2649
  ...dryRun ? [paint("yellow", "dry-run")] : [],
2650
+ ...globalQuietMode ? [paint("yellow", "quiet")] : [],
2636
2651
  ...scanAt ? [`scan-at=${paint("cyan", scanAt)}`] : [],
2637
2652
  `hung-timeout=${paint("cyan", `${hungTaskTimeoutMinutes}m`)}`
2638
2653
  ].join(" ");
@@ -2757,8 +2772,9 @@ var watchCommand = new Command8("watch").description(
2757
2772
  const legacyBranchName = `mr/${sid}/${slug}`;
2758
2773
  const prefix = taskTag(sid);
2759
2774
  const vcs = detectVcs(repoDir)?.provider ?? "github";
2760
- logDispatch(prefix, `"${paint("bold", task.title)}" ${paint("gray", repoDir)} ${paint("dim", `[${vcs}]`)}`);
2761
- await postTaskUpdate(task.id, `Agent dispatched \u2014 starting work on "${task.title}"`, "system");
2775
+ const taskIsQuiet = task.quietMode || globalQuietMode;
2776
+ logDispatch(prefix, `"${paint("bold", task.title)}" ${paint("gray", repoDir)} ${paint("dim", `[${vcs}]`)}${taskIsQuiet ? ` ${paint("yellow", "[quiet]")}` : ""}`);
2777
+ await postTaskUpdate(task.id, `Agent dispatched${taskIsQuiet ? " (quiet mode)" : ""} \u2014 starting work on "${task.title}"`, "system");
2762
2778
  let subtasks = [];
2763
2779
  try {
2764
2780
  subtasks = await api.get(`/api/tasks/${task.id}/subtasks`);
@@ -2824,6 +2840,7 @@ var watchCommand = new Command8("watch").description(
2824
2840
  );
2825
2841
  }
2826
2842
  const prompt2 = buildExecutionPrompt(task, repoDir, subtasks, vcs, protoRefs, feedbackUpdates, existingResources, skillRefs, executionDir, startWithoutWorktree, !startWithoutWorktree && isGitRepo(repoDir) ? branchName : void 0);
2843
+ const taskIsQuietForEntry = task.quietMode || globalQuietMode;
2827
2844
  const activeEntry = {
2828
2845
  process: void 0,
2829
2846
  title: task.title,
@@ -2831,7 +2848,9 @@ var watchCommand = new Command8("watch").description(
2831
2848
  cleanupRepoDir: cleanupWorktreePath ? repoDir : void 0,
2832
2849
  cleanupWorktreePath,
2833
2850
  startedAt: Date.now(),
2834
- lastActivityAt: Date.now()
2851
+ lastActivityAt: Date.now(),
2852
+ outputBytes: 0,
2853
+ quietMode: taskIsQuietForEntry
2835
2854
  };
2836
2855
  const touchActivity = () => {
2837
2856
  activeEntry.lastActivityAt = Date.now();
@@ -2860,7 +2879,12 @@ var watchCommand = new Command8("watch").description(
2860
2879
  const shouldResumeClaudeSession = attemptAgent === "claude" && !!task.claudeSessionId && !resumeAlreadyRetried && (hasFeedback || pausedForNetwork?.resumeSession === true);
2861
2880
  const sessionId = attemptAgent === "claude" ? shouldResumeClaudeSession ? task.claudeSessionId : randomUUID() : void 0;
2862
2881
  const effectiveClaudeModel = attemptAgent === "claude" ? taskClaudeModel : void 0;
2863
- const executionSystemPrompt = composeSystemPrompt(EXECUTION_SYSTEM_SECTIONS);
2882
+ const isQuiet = task.quietMode || globalQuietMode;
2883
+ const systemSections = isQuiet ? ["quiet-mode", ...EXECUTION_SYSTEM_SECTIONS] : [...EXECUTION_SYSTEM_SECTIONS];
2884
+ const executionSystemPrompt = composeSystemPrompt(systemSections);
2885
+ if (isQuiet) {
2886
+ logInfo(prefix, `${paint("yellow", "quiet mode")} \u2014 agent will suppress conversational output`);
2887
+ }
2864
2888
  const child = spawnAgent(
2865
2889
  attemptAgent,
2866
2890
  executionDir,
@@ -2875,7 +2899,10 @@ var watchCommand = new Command8("watch").description(
2875
2899
  },
2876
2900
  executionSystemPrompt,
2877
2901
  void 0,
2878
- effectiveClaudeModel
2902
+ effectiveClaudeModel,
2903
+ (bytes) => {
2904
+ activeEntry.outputBytes += bytes;
2905
+ }
2879
2906
  );
2880
2907
  activeEntry.process = child;
2881
2908
  activeEntry.currentAgent = attemptAgent;
@@ -2930,6 +2957,12 @@ var watchCommand = new Command8("watch").description(
2930
2957
  }
2931
2958
  }
2932
2959
  finishing.add(task.id);
2960
+ const elapsedMs = Date.now() - activeEntry.startedAt;
2961
+ const modeLabel = activeEntry.quietMode ? "quiet" : "standard";
2962
+ const outputTokenEstimate = Math.ceil(activeEntry.outputBytes / 4);
2963
+ console.log(
2964
+ `${timestamp()} ${prefix} ${paint("dim", `[output] mode=${modeLabel} output=~${formatTokenCount(outputTokenEstimate)} elapsed=${Math.round(elapsedMs / 1e3)}s exit=${code}`)}`
2965
+ );
2933
2966
  try {
2934
2967
  if (code === 0) {
2935
2968
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dunnewold-labs/mr-manager",
3
- "version": "0.4.26",
3
+ "version": "0.4.28",
4
4
  "description": "Mr. Manager - Task and project management CLI",
5
5
  "bin": {
6
6
  "mr": "./dist/index.mjs"