test(FN-4890): cover board-stall verification and cooldown
Fusion-Task-Id: FN-4890 Fusion-Task-Lineage: d1ae6585-7df0-481f-83c3-c7cdd45daf4f
This commit is contained in:
committed by
gsxdsm
parent
dfeb379a14
commit
5f6dddf863
@@ -84,4 +84,39 @@ describe("reliability interactions: board stall auto-recovery", () => {
|
||||
expect(audits).toContain("task:auto-board-stall-unrecovered");
|
||||
expect(notify).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("skips unrecovered notification when progress resumes", async () => {
|
||||
const holder = makeTask("FN-10", { column: "in-progress", paused: true, pausedReason: "waiting" });
|
||||
const { store, byId } = makeStore([holder]);
|
||||
const notify = vi.fn(async () => undefined);
|
||||
const manager = new SelfHealingManager(store, { rootDir: process.cwd(), getExecutingTaskIds: () => new Set(), ntfyNotifier: { notifyBoardStallUnrecovered: notify } });
|
||||
|
||||
await manager.runBoardStallAutoRecoverySweep();
|
||||
byId.set("FN-11", makeTask("FN-11", { column: "todo", blockedBy: "FN-10" }));
|
||||
await manager.runBoardStallAutoRecoverySweep();
|
||||
(manager as any).boardStallWindow.transitionsOutOfInProgressInWindow = 1;
|
||||
(manager as any).maintenanceTickCounter++;
|
||||
const verification = await manager.runBoardStallAutoRecoverySweep();
|
||||
expect(verification.unrecovered).toBe(false);
|
||||
expect(notify).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("enforces cooldown for repeated unrecovered alerts", async () => {
|
||||
const holder = makeTask("FN-20", { column: "in-progress", paused: true, pausedReason: "waiting" });
|
||||
const { store, byId } = makeStore([holder]);
|
||||
const notify = vi.fn(async () => undefined);
|
||||
const manager = new SelfHealingManager(store, { rootDir: process.cwd(), getExecutingTaskIds: () => new Set(), ntfyNotifier: { notifyBoardStallUnrecovered: notify } });
|
||||
|
||||
await manager.runBoardStallAutoRecoverySweep();
|
||||
byId.set("FN-21", makeTask("FN-21", { column: "todo", blockedBy: "FN-20" }));
|
||||
await manager.runBoardStallAutoRecoverySweep();
|
||||
(manager as any).maintenanceTickCounter++;
|
||||
await manager.runBoardStallAutoRecoverySweep();
|
||||
|
||||
(manager as any).boardStallWindow.pendingVerification = { holderIds: ["FN-20"], followerCount: 1, startedAt: Date.now(), tick: 0 };
|
||||
(manager as any).maintenanceTickCounter++;
|
||||
await manager.runBoardStallAutoRecoverySweep();
|
||||
|
||||
expect(notify).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2582,7 +2582,7 @@ export class SelfHealingManager {
|
||||
if (window.pendingVerification && this.maintenanceTickCounter > window.pendingVerification.tick) {
|
||||
const noProgress = window.transitionsOutOfInProgressInWindow === 0;
|
||||
if (noProgress) {
|
||||
const ntfyAllowed = window.lastNtfyAt === null || now - window.lastNtfyAt >= 15 * 60_000;
|
||||
const ntfyAllowed = window.lastNtfyAt === null || now - window.lastNtfyAt >= BOARD_STALL_NOTIFICATION_COOLDOWN_MS;
|
||||
let ntfyDispatched = false;
|
||||
if (ntfyAllowed) {
|
||||
try {
|
||||
@@ -2594,7 +2594,6 @@ export class SelfHealingManager {
|
||||
window.lastNtfyAt = now;
|
||||
ntfyDispatched = true;
|
||||
} else {
|
||||
const settings = await this.store.getSettings();
|
||||
const enabled = Boolean(settings.ntfyEnabled && settings.ntfyTopic);
|
||||
const events = resolveNtfyEvents(settings.ntfyEvents);
|
||||
if (enabled && isNtfyEventEnabled(events, "board-stall-unrecovered")) {
|
||||
|
||||
Reference in New Issue
Block a user