Review findings companion to docs/FlowAssist_Migration/Issues/phase-8-review-issues.md.
Documents the issues addressed by commit 24972e8 (partial-outcome notes
+ per-fix script-builder remount).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3.6 KiB
Phase 9 Review Issues
Date: 2026-04-24
Scope reviewed:
backend/app/api/endpoints/script_builder.pybackend/app/api/endpoints/session_suggested_fixes.pybackend/app/services/script_builder_service.pyfrontend/src/pages/AssistantChatPage.tsxfrontend/src/components/pilot/ScriptBuilderTab.tsxfrontend/src/components/pilot/EscalateInterceptDialog.tsx
1. "Applied partially" from the escalation intercept cannot persist
Severity: High
The escalation intercept offers an "applied partially" choice, but the frontend
sends applied_partial without notes. The backend requires notes for that
outcome and returns 400. The frontend catches the error silently and still opens
the conclude modal, so the user can believe the partial outcome was recorded
when it was not.
Relevant files:
frontend/src/pages/AssistantChatPage.tsx:659frontend/src/components/pilot/EscalateInterceptDialog.tsx:56backend/app/api/endpoints/session_suggested_fixes.py:316
Why this matters:
handleInterceptChoice()maps the partial button directly topatchOutcome(..., "applied_partial").- The call does not provide
notes. PATCH /suggested-fixes/{fix_id}/outcomerejectsapplied_partialwithout notes.- The catch block is silent and the UI continues into the conclude flow.
- The recorded fix status therefore remains unchanged while the user sees a flow that implies the partial outcome was accepted.
Recommended fix:
- Prompt for partial notes before calling
patchOutcome()withapplied_partial. - Do not proceed to the conclude modal if the partial outcome write fails.
- Consider hiding or disabling the partial option when it is not applicable, or
pass the current fix status into
EscalateInterceptDialogso it can render valid choices only. - Add a regression test covering the partial escalation-intercept path.
2. Script Builder can attach stale script state to a newer active fix
Severity: Medium/High
ScriptBuilderTab keeps local builder state across active-fix changes within
the same pilot chat. If a new active fix supersedes the previous one while the
tab remains mounted, old messages, latestScript, or editor text can remain in
memory while submission uses the new fix.id.
Relevant files:
frontend/src/components/pilot/ScriptBuilderTab.tsx:55frontend/src/components/pilot/ScriptBuilderTab.tsx:78frontend/src/components/pilot/ScriptBuilderTab.tsx:150frontend/src/pages/AssistantChatPage.tsx:399frontend/src/pages/AssistantChatPage.tsx:1630
Why this matters:
ScriptBuilderTabinitializeseditorBuffer, messages, and latest script from props and builder-session data.- The create/resume effect depends on
pilotSessionId, notfix.id. AssistantChatPagedetects active-fix changes but only closes the script panel.- The rendered
ScriptBuilderTabis not keyed by active fix id. - Submitting a stale builder draft calls the script patch endpoint with the
current
fix.id, so an older script can be attached to a newer fix.
Recommended fix:
- Reset Script Builder local state when
activeFix.idchanges. - Key the rendered
ScriptBuilderTabbyactiveFix.idif the intended UX is a fresh builder surface per fix. - If inline builder conversations are intended to resume per fix, extend the
backend idempotency model to include the fix id instead of only
(user_id, ai_session_id). - Add a frontend regression test for an active fix changing while the Script Builder tab is mounted.
Review Context
This review was based on code inspection of the latest committed Phase 9 implementation. No tracked working-tree diffs were present at review time.