import { describe, expect, it } from "vitest"; import { autonomyRetryDelayMinutes, classifyAutonomyBlocker } from "../src/services/autonomyRecovery.js"; describe("Auto Mode recovery classification", () => { it("keeps ordinary infrastructure failures retryable even when a client requests human escalation", () => { expect(classifyAutonomyBlocker("Gitea runner timed out while starting validation.", "human")).toBe("retryable"); expect(classifyAutonomyBlocker("Untrusted non-HTTPS Gitea server URL blocked security bootstrap.", "human")).toBe("retryable"); expect(classifyAutonomyBlocker("Provider returned HTTP 502 Bad Gateway.", "human")).toBe("retryable"); }); it("requires human attention only when durable evidence says a real owner action is needed", () => { expect(classifyAutonomyBlocker("Missing credential required for the production deployment.", "retryable")).toBe("human"); expect(classifyAutonomyBlocker("Owner decision is required before choosing between destructive reset and preserving production data.")).toBe("human"); expect(classifyAutonomyBlocker("Approval is required for this irreversible operation.")).toBe("human"); }); it("defaults unknown operational failures to retryable instead of creating approval chores", () => { expect(classifyAutonomyBlocker("Unexpected validation orchestration failure.", "human")).toBe("retryable"); }); it("uses bounded exponential retry delays", () => { expect(autonomyRetryDelayMinutes(1)).toBe(15); expect(autonomyRetryDelayMinutes(2)).toBe(30); expect(autonomyRetryDelayMinutes(3)).toBe(60); expect(autonomyRetryDelayMinutes(7)).toBe(960); expect(autonomyRetryDelayMinutes(100)).toBe(960); }); it.each([ "CI failed. No approval is required; repair the same branch.", "No destructive operation was performed. Runner is unavailable.", "This is not a credentials or approval requirement. Validation failed.", ])("does not mistake negated human decisions for blockers: %s", (reason) => { expect(classifyAutonomyBlocker(reason, "human")).toBe("retryable"); }); it("retains a real decision even beside negated or technical context", () => { expect(classifyAutonomyBlocker("No CI output is available, but missing credentials prevent deployment.")).toBe("human"); expect(classifyAutonomyBlocker("Runner failed. Owner authorization is required to change branch protection.")).toBe("human"); expect(classifyAutonomyBlocker("No changes were made, owner authorization is required.")).toBe("human"); expect(classifyAutonomyBlocker("This is not a CI issue and credentials are required.")).toBe("human"); }); });