fix(cron): keep recovered tool warnings diagnostic

This commit is contained in:
clawsweeper
2026-05-20 01:09:34 +00:00
parent a9476bfc7c
commit 8b8a36e912
2 changed files with 4 additions and 52 deletions

View File

@@ -1,32 +1,6 @@
import { describe, expect, it } from "vitest";
import { setReplyPayloadMetadata } from "../auto-reply/reply-payload.js";
import { detectCronDenialToken, resolveCronPayloadOutcome } from "./isolated-agent/helpers.js";
describe("detectCronDenialToken", () => {
it("matches host denial markers case-sensitively", () => {
expect(detectCronDenialToken("SYSTEM_RUN_DENIED: approval blocked")).toBe("SYSTEM_RUN_DENIED");
expect(detectCronDenialToken("INVALID_REQUEST: denied")).toBe("INVALID_REQUEST");
expect(detectCronDenialToken("system_run_denied: approval blocked")).toBeUndefined();
expect(detectCronDenialToken("invalid_request: denied")).toBeUndefined();
});
it("matches model-narrated denial phrases case-insensitively", () => {
expect(detectCronDenialToken("Approval Cannot Safely Bind this runtime command")).toBe(
"approval cannot safely bind",
);
expect(detectCronDenialToken("The runtime denied the operation.")).toBe("runtime denied");
expect(detectCronDenialToken("I could not run the script.")).toBe("could not run");
expect(detectCronDenialToken("The command did not run to completion.")).toBe("did not run");
expect(detectCronDenialToken("The request was denied by policy.")).toBe("was denied");
});
it("ignores empty and non-token text", () => {
expect(detectCronDenialToken(undefined)).toBeUndefined();
expect(
detectCronDenialToken("The denied claim was reviewed, then the job succeeded."),
).toBeUndefined();
});
});
import { resolveCronPayloadOutcome } from "./isolated-agent/helpers.js";
describe("resolveCronPayloadOutcome", () => {
it("uses the last non-empty non-error payload as summary and output", () => {

View File

@@ -293,35 +293,15 @@ export function resolveCronPayloadOutcome(params: {
: synthesizedText
? [{ text: synthesizedText }]
: [];
const denialSignal = resolveCronDenialSignal([
{ field: "summary", text: summary },
{ field: "outputText", text: outputText },
{ field: "synthesizedText", text: synthesizedText },
{ field: "fallbackSummary", text: fallbackSummary },
{ field: "fallbackOutputText", text: fallbackOutputText },
...params.payloads
.map((payload, index) => ({ payload, index }))
.filter(({ payload }) => !isNonTerminalToolErrorWarning(payload))
.map(({ payload, index }) => ({
field: `payloads[${index}].text`,
text: payload?.text,
})),
]);
const failureSignal = normalizeCronFailureSignal(params.failureSignal);
const runLevelError = formatCronRunLevelError(params.runLevelError);
const hasFatalErrorPayload =
hasFatalStructuredErrorPayload ||
failureSignal !== undefined ||
denialSignal !== undefined ||
runLevelError !== undefined;
hasFatalStructuredErrorPayload || failureSignal !== undefined || runLevelError !== undefined;
const structuredErrorText = hasFatalStructuredErrorPayload
? (lastErrorPayloadText ?? "cron isolated run returned an error payload")
: undefined;
const shouldUseRunLevelErrorPayload =
runLevelError !== undefined &&
structuredErrorText === undefined &&
failureSignal === undefined &&
denialSignal === undefined;
runLevelError !== undefined && structuredErrorText === undefined && failureSignal === undefined;
const fatalDeliveryText =
structuredErrorText ??
failureSignal?.message ??
@@ -343,9 +323,7 @@ export function resolveCronPayloadOutcome(params: {
? structuredErrorText
: failureSignal
? formatCronFailureSignal(failureSignal)
: denialSignal
? formatCronDenialSignal(denialSignal)
: runLevelError,
: runLevelError,
pendingPresentationWarningError: hasPendingPresentationWarning
? lastErrorPayloadText
: undefined,