From c308a492d71ea04328e549f0e714748527f56705 Mon Sep 17 00:00:00 2001 From: Mikael Hugo Date: Sat, 2 May 2026 21:59:38 +0200 Subject: [PATCH] chore(sf): differentiate auto-accepted vs user-resolved escalations in audit resolveEscalation gains an optional `source: "user" | "auto-mode"` parameter (default "user"). Auto-dispatch passes "auto-mode" when it auto-accepts. The UOK audit event type now flips between "escalation-user-responded" and "escalation-auto-accepted", and the payload includes a typed `resolvedBy` field. Why: a journal grep for user actions shouldn't return auto-mode events. Audit/observability tools can now filter cleanly without string-matching the rationale prefix. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/resources/extensions/sf/auto-dispatch.ts | 1 + src/resources/extensions/sf/escalation.ts | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/resources/extensions/sf/auto-dispatch.ts b/src/resources/extensions/sf/auto-dispatch.ts index f8828f459..16cfdb88a 100644 --- a/src/resources/extensions/sf/auto-dispatch.ts +++ b/src/resources/extensions/sf/auto-dispatch.ts @@ -548,6 +548,7 @@ export const DISPATCH_RULES: DispatchRule[] = [ state.activeTask.id, "accept", "auto-mode: accepted agent recommendation; user can override via /sf escalate", + "auto-mode", ); if (result.status === "resolved") { // Flags cleared; let the next dispatch cycle re-read state and diff --git a/src/resources/extensions/sf/escalation.ts b/src/resources/extensions/sf/escalation.ts index 3208ccccb..753a4c450 100644 --- a/src/resources/extensions/sf/escalation.ts +++ b/src/resources/extensions/sf/escalation.ts @@ -311,6 +311,7 @@ export function resolveEscalation( taskId: string, choice: string, rationale: string, + source: "user" | "auto-mode" = "user", ): ResolveEscalationResult { const task = getTask(milestoneId, sliceId, taskId); if (!task || !task.escalation_artifact_path) { @@ -365,13 +366,17 @@ export function resolveEscalation( buildAuditEnvelope({ traceId: `escalation:${milestoneId}:${sliceId}:${taskId}`, category: "gate", - type: "escalation-user-responded", + type: + source === "auto-mode" + ? "escalation-auto-accepted" + : "escalation-user-responded", payload: { milestoneId, sliceId, taskId, chosenOptionId: chosenOption?.id, rationale, + resolvedBy: source, }, }), );