Files
resolutionflow/docs/handoff/2026-04-22-flowpilot-migration.md
Michael Chihlas ec104dc8de docs(pilot): sync Phase 8 handoff with actual implementation
Correct the stale ai_sessions.fix_outcome reference (no such column) —
the real schema adds six columns to session_suggested_fixes. Update
last_commit to reflect the docs-correction tip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 19:48:54 -04:00

11 KiB

date: 2026-04-22 branch: feat/flowpilot-migration remote: ssh://gitea.resolutionflow.com/chihlasm/resolutionflow.git last_commit: a47ce07 docs(pilot): fix Phase 8 column + commit-SHA references status: Sprint 8/8 phases complete and pushed; PR not yet opened. Two open items remain (see "Open work" below); open item #2 resolved by Phase 8.

FlowPilot Migration — Session Handoff

Where the work lives

What shipped

All eight migration phases are merged onto the branch and verified against the live dev stack (resolutionflow_frontend / resolutionflow_backend / resolutionflow_postgres containers).

Phase Commit What landed
0 — baseline telemetry (pre-branch) analytics events for funnel deltas
1 — /assistant/pilot rename early commits route redirects, sidebar updates
2 — What we know (facts) (mid) session_facts table, [PROMOTE] marker, fact CRUD endpoints, WhatWeKnow section
3 — Suggested fix + Resolve preview 7ccf4c6 and prior session_suggested_fixes, [SUGGEST_FIX] marker, ResolutionNotePreview popover
4 — Escalate + PSA writeback 8fd2c1b psa_writeback_service with status verification, kind-parameterized preview
5 — inline Script Generator fa61376 TemplateMatchPanel, NoTemplateDialog three-option dialog
6 — post-resolve templatize 4aaf57a draft_templates table, accept/reject endpoints, TemplatizePrompt modal, account preferences
7 — polish 8a242f5 loading/empty states, keyboard shortcuts (⌘↵, ⌘G, ? overlay), responsive bottom-drawer <1200px
8 — Fix Outcome Banner cdd8bb0..a47ce07 Six outcome columns on session_suggested_fixes (status, applied_at, verified_at, partial_notes, failure_reason, ai_outcome_proposal) + PATCH /api/v1/ai-sessions/{sid}/suggested-fixes/{fid}/outcome endpoint + [FIX_OUTCOME] marker; replaces task-lane SuggestedFix card with a chat-composer-anchored ProposalBanner (5 states: proposed/verifying/partial/ai_confirming/nudge + collapsed); EscalateInterceptDialog captures outcome before handoff; Resolve-while-verifying auto-marks success; 17 new tests (8 endpoint + 7 marker + 2 anti-parrot)

Plus the structural fixes that came up along the way:

  • 50215b9 + d0ebdef — full sweep removing literal payloads from AI system prompts; new tests/test_prompt_anti_parrot.py guardrail
  • ce7c8ac + ddae171 — task-lane state-leak across chats (centralized resetSessionDerivedState() helper)
  • 8879f96 — dropped sticky top-0 from all four lane section headers (they were orphaning over unrelated content on scroll)

