docs(pilot): correct Phase 9 migration description
All checks were successful
Mirror to GitHub / mirror (push) Successful in 4s
All checks were successful
Mirror to GitHub / mirror (push) Successful in 4s
Handoff + migration spec incorrectly claimed Phase 9 added a new parent_pilot_session_id FK. The implementation reuses the existing ai_session_id column; the migration only adds the origin discriminator + partial unique index. Also: ScriptBuilderTab wraps ScriptBuilderChat and ScriptBodyEditor (Monaco), not "ScriptBuilderChat in ephemeral mode" — there is no ephemeral mode on the presentational component. Applies applied_at call-site specifics: handleScriptDecision stamps on one_off/draft_template, TemplateMatchPanel stamps on onMarkRun, Script Builder tab Submit does not stamp. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
> **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–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.
|
||||
> **Status:** Phases 0–9 implemented. Phase 9 shipped the tabbed Script Builder integration (chat-region tab strip, `ScriptBuilderTab` controller with AI + Monaco editor modes, `InlineNoTemplateDialog` chat-region relocation, `PATCH /script` endpoint, `origin` discriminator migration reusing the existing `ai_session_id` FK, `applied_at` semantics correction, and `EscalateInterceptDialog` fourth "partial" 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)
|
||||
|
||||
---
|
||||
@@ -920,18 +920,20 @@ git commit -m "feat(pilot): Phase 8 — fix outcome banner replaces task-lane Su
|
||||
|
||||
**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.
|
||||
**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` + a new `ScriptBuilderTab` controller) that hosts two modes: an AI path reusing the existing (untouched) `ScriptBuilderChat`, and a "Write it myself" path using `ScriptBodyEditor` (Monaco). Engineer submit writes the drafted script back to `session_suggested_fixes.ai_drafted_script` via a new PATCH endpoint — `applied_at` is NOT stamped (a draft is not an application). Tabs use `display: none` toggling so chat scroll position, draft message, AI history, and Monaco buffer are all preserved across switches. `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
|
||||
- `PATCH /api/v1/ai-sessions/{session_id}/suggested-fixes/{fix_id}/script` — writes `ai_drafted_script` + `ai_drafted_parameters` without stamping `applied_at`; bumps `state_version` so Resolve/Escalate preview bundles regenerate; 409 on terminal fix status
|
||||
- Alembic migration adds `origin VARCHAR(20) NOT NULL DEFAULT 'standalone'` to `script_builder_sessions` (CHECK enum `'standalone'|'pilot_inline'` + invariant `origin='pilot_inline' ⇒ ai_session_id IS NOT NULL`); reuses the pre-existing `ai_session_id` FK rather than adding a new parent column; partial unique index `ux_script_builder_sessions_pilot_inline` on `(user_id, ai_session_id) WHERE origin='pilot_inline'` backs get-or-create idempotency
|
||||
- `POST /api/v1/scripts/builder/sessions` extended: accepts `origin` + `ai_session_id` with auth (pilot session must belong to caller); returns existing row on duplicate; race-safe via `IntegrityError` + re-read fallback; `list_sessions` and `count_user_sessions` default-scope to `origin='standalone'` so inline sessions don't pollute the dashboard or count against the 5-session cap
|
||||
- `applied_at` semantics corrected: stamps only on run-declaring actions — `TemplateMatchPanel` "I ran this" click via new `onMarkRun` prop, and `NoTemplateDialog` decisions `one_off`/`draft_template` (both labelled "Run now, …"). `build_template` does NOT stamp. Script Builder tab Submit does NOT stamp. Banner `Apply` click no longer stamps directly
|
||||
|
||||
**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)
|
||||
- `ChatTabStrip` — `[Chat] [Script Builder ●]` header strip in the chat region when the active fix needs a drafted script (status proposed/applied_partial, no template, no drafted script)
|
||||
- `ScriptBuilderTab` — new controller wrapping `ScriptBuilderChat` (AI mode) + `ScriptBodyEditor` (Monaco, "Write it myself" mode); get-or-create on mount; Submit calls `sessionSuggestedFixesApi.patchScript`
|
||||
- `InlineNoTemplateDialog` — chat-region slide-up wrapper around the existing `NoTemplateDialog`; replaces the previous task-lane `bottomSlot` rendering of the drafted-script three-card decision
|
||||
- `TemplateMatchPanel` gains `onMarkRun` optional prop + "✓ I ran this" primary button
|
||||
- `EscalateInterceptDialog` gains a fourth "I applied some of it — partial" choice (dispatches `applied_partial` via the existing `FixOutcome` pass-through)
|
||||
|
||||
**Commit range:** `5bcb7aa` (Phase 9 Task 1 start) through `faf1d8d`
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ All nine migration phases are merged onto the branch and verified against the li
|
||||
| 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) |
|
||||
| 9 — Tabbed Script Builder | `5bcb7aa`..`faf1d8d` | Chat-region tab strip (`[Chat] [Script Builder ●]`) with `ChatTabStrip` + new `ScriptBuilderTab` controller wrapping the existing `ScriptBuilderChat` + Monaco editor (`ScriptBodyEditor`); `InlineNoTemplateDialog` relocates the existing `NoTemplateDialog` from the narrow task-lane `bottomSlot` to a chat-region placement wrapper; `EscalateInterceptDialog` gains a fourth "partial" choice; `PATCH /api/v1/ai-sessions/{sid}/suggested-fixes/{fid}/script` endpoint for engineer-drafted scripts (does not stamp `applied_at`); Alembic migration adds `origin VARCHAR(20)` to `script_builder_sessions` (reuses existing `ai_session_id` FK) + partial unique index on `(user_id, ai_session_id) WHERE origin='pilot_inline'` for idempotent get-or-create; `applied_at` semantics corrected to stamp only on run-declaring actions (`handleScriptDecision` for `one_off`/`draft_template`; new `onMarkRun` on `TemplateMatchPanel`) — 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
|
||||
@@ -63,11 +63,11 @@ See [docs/FlowAssist_Migration/phase-8-fix-outcome-banner.md](../FlowAssist_Migr
|
||||
### 3. Tabbed Script Builder inside the chat (Option A from the modal-vs-tab discussion)
|
||||
**Status: RESOLVED by Phase 9.**
|
||||
|
||||
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.
|
||||
Phase 9 shipped the complete tabbed Script Builder integration. The chat region now has a `[Chat] [Script Builder ●]` tab strip (`ChatTabStrip`) powered by a new `ScriptBuilderTab` controller that wraps the existing (untouched) `ScriptBuilderChat` for AI mode and `ScriptBodyEditor` (Monaco) for a "Write it myself" editor mode. `display: none` toggling preserves chat scroll position, draft message, and editor buffer across tab switches.
|
||||
|
||||
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.
|
||||
The `PATCH /api/v1/ai-sessions/{sid}/suggested-fixes/{fid}/script` endpoint writes `ai_drafted_script` + `ai_drafted_parameters` back to the fix record without stamping `applied_at` — a draft is not an application. Bumps `state_version` so cached Resolve/Escalate previews regenerate.
|
||||
|
||||
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.
|
||||
The migration added `origin VARCHAR(20) NOT NULL DEFAULT 'standalone'` (with CHECK constraint on the two valid values + invariant that `origin='pilot_inline'` requires `ai_session_id IS NOT NULL`) to `script_builder_sessions`. It reuses the pre-existing `ai_session_id` FK rather than adding a new parent column. A partial unique index on `(user_id, ai_session_id) WHERE origin='pilot_inline'` backs get-or-create idempotency from the inline tab.
|
||||
|
||||
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.
|
||||
|
||||
@@ -75,7 +75,7 @@ See [docs/FlowAssist_Migration/phase-9-implementation-plan.md](../FlowAssist_Mig
|
||||
|
||||
- **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 (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 9 browser QA not done.** The new tab strip, `ScriptBuilderTab` (AI + editor modes), `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 or losing editor buffer; Script Builder tab Submit persists script via PATCH without stamping `applied_at`; `one_off`/`draft_template` decisions DO stamp; `build_template` does NOT stamp; `TemplateMatchPanel` "I ran this" stamps via `onMarkRun`; 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.
|
||||
|
||||
Reference in New Issue
Block a user