From 65a831bf9af50795520cd2c16b5440eceea2e7f2 Mon Sep 17 00:00:00 2001 From: Michael Chihlas Date: Fri, 24 Apr 2026 06:14:41 -0400 Subject: [PATCH] docs(pilot): Phase 9 handoff + migration spec update Marks open items #1 (NoTemplateDialog narrow-lane) and #3 (Tabbed Script Builder) as resolved. Records the applied_at semantics correction as shipped. Final Phase 9 row added to the 'What shipped' table. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../FLOWPILOT-MIGRATION.md | 29 +++++++++- .../handoff/2026-04-22-flowpilot-migration.md | 57 ++++++------------- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/docs/FlowAssist_Migration/FLOWPILOT-MIGRATION.md b/docs/FlowAssist_Migration/FLOWPILOT-MIGRATION.md index eab4e541..89ca92ac 100644 --- a/docs/FlowAssist_Migration/FLOWPILOT-MIGRATION.md +++ b/docs/FlowAssist_Migration/FLOWPILOT-MIGRATION.md @@ -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–8 implemented. Phase 8 replaced the task-lane `SuggestedFix` card CTA with a chat-composer-anchored `ProposalBanner`, added six columns to `session_suggested_fixes` (`status`, `applied_at`, `verified_at`, `partial_notes`, `failure_reason`, `ai_outcome_proposal`), `PATCH /api/v1/ai-sessions/{session_id}/suggested-fixes/{fix_id}/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) +> **Status:** Phases 0–9 implemented. Phase 9 shipped the tabbed Script Builder integration (chat-region tab strip, `ScriptBuilderTab` in ephemeral mode, `InlineNoTemplateDialog` chat-region relocation, `PATCH /script` endpoint, `origin`/`parent_pilot_session_id` migration, `applied_at` semantics correction, and `EscalateInterceptDialog` fourth "partial attempt" choice). `tsc -b` and `npm run build` both clean. +> **Last updated:** April 24, 2026 (Phase 9 — Tabbed Script Builder — committed; handoff and migration spec updated) --- @@ -914,6 +914,31 @@ git commit -m "feat(pilot): visual polish, empty/loading states, keyboard shortc git commit -m "feat(pilot): Phase 8 — fix outcome banner replaces task-lane SuggestedFix CTA" ``` +### Phase 9 — Tabbed Script Builder + +**Spec:** [phase-9-script-builder-tab.md](phase-9-script-builder-tab.md) + +**Implementation plan:** [phase-9-implementation-plan.md](phase-9-implementation-plan.md) + +**What this phase does:** Resolves open items #1 (NoTemplateDialog narrow-lane bug) and #3 (Tabbed Script Builder) from the Phase 6/7 backlog. The chat region gains a `[Chat] [Script Builder ●]` tab strip (`ChatTabStrip` + `ScriptBuilderTab`) that embeds `ScriptBuilderChat` in ephemeral mode — the generated script is returned to the caller and written back to `session_suggested_fixes.ai_drafted_script` via a new endpoint, which then unlocks the three-option dialog. Tabs use `display: none` toggling so chat scroll position, draft message, and history are fully preserved. `InlineNoTemplateDialog` is relocated from the task-lane `bottomSlot` into a dedicated chat-region placement wrapper, eliminating the narrow-lane viewport-breakpoint collision that made the three-option grid unusable. + +**Key backend additions:** +- `PATCH /api/v1/ai-sessions/{session_id}/suggested-fixes/{fix_id}/script` — writes `ai_drafted_script` + `ai_drafted_parameters` back to the fix record +- Alembic migration: `origin VARCHAR(20) NOT NULL DEFAULT 'standalone'` and `parent_pilot_session_id UUID NULL REFERENCES ai_sessions(id) ON DELETE SET NULL` added to `script_builder_sessions`; partial unique index `uq_script_builder_sessions_active_inline` prevents duplicate active inline sessions per pilot session +- `applied_at` semantics corrected: the field now stamps only when an action declares that the fix was run (e.g. `status='verified'` or `status='failed'`), not on the initial "Apply" click + +**Key frontend additions:** +- `ChatTabStrip` — tab strip rendered in the chat column header when an inline script session is active +- `ScriptBuilderTab` — wraps `ScriptBuilderChat` in ephemeral mode; calls the `/script` PATCH endpoint on completion +- `InlineNoTemplateDialog` — chat-region placement wrapper replacing the previous task-lane `bottomSlot` rendering +- `EscalateInterceptDialog` gains a fourth "partial attempt" choice (escalating mid-fix with partial notes) + +**Commit range:** `5bcb7aa` (Phase 9 Task 1 start) through `faf1d8d` + +``` +git commit -m "feat(pilot): Phase 9 — tabbed Script Builder + InlineNoTemplateDialog relocation" +``` + --- ## 10. Design system reference diff --git a/docs/handoff/2026-04-22-flowpilot-migration.md b/docs/handoff/2026-04-22-flowpilot-migration.md index 5c4aba80..670ef000 100644 --- a/docs/handoff/2026-04-22-flowpilot-migration.md +++ b/docs/handoff/2026-04-22-flowpilot-migration.md @@ -2,8 +2,8 @@ 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. +last_commit: faf1d8d fix(pilot): applied_at stamps on run-declaring actions, not Apply click +status: Sprint 9/9 phases complete and pushed; PR not yet opened. Open items #1 and #3 resolved by Phase 9. --- # FlowPilot Migration — Session Handoff @@ -16,7 +16,7 @@ status: Sprint 8/8 phases complete and pushed; PR not yet opened. Two open items ## 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). +All nine 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 | |---|---|---| @@ -29,6 +29,7 @@ All eight migration phases are merged onto the branch and verified against the l | 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) | +| 9 — Tabbed Script Builder | `5bcb7aa`..`faf1d8d` | Chat-region tab strip (`[Chat] [Script Builder ●]`) with `ChatTabStrip` + `ScriptBuilderTab` (inline `ScriptBuilderChat` in ephemeral mode); `InlineNoTemplateDialog` relocated from task-lane `bottomSlot` to a chat-region placement wrapper; `EscalateInterceptDialog` gains a fourth "partial attempt" choice; `PATCH /api/v1/ai-sessions/{id}/suggested-fixes/{fid}/script` endpoint for writing back AI-drafted script; Alembic migration adds `origin` column + `parent_pilot_session_id` FK to `script_builder_sessions` with partial unique index; `applied_at` semantics corrected to stamp only on run-declaring actions (not the Apply click) | 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 @@ -45,20 +46,14 @@ Plus the structural fixes that came up along the way: ## 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. +Items #1 and #3 were discovered during Phase 6/7 verification. Item #2 was resolved by Phase 8. Items #1 and #3 are **resolved by Phase 9** (see below). ### 1. NoTemplateDialog narrow-lane bug -[frontend/src/components/pilot/script/NoTemplateDialog.tsx](../../frontend/src/components/pilot/script/NoTemplateDialog.tsx) +**Status: RESOLVED by Phase 9.** -**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). +Phase 9 relocated `InlineNoTemplateDialog` from the task-lane `bottomSlot` into a dedicated chat-region placement wrapper (`InlineNoTemplateDialog.tsx`). The dialog no longer renders inside the narrow 380px task lane, eliminating the `sm:grid-cols-3` viewport-breakpoint collision. The disabled-cards bug (when no `ai_drafted_script` is present) is also resolved: when no draft exists, the engineer is routed into the new `ScriptBuilderTab` inline chat instead of reaching the three-option dialog with disabled cards. -**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. +See [docs/FlowAssist_Migration/phase-9-implementation-plan.md](../FlowAssist_Migration/phase-9-implementation-plan.md) and [docs/FlowAssist_Migration/phase-9-script-builder-tab.md](../FlowAssist_Migration/phase-9-script-builder-tab.md) for full implementation details. ### 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. @@ -66,46 +61,28 @@ Items #1 and #3 were discovered during Phase 6/7 verification and remain deferre 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.** +**Status: RESOLVED by Phase 9.** -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): +Phase 9 shipped the complete tabbed Script Builder integration. The chat region now has a `[Chat] [Script Builder ●]` tab strip (`ChatTabStrip`) powered by `ScriptBuilderTab`, which embeds `ScriptBuilderChat` in ephemeral mode (returns script to caller, no standalone `script_templates` row). `display: none` toggling preserves chat scroll position, draft message, and history across tab switches. -- **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)). +The `PATCH /api/v1/ai-sessions/{id}/suggested-fixes/{fid}/script` endpoint writes `ai_drafted_script` + `ai_drafted_parameters` back to the fix record so the three-option dialog unlocks normally after script generation. -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. +The migration added `origin VARCHAR(20) DEFAULT 'standalone'` and `parent_pilot_session_id UUID NULL REFERENCES ai_sessions(id)` to `script_builder_sessions`, with a partial unique index ensuring only one active inline session per pilot session. -**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 `` 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. +See [docs/FlowAssist_Migration/phase-9-implementation-plan.md](../FlowAssist_Migration/phase-9-implementation-plan.md) and [docs/FlowAssist_Migration/phase-9-script-builder-tab.md](../FlowAssist_Migration/phase-9-script-builder-tab.md) for full implementation details. ## 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`. +- **`/ultrareview` not run** on the final state of the branch (including Phase 9). Worth doing before PR creation. +- **Phase 9 browser QA not done.** The new tab strip, `ScriptBuilderTab`, `InlineNoTemplateDialog` chat-region placement, and `EscalateInterceptDialog` fourth-choice flow have not been exercised in a headless-browser session. Key states to cover: tab strip renders and toggles without unmounting chat; ephemeral Script Builder returns a script and unlocks the three-option dialog; partial-attempt choice in `EscalateInterceptDialog` is recorded correctly. +- **Phase 8 browser QA not done.** The `ProposalBanner` and `EscalateInterceptDialog` (three-choice variant) have not been exercised in a headless-browser session. Key states: banner appears on `[FIX_OUTCOME]` marker; banner dismisses correctly; escalate mid-fix triggers dialog; 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. +- [frontend/src/components/assistant/TaskLane.tsx](../../frontend/src/components/assistant/TaskLane.tsx) — accepts `whatWeKnowSlot` / `bottomSlot` from the parent, plus a `variant: 'side' | 'drawer'` for responsive. `bottomSlot` remains active (carries `TemplateMatchPanel` + resolve/escalate preview buttons in both side and drawer variants). - [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 `` syntax only.