docs(pilot): Phase 8 fix outcome banner — handoff + migration spec
Marks open item #2 (task-lane crowding / Suggested Fix discoverability) as resolved by Phase 8. Open items #1 (NoTemplateDialog narrow-lane) and #3 (Tabbed Script Builder inside chat) remain deferred. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
|
||||
> **Target:** Transform `/assistant` (ResolutionAssist) into the new unified `/pilot` (FlowPilot) surface.
|
||||
> **Audience:** Claude Code (implementation) and Codex (review) reviewed by Michael (owner).
|
||||
> **Status:** Phases 0–7 implemented. Phase 7 delivered polish: fact-synthesis loading indicator in `WhatWeKnow`, "thinking" pip in the task-lane header, quiet-state hint when questions/checks/fix are all absent, keyboard shortcuts (`⌘K` palette already present, `⌘↵` send, `⌘G` toggle script panel, `?` help overlay), and responsive bottom-drawer lane on viewports <1200px with a floating "Tasks" toggle. `tsc -b` and `npm run build` both clean.
|
||||
> **Last updated:** April 22, 2026 (Phase 6 — post-resolve TemplatizePrompt — committed; draft accept → script_templates promotion with provenance verified live)
|
||||
> **Status:** Phases 0–8 implemented. Phase 8 replaced the task-lane `SuggestedFix` card CTA with a chat-composer-anchored `ProposalBanner`, added `ai_sessions.fix_outcome` column, `PATCH /outcome` endpoint, `[FIX_OUTCOME]` marker, and `EscalateInterceptDialog`. `tsc -b` and `npm run build` both clean.
|
||||
> **Last updated:** April 23, 2026 (Phase 8 — Fix Outcome Banner — committed; handoff and migration spec updated)
|
||||
|
||||
---
|
||||
|
||||
@@ -891,6 +891,29 @@ git commit -m "feat(pilot): add post-resolve templatize prompt for draft templat
|
||||
git commit -m "feat(pilot): visual polish, empty/loading states, keyboard shortcuts"
|
||||
```
|
||||
|
||||
### Phase 8 — Fix Outcome Banner
|
||||
|
||||
**Plan and rationale:** [phase-8-fix-outcome-banner.md](phase-8-fix-outcome-banner.md)
|
||||
|
||||
**Mockups:** [mockups/06-slide-up-banner.html](mockups/06-slide-up-banner.html), [mockups/07-verify-states.html](mockups/07-verify-states.html)
|
||||
|
||||
**What this phase does:** Removes the `SuggestedFix` card as the primary interaction point for fix application. Replaces it with a chat-composer-anchored slide-up banner (`ProposalBanner`) that stays visible at the bottom of the conversation column regardless of task-lane scroll depth. Addresses the user-reported discoverability problem: *"the task lane fills up pretty quick … the suggested fix … is easily missed."*
|
||||
|
||||
**Key backend additions:**
|
||||
- `ai_sessions.fix_outcome` VARCHAR column (values: `null` / `accepted` / `dismissed` / `escalated`)
|
||||
- `PATCH /api/v1/ai-sessions/{id}/outcome` endpoint to record the engineer's decision
|
||||
- `[FIX_OUTCOME]` marker in the FlowPilot system prompt, parsed by `unified_chat_service.py` to trigger the banner
|
||||
|
||||
**Key frontend additions:**
|
||||
- `ProposalBanner` component (`frontend/src/components/pilot/ProposalBanner.tsx`) — slide-up banner anchored above the chat composer; shows fix title, confidence, and Accept / Dismiss / Escalate actions; auto-collapses after session resolves
|
||||
- `EscalateInterceptDialog` — intercepts the Escalate action when a fix proposal is active, asking whether the engineer wants to note that the fix was attempted before escalating
|
||||
|
||||
**Commit range:** `6721b84` (Phase 8 Task 1 start) through `8582d24`
|
||||
|
||||
```
|
||||
git commit -m "feat(pilot): Phase 8 — fix outcome banner replaces task-lane SuggestedFix CTA"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Design system reference
|
||||
|
||||
111
docs/handoff/2026-04-22-flowpilot-migration.md
Normal file
111
docs/handoff/2026-04-22-flowpilot-migration.md
Normal file
@@ -0,0 +1,111 @@
|
||||
---
|
||||
date: 2026-04-22
|
||||
branch: feat/flowpilot-migration
|
||||
remote: ssh://gitea.resolutionflow.com/chihlasm/resolutionflow.git
|
||||
last_commit: 8582d24 docs(pilot): Phase 8 fix outcome banner — handoff + migration spec
|
||||
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
|
||||
|
||||
- Branch: `feat/flowpilot-migration` (pushed to Gitea, mirrors to GitHub)
|
||||
- Spec: [docs/FlowAssist_Migration/FLOWPILOT-MIGRATION.md](../FlowAssist_Migration/FLOWPILOT-MIGRATION.md)
|
||||
- Mockups: [docs/FlowAssist_Migration/mockups/](../FlowAssist_Migration/mockups/) (PNG + HTML reference)
|
||||
|
||||
## 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 | `8582d24` | `ai_sessions.fix_outcome` column + `PATCH /outcome` endpoint + `[FIX_OUTCOME]` marker; replaces task-lane `SuggestedFix` card CTA with a chat-composer-anchored slide-up banner (`ProposalBanner`); `EscalateInterceptDialog` for mid-fix escalation; banner dismissible and auto-collapsed after resolution |
|
||||
|
||||
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](../../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](../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):
|
||||
|
||||
- **Write it myself** → modal/tab with a Monaco/textarea editor pre-loaded with the fix description as a comment.
|
||||
- **Generate with AI** → embed `ScriptBuilderChat` (already extracted from `ScriptBuilderPage`, lives at [frontend/src/components/script-builder/ScriptBuilderChat.tsx](../../frontend/src/components/script-builder/ScriptBuilderChat.tsx)).
|
||||
|
||||
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):**
|
||||
|
||||
```sql
|
||||
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 only** — `tsc -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
|
||||
|
||||
- [frontend/src/pages/AssistantChatPage.tsx](../../frontend/src/pages/AssistantChatPage.tsx) — 1500+ lines, the central pilot orchestrator. Most state-leak and rendering bugs surface here first. Search for `resetSessionDerivedState` to see the chat-switch reset pattern.
|
||||
- [frontend/src/components/assistant/TaskLane.tsx](../../frontend/src/components/assistant/TaskLane.tsx) — accepts `whatWeKnowSlot` / `suggestedFixSlot` / `bottomSlot` from the parent, plus a `variant: 'side' | 'drawer'` for responsive.
|
||||
- [backend/app/services/unified_chat_service.py](../../backend/app/services/unified_chat_service.py) — owns marker parsing for `[PROMOTE]`, `[SUGGEST_FIX]`, `[QUESTIONS]`, `[ACTIONS]`, `[FORK]`, `[TREE_UPDATE]`. If markers stop firing in chat, this is the first place to check.
|
||||
- [backend/app/services/assistant_chat_service.py](../../backend/app/services/assistant_chat_service.py) — `ASSISTANT_SYSTEM_PROMPT` constant. Anti-parrot test enforces no literal payloads here; use `<placeholder>` syntax only.
|
||||
Reference in New Issue
Block a user