@dunnewold-labs/mr-manager 0.2.0 → 0.3.0

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 +42 -41
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -255,11 +255,9 @@ var tasksCommand = new Command5("tasks").description("List tasks for the linked
255
255
  const params = new URLSearchParams();
256
256
  params.set("projectId", projectId);
257
257
  if (opts.inProgress) {
258
- params.set("inProgress", "true");
258
+ params.set("status", "in_progress");
259
259
  } else if (opts.completed) {
260
- params.set("completed", "true");
261
- } else if (!opts.all) {
262
- params.set("completed", "false");
260
+ params.set("status", "completed");
263
261
  }
264
262
  path += `?${params.toString()}`;
265
263
  const tasks = await api.get(path);
@@ -409,9 +407,9 @@ var contextCommand = new Command7("context").description("Output project context
409
407
  const allTasks = await api.get(
410
408
  `/api/projects/${projectId}/tasks`
411
409
  );
412
- const inProgress = allTasks.filter((t) => t.inProgress && !t.completed);
413
- const todo = allTasks.filter((t) => !t.completed && !t.inProgress);
414
- const recentlyCompleted = allTasks.filter((t) => t.completed).slice(0, 10);
410
+ const inProgress = allTasks.filter((t) => t.status === "in_progress" || t.status === "queued" || t.status === "delegated" || t.status === "review");
411
+ const todo = allTasks.filter((t) => t.status === "todo");
412
+ const recentlyCompleted = allTasks.filter((t) => t.status === "completed").slice(0, 10);
415
413
  const summaryLines = [
416
414
  `Project: ${project.name} (${project.status})`,
417
415
  ...inProgress.map((t) => `In Progress: ${t.title}`),
@@ -2068,8 +2066,7 @@ var watchCommand = new Command8("watch").description(
2068
2066
  }
2069
2067
  }
2070
2068
  await api.patch(`/api/tasks/${task.id}`, {
2071
- inProgress: false,
2072
- readyForReview: true,
2069
+ status: "review",
2073
2070
  ...prUrl ? { link: prUrl } : {}
2074
2071
  });
2075
2072
  logSuccess(prefix, `"${paint("bold", task.title)}" marked ready for review`);
@@ -2170,8 +2167,7 @@ var watchCommand = new Command8("watch").description(
2170
2167
  }
2171
2168
  }
2172
2169
  await api.patch(`/api/tasks/${task.id}`, {
2173
- inProgress: false,
2174
- readyForReview: true,
2170
+ status: "review",
2175
2171
  ...prdContent ? { prdContent } : {}
2176
2172
  });
2177
2173
  logSuccess(prefix, `"${paint("bold", task.title)}" PRD generated and marked ready for review`);
@@ -2447,20 +2443,24 @@ ${divider}`);
2447
2443
  }
2448
2444
  }
2449
2445
  async function poll() {
2450
- let tasks;
2446
+ let queuedTasks;
2447
+ let delegatedTasks;
2451
2448
  try {
2452
- const allInProgress = await api.get("/api/tasks?inProgress=true");
2453
- tasks = allInProgress.filter((t) => t.delegated || t.planMode);
2449
+ queuedTasks = await api.get("/api/tasks?status=queued");
2450
+ delegatedTasks = await api.get("/api/tasks?status=delegated");
2454
2451
  } catch (err) {
2455
2452
  logError(watchTag(), `Failed to fetch tasks: ${err.message}`);
2456
2453
  return;
2457
2454
  }
2455
+ const nonTestQueued = queuedTasks.filter((t) => t.mode !== "testing");
2456
+ const nonTestDelegated = delegatedTasks.filter((t) => t.mode !== "testing");
2457
+ const tasks = [...nonTestQueued, ...nonTestDelegated];
2458
2458
  const config = loadConfig();
2459
- const inProgressIds = new Set(tasks.map((t) => t.id));
2459
+ const activeTaskIds = new Set(tasks.map((t) => t.id));
2460
2460
  for (const [taskId, entry] of active) {
2461
2461
  if (taskId.startsWith("proto-") || taskId.startsWith("repo-") || taskId.startsWith("scan-")) continue;
2462
- if (!inProgressIds.has(taskId)) {
2463
- logWarn(watchTag(), `Task ${paint("yellow", taskId.slice(0, 8))} no longer in-progress, terminating\u2026`);
2462
+ if (!activeTaskIds.has(taskId)) {
2463
+ logWarn(watchTag(), `Task ${paint("yellow", taskId.slice(0, 8))} no longer active, terminating\u2026`);
2464
2464
  entry.process.kill("SIGTERM");
2465
2465
  active.delete(taskId);
2466
2466
  queued.delete(taskId);
@@ -2469,11 +2469,11 @@ ${divider}`);
2469
2469
  const nonTaskPrefixes = ["proto-", "repo-", "scan-", "idea-", "test-"];
