import { strict as assert } from "node:assert"; import { applyAgentEvent, classifyRunOutcome, newSettleState } from "./settle-policy.mjs"; const ui11Events = [ { type: "message_end", message: { stopReason: "error", errorMessage: "terminated" } }, { type: "auto_retry_start", attempt: 1, maxAttempts: 3, errorMessage: "terminated" }, { type: "message_end", message: { stopReason: "error", errorMessage: "Connection error." } }, { type: "auto_retry_start", attempt: 2, errorMessage: "Connection error." }, { type: "auto_retry_start", attempt: 3, errorMessage: "Connection error." }, { type: "auto_retry_end", success: false, attempt: 3, finalError: "Connection error." }, { type: "agent_settled" }, ]; const state = newSettleState(); for (const ev of ui11Events) { applyAgentEvent(state, ev); } assert.equal(state.succeeded, false, "agent_settled after auto_retry_end success=false is not success"); assert.equal(state.providerTransient, true); assert.equal(state.retryFailed, true); const settledFail = classifyRunOutcome({ ...state, missing: ["output.md"], lastErr: "Connection error.", }); assert.equal(settledFail.ok, false); assert.equal(settledFail.retryable, true); assert.match(settledFail.fallback_reason, /Connection error|terminated|auto_retry/i); const cleanMissing = classifyRunOutcome({ succeeded: true, retryFailed: false, providerTransient: false, lastErr: "", missing: ["output.md"], }); assert.equal(cleanMissing.ok, false); assert.equal(cleanMissing.retryable, true, "clean settle + missing target is retryable at product layer"); assert.match(cleanMissing.fallback_reason, /missing target deliverable/); const promptEmpty = classifyRunOutcome({ succeeded: false, retryFailed: false, providerTransient: false, lastErr: "prompt_empty", missing: [], }); assert.equal(promptEmpty.retryable, false); const recovered = newSettleState(); for (const ev of [ { type: "message_end", message: { stopReason: "error", errorMessage: "terminated" } }, { type: "auto_retry_start", attempt: 1, maxAttempts: 3, errorMessage: "terminated" }, { type: "auto_retry_end", success: true, attempt: 1 }, { type: "agent_settled" }, ]) { applyAgentEvent(recovered, ev); } assert.equal(recovered.retryFailed, false, "recovered SDK retry must clear retryFailed"); assert.equal(recovered.providerTransient, false, "recovered SDK retry must clear providerTransient"); assert.equal(recovered.lastErr, "", "recovered SDK retry must clear lastErr"); assert.equal(recovered.succeeded, true, "settle after recovered auto_retry must succeed"); const recoveredOk = classifyRunOutcome({ ...recovered, missing: [], }); assert.equal(recoveredOk.ok, true, "settled + target present after recovered retry is success"); assert.equal(recoveredOk.retryable, false); const recoveredThenNewError = newSettleState(); for (const ev of [ { type: "message_end", message: { stopReason: "error", errorMessage: "terminated" } }, { type: "auto_retry_end", success: true, attempt: 1 }, { type: "message_end", message: { stopReason: "error", errorMessage: "Connection error." } }, { type: "agent_settled" }, ]) { applyAgentEvent(recoveredThenNewError, ev); } assert.equal(recoveredThenNewError.succeeded, false, "a new error after recovery must not be masked"); assert.equal(recoveredThenNewError.providerTransient, true); assert.match(recoveredThenNewError.lastErr, /Connection error/i); console.log("settle-policy.test.mjs PASS");