@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.
- package/dist/index.mjs +42 -41
- 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("
|
|
258
|
+
params.set("status", "in_progress");
|
|
259
259
|
} else if (opts.completed) {
|
|
260
|
-
params.set("
|
|
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.
|
|
413
|
-
const todo = allTasks.filter((t) =>
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
2446
|
+
let queuedTasks;
|
|
2447
|
+
let delegatedTasks;
|
|
2451
2448
|
try {
|
|
2452
|
-
|
|
2453
|
-
|
|
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
|
|
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 (!
|
|
2463
|
-
logWarn(watchTag(), `Task ${paint("yellow", taskId.slice(0, 8))} no longer
|
|
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 (!
|
|
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 (!
|
|
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.
|
|
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
|
-
|
|
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}`, {
|
|
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}`, {
|
|
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}`, {
|
|
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
|
-
|
|
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("
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 ||
|
|
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
|
-
|
|
4320
|
+
status: "in_progress"
|
|
4320
4321
|
});
|
|
4321
4322
|
console.log(` Created task: ${task.title} (${task.id})`);
|
|
4322
4323
|
console.log(" Analyzing web app...");
|