chore: update stuck task handling and dashboard tweaks

This commit is contained in:
gsxdsm
2026-04-05 21:36:18 -07:00
parent 4de3be79ca
commit b670d8b3e3
9 changed files with 84 additions and 13 deletions

View File

@@ -736,7 +736,7 @@ export class TaskExecutor {
this.createTaskCreateTool(),
this.createTaskAddDepTool(task.id),
this.createTaskDoneTool(task.id, () => { taskDone = true; }),
this.createReviewStepTool(task.id, worktreePath, detail.prompt, codeReviewVerdicts, sessionRef, stepCheckpoints, detail),
this.createReviewStepTool(task.id, worktreePath, detail.prompt, codeReviewVerdicts, sessionRef, stepCheckpoints, detail, stuckDetector),
this.createSpawnAgentTool(task.id, worktreePath, settings),
];
@@ -1471,6 +1471,7 @@ export class TaskExecutor {
sessionRef: { current: AgentSession | null },
stepCheckpoints: Map<number, string>,
detail: TaskDetail,
stuckDetector?: StuckTaskDetector,
): ToolDefinition {
const store = this.store;
const options = this.options;
@@ -1518,6 +1519,7 @@ export class TaskExecutor {
result.summary,
);
reviewerLog.log(`${taskId}: Step ${step} ${reviewType}${result.verdict}`);
stuckDetector?.recordProgress(taskId);
// Track code review verdicts for enforcement. Plan reviews remain
// advisory — only code reviews write to the verdict map.

View File

@@ -30,7 +30,7 @@ function createMockStore(overrides: Record<string, unknown> = {}): TaskStore & E
autoUnpauseEnabled: true,
autoUnpauseBaseDelayMs: 100,
autoUnpauseMaxDelayMs: 800,
maxStuckKills: 3,
maxStuckKills: 6,
maintenanceIntervalMs: 0,
maxWorktrees: 4,
globalPause: true, // default: paused (for auto-unpause tests)
@@ -192,7 +192,7 @@ describe("SelfHealingManager", () => {
expect(store.updateTask).toHaveBeenCalledWith("FN-001", { stuckKillCount: 1 });
expect(store.logEntry).toHaveBeenCalledWith(
"FN-001",
expect.stringContaining("Stuck kill 1/3"),
expect.stringContaining("Stuck kill 1/6"),
);
});
@@ -213,7 +213,7 @@ describe("SelfHealingManager", () => {
it("returns false and marks failed when budget exceeded", async () => {
(store.getTask as ReturnType<typeof vi.fn>).mockResolvedValue({
id: "FN-001",
stuckKillCount: 3,
stuckKillCount: 6,
} as unknown as Task);
manager.start();
@@ -222,9 +222,9 @@ describe("SelfHealingManager", () => {
expect(result).toBe(false);
expect(store.updateTask).toHaveBeenCalledWith("FN-001", {
stuckKillCount: 4,
stuckKillCount: 7,
status: "failed",
error: expect.stringContaining("exceeded maximum of 3"),
error: expect.stringContaining("exceeded maximum of 6"),
});
expect(store.logEntry).toHaveBeenCalledWith(
"FN-001",

View File

@@ -188,7 +188,7 @@ export class SelfHealingManager {
async checkStuckBudget(taskId: string): Promise<boolean> {
try {
const settings = await this.store.getSettings();
const maxKills = settings.maxStuckKills ?? 3;
const maxKills = settings.maxStuckKills ?? 6;
const task = await this.store.getTask(taskId);
const newCount = (task.stuckKillCount ?? 0) + 1;