How to resume

  1. git checkout feat/flowpilot-migration
  2. docker compose -f docker-compose.dev.yml up -d (if the stack isn't running)
  3. Verify: docker exec resolutionflow_frontend sh -c "cd /app && npx tsc -b" should be clean
  4. Live URL: http://localhost:5173/pilot (or <host-ip>:5173/pilot)
  5. Test users (password TestPass123!): engineer@resolutionflow.example.com

Open work — pick one

Items #1 and #3 were discovered during Phase 6/7 verification and remain deferred. Item #2 is resolved by Phase 8. Items #1 and #3 can now be tackled in either order; #2 no longer reframes #3 since the primary fix entry point has moved to the banner.

1. NoTemplateDialog narrow-lane bug

frontend/src/components/pilot/script/NoTemplateDialog.tsx

Symptoms (live, reproducible):

  • The three-card option grid uses grid-cols-1 gap-2 sm:grid-cols-3. The sm: breakpoint is viewport-based, not container-based, so a 340px-wide lane on a 1400px viewport gets three 100px-wide cards. Text wraps every two words, the RECOMMENDED pill collides with the drafted-script box.
  • Cards appear unclickable when the AI emits [SUGGEST_FIX] without an ai_drafted_script. They render disabled because disabled={busy || !draftBody.trim()} (line 175).

Decision needed before coding: when the AI proposes a fix but doesn't draft a script, what should this dialog do? Three options were enumerated; the recommended one is (a) don't show the three-option dialog at all — show a single "Open Script Builder pre-loaded with the fix description →" CTA. The three-card UX is for evaluating an existing draft; with no draft, the choice collapses to one button.

Visual fix is mechanical regardless of which behavior is chosen: switch the grid to grid-cols-1 (always stacked) — Tailwind container queries are also an option but stacking is simpler and the lane is too narrow for three columns at any container width.

Note: After Phase 8, this dialog is only reached after the engineer interacts with the ProposalBanner at the bottom of the chat column. The narrow-lane problem is less prominent than before, but the disabled-cards bug (when no ai_drafted_script is present) still needs a decision before the dialog is usable without a draft.

2. Task lane crowding / Suggested Fix discoverability

Status: RESOLVED by Phase 8. The SuggestedFix card no longer lives inside the scrollable task lane. Phase 8 replaced it with a chat-composer-anchored slide-up banner (ProposalBanner) that is always visible at the bottom of the conversation column regardless of how far the task lane has scrolled. The banner is the primary entry point for fix application; the task lane retains a compact read-only summary of the active fix for reference.

See docs/FlowAssist_Migration/phase-8-fix-outcome-banner.md for the implementation plan and design rationale. Because the banner is now the primary entry point, the NoTemplateDialog narrow-lane bug (open item #1) is considerably less visible — the three-option dialog is only reached after the engineer opts in via the banner, at which point they have already acknowledged the fix.

3. Tabbed Script Builder inside the chat (Option A from the modal-vs-tab discussion)

Status: agreed in concept, schema + plan drafted, no code written yet.

When the AI proposes a fix without a drafted script, give the engineer two paths inside a tabbed interface (the chat region gets a [Chat] [Script Builder ●] tab strip):

Either path persists the script to session_suggested_fixes.ai_drafted_script on the backend. Modal closes, NoTemplateDialog re-renders with draftBody populated, the three-card decision unlocks normally.

Schema additions agreed (not yet migrated):

ALTER TABLE script_builder_sessions
  ADD COLUMN origin VARCHAR(20) NOT NULL DEFAULT 'standalone',  -- 'standalone' | 'pilot_inline'
  ADD COLUMN parent_pilot_session_id UUID NULL REFERENCES ai_sessions(id) ON DELETE SET NULL;

Both nullable-default so existing rows stay valid. origin enables future split-quota billing (decided to count as one billable session for now, but tagged for analytics). parent_pilot_session_id enables the "Resume script generation →" link on the suggested-fix card when the engineer closes the tab mid-build.

UX placement decision: tabbed within the chat region. User explicitly rejected modal-on-top and side-by-side because both context-switch the engineer away from the chat. Tabs use display: none toggling (not unmount) so chat scroll position, draft message, and history stay exactly preserved.

Lift items:

  • Extract <ScriptBuilderChat> into a mode: 'standalone' | 'ephemeral' prop — ephemeral mode returns the script to the caller instead of saving a script_templates row.
  • New backend endpoint: PATCH /sessions/{sid}/suggested-fixes/{id}/script (writes ai_drafted_script + ai_drafted_parameters).
  • Tab strip UI in the chat region (new affordance — biggest visual delta).
  • Migration for the two new columns.

Estimated half a day end-to-end.

Loose ends / things to verify on resume

  • PR not opened. Branch is pushed but no Gitea PR yet. When ready: gh pr create works against the GitHub mirror, but the actual review happens in Gitea.
  • /ultrareview not run on the final state of the branch. Worth doing before PR creation.
  • Phase 8 browser QA not done. The new ProposalBanner and EscalateInterceptDialog have not been exercised in a headless-browser session. Key states to cover: banner appears on [FIX_OUTCOME] marker; banner dismisses correctly; escalate mid-fix triggers EscalateInterceptDialog; banner auto-collapses after session resolved. Use /qa or /design-review against mockups/06-slide-up-banner.html and mockups/07-verify-states.html.
  • Phase 7 visual verification was structural onlytsc -b and npm run build both clean, HMR applied each change without error, but no headless-browser screenshot comparison against the mockup PNGs. If you want pixel-level verification, /qa or /design-review would catch deltas.
  • Anti-parrot test runs as part of pytest but is not enforced in any specific CI step yet — verify tests/test_prompt_anti_parrot.py is discovered by the existing pytest run, and consider failing CI explicitly on regression.

Files most likely to need attention next