2470
2470
  for (const taskId of failed.keys()) {
2471
2471
  if (nonTaskPrefixes.some((p) => taskId.startsWith(p))) continue;
2472
- if (!inProgressIds.has(taskId)) failed.delete(taskId);
2472
+ if (!activeTaskIds.has(taskId)) failed.delete(taskId);
2473
2473
  }
2474
2474
  for (const taskId of queued) {
2475
2475
  if (nonTaskPrefixes.some((p) => taskId.startsWith(p))) continue;
2476
- if (!inProgressIds.has(taskId)) queued.delete(taskId);
2476
+ if (!activeTaskIds.has(taskId)) queued.delete(taskId);
2477
2477
  }
2478
2478
  for (const task of tasks) {
2479
2479
  if (queued.has(task.id)) continue;
@@ -2493,6 +2493,14 @@ ${divider}`);
2493
2493
  failed.set(task.id, reason);
2494
2494
  continue;
2495
2495
  }
2496
+ if (task.status === "queued") {
2497
+ try {
2498
+ await api.patch(`/api/tasks/${task.id}`, { status: "delegated" });
2499
+ } catch (err) {
2500
+ logError(prefix, `Failed to mark task as delegated: ${err.message}`);
2501
+ continue;
2502
+ }
2503
+ }
2496
2504
  queued.add(task.id);
2497
2505
  if (dryRun) {
2498
2506
  logInfo(
@@ -2501,7 +2509,7 @@ ${divider}`);
2501
2509
  );
2502
2510
  continue;
2503
2511
  }
