fix: route denied exec approval followups to sessions

Routes denied async exec approval followups through the originating main session before using direct external fallback. Keeps strict inline-eval timeout denials fail-closed, while preserving suppression for subagent, cron, and no-session denial cases.

Refs #88167.

Verification:
- git diff --check origin/main...refs/remotes/pr/88417
- .agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main
- gh pr checks 88417 --repo openclaw/openclaw --watch=false

Co-authored-by: brokemac79 <martin_cleary@yahoo.co.uk>
This commit is contained in:
brokemac79
2026-05-30 21:45:16 +01:00
committed by GitHub
parent 48980a0f41
commit 3aa460409e
7 changed files with 113 additions and 46 deletions
+17 -5
View File
@@ -168,7 +168,7 @@ vi.mock("./bash-tools.exec-host-shared.js", () => ({
buildDefaultExecApprovalRequestArgs: vi.fn(() => ({})),
createAndRegisterDefaultExecApprovalRequest: createAndRegisterDefaultExecApprovalRequestMock,
shouldResolveExecApprovalUnavailableInline: vi.fn(() => false),
buildExecApprovalFollowupTarget: vi.fn(() => ({ approvalId: "approval-1" })),
buildExecApprovalFollowupTarget: vi.fn((value) => value),
resolveApprovalDecisionOrUndefined: resolveApprovalDecisionOrUndefinedMock,
createExecApprovalDecisionState: createExecApprovalDecisionStateMock,
enforceStrictInlineEvalApprovalBoundary: enforceStrictInlineEvalApprovalBoundaryMock,
@@ -1365,7 +1365,10 @@ describe("executeNodeHostCommand", () => {
expect(autoReviewer).not.toHaveBeenCalled();
await vi.waitFor(() => {
expect(sendExecApprovalFollowupResultMock).toHaveBeenCalledWith(
{ approvalId: "approval-1" },
expect.objectContaining({
approvalId: "approval-1",
sessionKey: "requested-session",
}),
"Exec denied (node=node-1 id=approval-1, approval-timeout): bun ./script.ts",
);
});
@@ -1638,7 +1641,10 @@ describe("executeNodeHostCommand", () => {
expect(autoReviewer).not.toHaveBeenCalled();
await vi.waitFor(() => {
expect(sendExecApprovalFollowupResultMock).toHaveBeenCalledWith(
{ approvalId: "approval-1" },
expect.objectContaining({
approvalId: "approval-1",
sessionKey: "requested-session",
}),
"Exec denied (node=node-1 id=approval-1, approval-timeout): echo 'unterminated",
);
});
@@ -1693,7 +1699,10 @@ describe("executeNodeHostCommand", () => {
expect(result.details?.status).toBe("approval-pending");
await vi.waitFor(() => {
expect(sendExecApprovalFollowupResultMock).toHaveBeenCalledWith(
{ approvalId: "approval-1" },
expect.objectContaining({
approvalId: "approval-1",
sessionKey: "requested-session",
}),
"Exec denied (node=node-1 id=approval-1, approval-timeout): bun ./script.ts",
);
});
@@ -2057,7 +2066,10 @@ describe("executeNodeHostCommand", () => {
expect(result.details?.status).toBe("approval-pending");
await vi.waitFor(() => {
expect(sendExecApprovalFollowupResultMock).toHaveBeenCalledWith(
{ approvalId: "approval-1" },
expect.objectContaining({
approvalId: "approval-1",
sessionKey: "requested-session",
}),
"Exec denied (node=node-1 id=approval-1, approval-timeout): python3 -c 'print(1)'",
);
});