From 24972e8444f698b82eec338a6a8d6c9dc2d6fb37 Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Fri, 24 Apr 2026 11:08:00 -0400 Subject: [PATCH] =?UTF-8?q?fix(pilot):=20Phase=209=20review=20=E2=80=94=20?= =?UTF-8?q?partial-outcome=20notes=20+=20per-fix=20script-builder=20remoun?= =?UTF-8?q?t?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses docs/FlowAssist_Migration/Issues/phase-9-review-issues.md. Issue #1 (High): "Applied partially" from the escalation intercept silently dropped because the backend requires notes on applied_partial and the dialog sent none. The catch was silent and the UI advanced into the conclude flow as if the outcome were recorded. - EscalateInterceptDialog now has a two-step flow: clicking the partial choice reveals a notes textarea (autofocused, required non-empty) plus Back / "Record partial & escalate" buttons. - onChoose signature extended to (choice, notes?). - handleInterceptChoice passes notes to patchOutcome; on failure it surfaces a toast and does NOT advance to the conclude modal, so the intercept stays open for retry. Issue #2 (Medium/High): ScriptBuilderTab kept local state across active-fix changes within the same pilot session, so a stale draft could PATCH against a newer fix.id. Added key={activeFix.id} on the mount — forces a clean remount per fix; backend get-or-create (keyed on user+ai_session_id) still returns the same session row, which is the intended resume-on-refresh semantic; but messages/editorBuffer/latestScript local state resets. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../pilot/EscalateInterceptDialog.tsx | 128 ++++++++++++------ frontend/src/pages/AssistantChatPage.tsx | 31 ++++- 2 files changed, 113 insertions(+), 46 deletions(-) diff --git a/frontend/src/components/pilot/EscalateInterceptDialog.tsx b/frontend/src/components/pilot/EscalateInterceptDialog.tsx index 4163c407..bb9b9f34 100644 --- a/frontend/src/components/pilot/EscalateInterceptDialog.tsx +++ b/frontend/src/components/pilot/EscalateInterceptDialog.tsx @@ -8,14 +8,16 @@ * Visual reference: docs/FlowAssist_Migration/mockups/07-verify-states.html * (panel C). */ +import { useState } from 'react' import { X, AlertCircle, Check, Info } from 'lucide-react' +import { cn } from '@/lib/utils' import type { FixOutcome } from '@/api/sessionSuggestedFixes' export type InterceptChoice = FixOutcome | 'never_applied' export interface EscalateInterceptDialogProps { fixTitle: string - onChoose: (choice: InterceptChoice) => void + onChoose: (choice: InterceptChoice, notes?: string) => void onClose: () => void } @@ -24,6 +26,11 @@ export function EscalateInterceptDialog({ onChoose, onClose, }: EscalateInterceptDialogProps) { + const [partialStep, setPartialStep] = useState(false) + const [partialNotes, setPartialNotes] = useState('') + + const notesValid = partialNotes.trim().length > 0 + return ( <>
-
- Before escalating — what happened with the fix? -
-
- “{fixTitle}” is still in the Verifying state. Tag its outcome so - the senior picking this up knows what's been tried. -
-
- - - - -
+ {!partialStep ? ( + <> +
+ Before escalating — what happened with the fix? +
+
+ “{fixTitle}” is still in the Verifying state. Tag its outcome so + the senior picking this up knows what's been tried. +
+
+ + + + +
+ + ) : ( + <> +
+ What partially worked? +
+
+ A short note for whoever picks this up — what you tried, what worked, what's still broken. +
+