2504
- if (task.planMode) {
2512
+ if (task.mode === "planning") {
2505
2513
  dispatchPlanModeTask(task, repoDir);
2506
2514
  } else if (planApproval) {
2507
2515
  approvalQueue.push({ task, repoDir });
@@ -2565,12 +2573,7 @@ ${divider}`);
2565
2573
  }
2566
2574
  dispatchPrototypeJob(proto, repoDir);
2567
2575
  }
2568
- let testTasks = [];
2569
- try {
2570
- testTasks = await api.get("/api/tasks?testStatus=pending");
2571
- } catch (err) {
2572
- logError(watchTag(), `Failed to fetch test tasks: ${err.message}`);
2573
- }
2576
+ const testTasks = queuedTasks.filter((t) => t.mode === "testing");
2574
2577
  for (const task of testTasks) {
2575
2578
  const key = `test-${task.id}`;
2576
2579
  if (queued.has(key)) continue;
@@ -2592,7 +2595,7 @@ ${divider}`);
2592
2595
  (async () => {
2593
2596
  logDispatch(prefix, `Running test for "${paint("bold", task.title)}"\u2026`);
2594
2597
  try {
2595
- await api.patch(`/api/tasks/${task.id}`, { testStatus: "running" });
2598
+ await api.patch(`/api/tasks/${task.id}`, { status: "delegated" });
2596
2599
  await postTaskUpdate(task.id, "Test started \u2014 setting up environment\u2026");
2597
2600
  let localPath;
2598
2601
  try {
@@ -2655,12 +2658,12 @@ ${divider}`);
2655
2658
  },
2656
2659
  onProgress: (msg) => logInfo(prefix, msg)
2657
2660
  });
2658
- await api.patch(`/api/tasks/${task.id}`, { testStatus: result.status });
2661
+ await api.patch(`/api/tasks/${task.id}`, { status: "completed", testResult: result.status });
2659
2662
  logSuccess(prefix, result.summary);
2660
2663
  } catch (err) {
2661
2664
  logError(prefix, `Test failed: ${err.message}`);
2662
2665
  try {
2663
- await api.patch(`/api/tasks/${task.id}`, { testStatus: "failed" });
2666
+ await api.patch(`/api/tasks/${task.id}`, { status: "completed", testResult: "failed" });
2664
2667
  await postTaskUpdate(task.id, `Test failed: ${err.message}`);
2665
2668
  } catch {
2666
2669
  }
@@ -2859,21 +2862,20 @@ function printTaskBanner(action, title, id) {
2859
2862
  }
2860
2863
  var startCommand = new Command9("start").description("Mark a task as in-progress (you are working on it)").argument("<task-id>", "Task ID to start").action(async (taskId) => {
2861
2864
  const task = await api.patch(`/api/tasks/${taskId}`, {
2862
- inProgress: true,
2863
- delegated: false
2865
+ status: "in_progress"
2864
2866
  });
2865
2867
  printTaskBanner(paint2("green", "start"), task.title, task.id);
2866
2868
  });
2867
- var delegateCommand = new Command9("delegate").description("Mark a task as in-progress and delegate it to the watch agent").argument("<task-id>", "Task ID to delegate").action(async (taskId) => {
2869
+ var delegateCommand = new Command9("delegate").description("Queue a task for the watch agent to pick up").argument("<task-id>", "Task ID to delegate").action(async (taskId) => {
2868
2870
  const task = await api.patch(`/api/tasks/${taskId}`, {
2869
- inProgress: true,
2870
- delegated: true
2871
+ status: "queued"
2871
2872
  });
2872
2873
  printTaskBanner(paint2("cyan", "delegate"), task.title, task.id);
2873
2874
  });
2874
- var undelegateCommand = new Command9("undelegate").description("Remove delegation from a task (keep it in-progress)").argument("<task-id>", "Task ID to undelegate").action(async (taskId) => {
2875
+ var undelegateCommand = new Command9("undelegate").description("Remove delegation from a task and return to todo").argument("<task-id>", "Task ID to undelegate").action(async (taskId) => {
2875
2876
  const task = await api.patch(`/api/tasks/${taskId}`, {
2876
- delegated: false
2877
+ status: "todo",
2878
+ mode: "development"
2877
2879
  });
2878
2880
  printTaskBanner(paint2("yellow", "undelegate"), task.title, task.id);
2879
2881
  });
@@ -2892,7 +2894,7 @@ var createCommand = new Command10("create").description("Create a new task in th
2892
2894
  title,
2893
2895
  projectId,
2894
2896
  notes: opts.notes,
2895
- inProgress: opts.inProgress ?? false
2897
+ status: opts.inProgress ? "in_progress" : "todo"
2896
2898
  });
2897
2899
  const t = task;
2898
2900
  console.log(`Created: ${t.title} (${t.id})`);
@@ -2927,8 +2929,7 @@ function printTaskBanner2(action, title, id) {
2927
2929
  }
2928
2930
  var completeCommand = new Command11("complete").description("Mark a task as completed").argument("<task-id>", "Task ID to complete").action(async (taskId) => {
2929
2931
  const task = await api.patch(`/api/tasks/${taskId}`, {
2930
- completed: true,
2931
- inProgress: false
2932
+ status: "completed"
2932
2933
  });
2933
2934
  printTaskBanner2(paint3("green", "complete \u2713"), task.title, task.id);
2934
2935
  });
@@ -3863,7 +3864,7 @@ var resumeCommand = new Command19("resume").description("Resume an interactive C
3863
3864
  );
3864
3865
  process.exit(1);
3865
3866
  }
3866
- if (task.completed || !task.inProgress && !task.delegated) {
3867
+ if (task.status === "completed" || task.status === "todo") {
3867
3868
  console.error(
3868
3869
  `
3869
3870
  ${paint8("yellow", "\u26A0")} Task ${paint8("dim", taskId.slice(0, 8))} has already completed.`
@@ -4316,7 +4317,7 @@ var mobileCommand = new Command25("mobile").description(
4316
4317
  const task = await api.post("/api/tasks", {
4317
4318
  title: "Convert to Mobile App",
4318
4319
  projectId,
4319
- inProgress: true
4320
+ status: "in_progress"
4320
4321
  });
4321
4322
  console.log(` Created task: ${task.title} (${task.id})`);
4322
4323
  console.log(" Analyzing web app...");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dunnewold-labs/mr-manager",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Mr. Manager - Task and project management CLI",
5
5
  "bin": {
6
6
  "mr": "./dist/index.mjs"