docs: add FlowPilot migration design doc and mockups
Brings the locked FlowPilot migration design onto the branch that will implement it. Includes the annotated target UI mockups (primary session view + three Script Generator integration states) and the superseded FLOWPILOT-AND-RESOLUTIONASSIST.md for historical reference. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
163
docs/FLOWPILOT-AND-RESOLUTIONASSIST.md
Normal file
163
docs/FLOWPILOT-AND-RESOLUTIONASSIST.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# FlowPilot & ResolutionAssist
|
||||
|
||||
> ResolutionFlow offers two AI-driven troubleshooting modes that share the same session backend but present very different interaction styles. Both work standalone and become richer when paired with a PSA connection.
|
||||
|
||||
---
|
||||
|
||||
## At a glance
|
||||
|
||||
| | **FlowPilot** | **ResolutionAssist** |
|
||||
|---|---|---|
|
||||
| **Style** | Guided, structured | Conversational, freeform |
|
||||
| **Entry** | `/pilot` | `/assistant` |
|
||||
| **Interaction** | Questions → Actions → Resolution, one step at a time | Natural chat with inline questions/actions |
|
||||
| **Best for** | Reproducible workflows, low-context engineers, handoffs | Exploratory problems, quick lookups, rubber-ducking |
|
||||
| **Lifecycle** | Active → Paused → Resolved / Escalated / Abandoned | Active → Resolved / Abandoned (lightweight) |
|
||||
| **Confidence tracking** | Yes — drives tier transitions | No — always responsive to user direction |
|
||||
| **Navigation guard** | Yes — prevents accidental loss | No — free to leave and return |
|
||||
|
||||
Both modes share the `ai_sessions` table (discriminated by `session_type`), the same multimodal AI backend (image uploads, markdown, cached prompts), and the same `[QUESTIONS]` / `[ACTIONS]` / `[FORK]` marker vocabulary that renders inline TaskLane elements.
|
||||
|
||||
---
|
||||
|
||||
## FlowPilot — guided troubleshooting
|
||||
|
||||
FlowPilot is a wizard-style AI engineer that walks you through a problem one diagnostic step at a time. It runs on confidence tiers:
|
||||
|
||||
- **Discovery** (confidence < 0.4) — asking broad, open-ended questions to characterize the problem
|
||||
- **Exploring** (0.4–0.8) — proposing targeted actions and narrowing hypotheses
|
||||
- **Guided** (≥ 0.8) — recommending a specific fix with steps to verify
|
||||
|
||||
### The FlowPilot session flow
|
||||
|
||||
1. **Intake.** You start from `/pilot` or from the dashboard "New Session" button. The intake screen accepts free-text description, PSA ticket context, screenshots, or log pastes.
|
||||
2. **Preference check.** Before suggesting any fix, the AI asks whether you want a **GUI** or **script** approach. This is enforced in the system prompt so you never get steps you can't execute.
|
||||
3. **Step-by-step progression.** Each AI response is either a question (with clickable options), an action (with "Done" / "Didn't work" buttons), a `[FORK]` (two distinct paths to try), or a final resolution suggestion. You respond, the AI updates its confidence, and the next step is generated.
|
||||
4. **Action bar.** The session header always shows **Pause & Leave**, **Resolve**, **Escalate**, **Share Update**, and **Close**. Pausing freezes the session; resuming restores the full context.
|
||||
5. **Resolve / Escalate.** *Resolve* marks the ticket fixed and generates a clean summary of what worked. *Escalate* packages the problem summary and steps tried into an **escalation package** that the next engineer (or the PSA ticket) inherits.
|
||||
|
||||
### Why FlowPilot exists
|
||||
|
||||
- **New engineers** get senior-engineer-level diagnostic rigor without needing the experience to know what to ask next.
|
||||
- **Documented resolutions** — every step is captured, so the generated note on the ticket is substantive (not just "fixed it").
|
||||
- **Handoff-friendly** — escalation packages mean the next person doesn't start from zero.
|
||||
|
||||
---
|
||||
|
||||
## ResolutionAssist — conversational AI
|
||||
|
||||
ResolutionAssist is a chat with an expert IT systems engineer. It's less structured than FlowPilot but still surfaces interactive elements when the AI wants structured input.
|
||||
|
||||
### The ResolutionAssist flow
|
||||
|
||||
1. **Open a chat.** From `/assistant` or the dashboard. Sessions show up in the left sidebar just like any messaging app.
|
||||
2. **Send a message.** Freeform prose. Attach up to 3 images per message (screenshots, error dialogs, network diagrams). Paste logs, code, or PowerShell output.
|
||||
3. **AI responds.** The response is prose, but any `[QUESTIONS]` or `[ACTIONS]` blocks render as a **TaskLane** — a side panel with clickable options and action buttons. You can answer via chat or click the TaskLane elements.
|
||||
4. **Branching (`[FORK]`).** If the AI proposes two paths ("check cable or restart switch?"), the fork renders as a choice. Picking one continues the conversation down that path.
|
||||
5. **Resume later.** Unlike FlowPilot, there's no navigation guard. Leave mid-conversation; every message is stored.
|
||||
|
||||
### Why ResolutionAssist exists
|
||||
|
||||
- **Unstructured problems** — "I have no idea where to start, here's a screenshot" works great.
|
||||
- **Reference lookups** — "what's the right PowerShell command to check Exchange health" is faster in chat than through an intake form.
|
||||
- **Senior engineers** — when you already know what you're doing and just want a second opinion or a syntax check.
|
||||
|
||||
---
|
||||
|
||||
## Without a PSA connection
|
||||
|
||||
Both modes work standalone. Without ConnectWise connected:
|
||||
|
||||
- Sessions live entirely in ResolutionFlow. They're listed in your session history, searchable, and shareable via public share links (`/shared/sessions/:token`).
|
||||
- Summaries generated on Resolve are saved to the session record but **not** written anywhere else. You can copy/paste into whatever ticketing or documentation system you use.
|
||||
- Escalating a FlowPilot session routes the escalation package to another ResolutionFlow engineer on your team — not to an external PSA ticket.
|
||||
- No ticket context is injected into the AI prompt, so the AI starts cold with only what you provide in the intake or first message.
|
||||
|
||||
**Standalone use cases:**
|
||||
- Evaluating ResolutionFlow before committing to a PSA integration
|
||||
- Troubleshooting internal IT issues that aren't client-facing
|
||||
- Teams using a PSA ResolutionFlow doesn't integrate with yet
|
||||
- Knowledge-base research ("what are my options for X") that don't map to a ticket
|
||||
|
||||
---
|
||||
|
||||
## With a PSA connection (ConnectWise)
|
||||
|
||||
When ConnectWise is connected, both modes become ticket-aware and write back to the PSA as a first-class client.
|
||||
|
||||
### FlowPilot + PSA
|
||||
|
||||
**Starting from a ticket:**
|
||||
- Click a ticket row (from `/tickets` or the dashboard queue) and pick "Start FlowPilot." The ticket's problem description, recent notes, configurations, company details, and related tickets are auto-injected into the AI's context. No manual retyping.
|
||||
- The session shows the linked ticket badge in the header.
|
||||
|
||||
**During the session:**
|
||||
- **Share Update** — posts an interim note to the CW ticket with the current AI summary, so stakeholders can see progress without interrupting you.
|
||||
- **Status changes** — the detail panel and session header let you move the ticket through statuses (New → In Progress → Waiting on Customer → Resolved) directly from ResolutionFlow. Status writes are verified against CW so you're never told "success" when CW silently rejected the change.
|
||||
- **Resource assignment** — add yourself or a teammate as a co-assignee without touching the owner. If the ticket has no owner yet, assigning sets owner; if there's already an owner, you're added as an additional resource via a CW schedule entry.
|
||||
|
||||
**On Resolve:**
|
||||
- Final summary is posted as a ticket note.
|
||||
- Ticket status can auto-update to Resolved (per your team's settings).
|
||||
|
||||
**On Escalate:**
|
||||
- The escalation package (problem summary + steps tried) is posted as a note.
|
||||
- The ticket can be routed via CW's normal escalation rules.
|
||||
- The next engineer picking up the ticket can auto-start a new session with the full escalation context pre-filled.
|
||||
|
||||
**Spin-off tickets (new):**
|
||||
- During any session, if you discover a separate issue, the AI can propose `create_spin_off_ticket`. Accepting opens the New Ticket modal pre-filled with the current ticket's company and board, so a second ticket is one click away without leaving your session.
|
||||
|
||||
### ResolutionAssist + PSA
|
||||
|
||||
**Starting from a ticket:**
|
||||
- Same ticket-context injection as FlowPilot. When opened with a linked ticket, the AI sees company, configs, notes, and related tickets.
|
||||
- A "New Ticket" button appears in the header — lets you spawn a separate ticket mid-conversation (same flow as FlowPilot's spin-off).
|
||||
|
||||
**During the chat:**
|
||||
- Ask the AI about the ticket directly: *"Summarize what's been tried," "What configs does this company have?"* — the AI already has that context loaded.
|
||||
- `[ACTIONS]` can include `create_spin_off_ticket` when the AI detects a separate issue surfaced in the conversation.
|
||||
|
||||
**Writing back:**
|
||||
- ResolutionAssist is a lighter-weight mode, so it doesn't auto-post on resolve. You can manually copy the conversation summary to a ticket note if useful.
|
||||
- Status updates and resource assignment are done via the `/tickets` page rather than the chat UI.
|
||||
|
||||
---
|
||||
|
||||
## Choosing between them
|
||||
|
||||
| I want to… | Use |
|
||||
|---|---|
|
||||
| Walk through a known issue type with step-by-step rigor | **FlowPilot** |
|
||||
| Document every action taken for audit or handoff | **FlowPilot** |
|
||||
| Escalate with a full context package | **FlowPilot** |
|
||||
| Ask a question, get an answer, move on | **ResolutionAssist** |
|
||||
| Paste a screenshot and say "what's wrong here?" | **ResolutionAssist** |
|
||||
| Stay on the ticket for 2 minutes, not 20 | **ResolutionAssist** |
|
||||
| Troubleshoot without breaking flow to switch pages | Either, with the linked ticket panel open alongside |
|
||||
|
||||
The two modes aren't competitive. A common workflow is to start in ResolutionAssist to scope the problem, then kick off a FlowPilot session when you realize the issue is going to take real diagnosis. Both show up in the unified session history.
|
||||
|
||||
---
|
||||
|
||||
## Tickets page — the PSA hub
|
||||
|
||||
`/tickets` is the CW ticket manager built into ResolutionFlow. With a PSA connection:
|
||||
|
||||
- Search and filter tickets by assignment (me / unassigned / specific member via searchable picker), board, status, priority, company, open/closed.
|
||||
- Slide-out detail panel shows notes, configurations, related tickets, and assignees — all fetched in parallel for fast hydration.
|
||||
- From the detail panel: change status, add/remove assignees, post notes, or "Start FlowPilot" / "Open in ResolutionAssist" with full context.
|
||||
- New Ticket modal offers both AI-parse ("Create a high-priority ticket for Acme — Outlook not syncing for jsmith") and a traditional form.
|
||||
|
||||
Without a PSA connection, `/tickets` is hidden from the sidebar entirely — there's nothing to show.
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
- **FlowPilot** = guided, structured, lifecycle-heavy, ideal for resolvable issues and handoffs.
|
||||
- **ResolutionAssist** = freeform chat, ideal for scoping and quick answers.
|
||||
- **Without PSA** = both work, sessions live in ResolutionFlow, summaries are yours to export.
|
||||
- **With PSA** = both become ticket-aware, write back to CW (notes, status, resources), and can spawn spin-off tickets mid-session.
|
||||
|
||||
The AI is the same under the hood. The difference is how much structure you want around the conversation — and how deeply the result needs to integrate with your ticketing system.
|
||||
794
docs/FlowAssist_Migration/FLOWPILOT-MIGRATION.md
Normal file
794
docs/FlowAssist_Migration/FLOWPILOT-MIGRATION.md
Normal file
@@ -0,0 +1,794 @@
|
||||
# FlowPilot Migration — Design & Implementation Doc
|
||||
|
||||
> **Target:** Transform `/assistant` (ResolutionAssist) into the new unified `/pilot` (FlowPilot) surface.
|
||||
> **Audience:** Claude Code (implementation) reviewed by Michael (owner).
|
||||
> **Status:** Design locked. Ready for phased implementation.
|
||||
> **Last updated:** April 17, 2026
|
||||
|
||||
---
|
||||
|
||||
## 0. Prerequisite reading for Claude Code
|
||||
|
||||
Before writing any code, read these in order:
|
||||
|
||||
1. This document end-to-end.
|
||||
2. `mockups/01-session-primary.png` — the target state for the main session UI.
|
||||
3. `mockups/02-script-template-match.png`, `03-script-three-options.png`, `04-script-templatize-prompt.png` — Script Generator integration states.
|
||||
4. The source HTML files `mockups/01-session-primary.html` and `mockups/02-04-script-integration.html` — authoritative for spacing, colors, and component structure. When CSS or layout questions arise during implementation, these files are the tiebreaker.
|
||||
|
||||
Do not proceed to implementation until you have confirmed you understand the following three architectural claims. If any of them are unclear, stop and ask.
|
||||
|
||||
1. **There is one AI troubleshooting surface, not two.** The existing split between FlowPilot (guided) and ResolutionAssist (chat) is collapsed into a single chat-primary product called FlowPilot at `/pilot`. The `ai_sessions.session_type` discriminator column is retained for data, but the product shows one unified UI.
|
||||
2. **The task lane is the load-bearing structural feature.** It is not a sidebar of metadata. It actively tracks diagnostic state: *What we know*, *Questions*, *Diagnostic checks*, *Suggested fix*. Engineers interact with it; facts flow between sections.
|
||||
3. **Resolve and Escalate are deterministic artifact generators, not free-text prompts.** When an engineer clicks Resolve, a structured summary is generated from task lane state (not from the chat transcript alone) and posted to CW. The summary structure is fixed: *Problem / What we confirmed / Root cause / Resolution*.
|
||||
|
||||
---
|
||||
|
||||
## 1. Why this change
|
||||
|
||||
### The current state
|
||||
|
||||
- `/assistant` is a chat-primary AI session with a `[QUESTIONS]` and `[DIAGNOSTIC_CHECKS]` task lane.
|
||||
- `/pilot` was specced as a separate guided, confidence-tiered wizard with a different UI and lifecycle.
|
||||
- The `FLOWPILOT-AND-RESOLUTIONASSIST.md` design document treated them as two products sharing a backend.
|
||||
|
||||
### The problems with the current state
|
||||
|
||||
- Two sidebar entries, two session histories, two mental models for engineers to learn.
|
||||
- The PSA integration scope doubles (writebacks for lifecycle events must be built twice, or built for Pilot and bolted onto Assist).
|
||||
- The Team Wiki moat depends on structured session artifacts with explicit resolutions — a chat-only mode produces weaker artifacts.
|
||||
- The cockpit positioning (the core ResolutionFlow brand promise) does not map to a blank chat window.
|
||||
- Branching into two modes forces a decision onto the engineer ("which mode for this ticket?") that has no right answer.
|
||||
|
||||
### The resolution
|
||||
|
||||
The existing `/assistant` UI already does most of what `/pilot` was supposed to do — structured questions, diagnostic checks, lifecycle actions in the header. It is closer to the right product than the doc anticipated. Rather than building Pilot as a second surface, we extend Assist with the missing structural features (*What we know*, auto-generated summaries, escalation packages) and rename it FlowPilot.
|
||||
|
||||
### The strategic move
|
||||
|
||||
FlowPilot becomes the single canonical troubleshooting surface. Every PSA writeback, every Wiki compilation path, every Script Generator invocation points here. One session shape, one lifecycle, one integration surface.
|
||||
|
||||
---
|
||||
|
||||
## 2. Terminology used in this document
|
||||
|
||||
| Term | Meaning |
|
||||
|---|---|
|
||||
| **Session** | A single `ai_sessions` row representing one troubleshooting conversation. |
|
||||
| **Task lane** | The right-side panel containing What we know, Questions, Diagnostic checks, Suggested fix. |
|
||||
| **Fact** | An item in the What we know section. Has `text`, `source_type` (`question` / `diagnostic_check` / `user_note`), and `source_ref` (FK to the originating question/check, or null for user notes). |
|
||||
| **Suggested fix** | The AI's current best-guess resolution path. Has a confidence score and, optionally, a reference to a Script Library template. |
|
||||
| **Promotion** | The act of a question answer or diagnostic check result being converted into a fact in What we know. Triggered by AI, confirmed/editable by engineer. |
|
||||
| **Resolution note** | The structured document generated when the engineer clicks Resolve. Posted to CW as a ticket note. |
|
||||
| **Escalation package** | The structured handoff document generated when the engineer clicks Escalate. Posted to CW and attached to the session for the next engineer. |
|
||||
|
||||
---
|
||||
|
||||
## 3. Target UI — annotated
|
||||
|
||||
### 3.1 Primary session view
|
||||
|
||||

|
||||
|
||||
The session UI is a four-column layout:
|
||||
|
||||
1. **Icon rail** (64px wide) — primary app navigation. FlowPilot / Tickets / Trees / Scripts / Wiki. Avatar at bottom.
|
||||
2. **Session list** (260px wide) — all sessions grouped by state (Active / Recent). Each row shows title, state dot, PSA ticket number, and client name.
|
||||
3. **Conversation column** (fluid) — the chat thread, composer, and incident header.
|
||||
4. **Task lane** (380px wide) — *What we know*, *Questions*, *Diagnostic checks*, *Suggested fix*, and the Resolve action at the bottom.
|
||||
|
||||
Key visual and behavioral elements numbered against the mockup:
|
||||
|
||||
**Incident header (top of conversation column)**
|
||||
- PSA chip showing `CW #48291` in cyan, monospaced
|
||||
- Client / contact / priority meta line
|
||||
- Incident title in Bricolage Grotesque 19px
|
||||
- Four lifecycle buttons right-aligned: **Pause** (ghost), **Share update** (neutral), **Escalate** (amber), **Resolve** (green)
|
||||
|
||||
**Conversation column**
|
||||
- Standard chat thread with pilot and user avatars
|
||||
- Pilot uses cyan gradient avatar; user uses purple gradient
|
||||
- AI messages in `bg-2` bubbles with subtle border; user messages in cyan-tinted bubbles
|
||||
- Composer at bottom with inline action chips (Attach / Paste logs / Ticket context) and a send button
|
||||
|
||||
**Task lane sections, in order:**
|
||||
|
||||
1. **What we know** (NEW)
|
||||
- Header: `WHAT WE KNOW · 4` (section title + count)
|
||||
- Each fact is a card: `bg-2` background, dashed circular green check, fact text, and a provenance line (`from question · rules out tenant/license`)
|
||||
- "+ Add a note" button at the bottom for manual facts from the engineer
|
||||
- Background has a subtle green-to-transparent gradient to visually distinguish from the rest of the lane
|
||||
|
||||
2. **Questions**
|
||||
- Header: `QUESTIONS · 2 unanswered`
|
||||
- Each unanswered question: title, AI hint text, Answer / Skip buttons
|
||||
- Answered questions dim to 55% opacity with a dashed border and show the resolution inline (`Answered · isolated to jsmith (promoted to What we know)`)
|
||||
|
||||
3. **Diagnostic checks**
|
||||
- Header: `DIAGNOSTIC CHECKS · 1 / 3 run`
|
||||
- "Run remaining 2 checks" button at top when applicable
|
||||
- Each check: icon + command name (monospaced), description
|
||||
- Completed checks dim and show "Complete · findings promoted to What we know" in green
|
||||
|
||||
4. **Suggested fix**
|
||||
- Header: `SUGGESTED FIX · 94% confidence`
|
||||
- Amber-accented card with fix title and description
|
||||
- Clicking opens the Script Generator flow (Section 5)
|
||||
|
||||
**Resolve action bar (bottom of task lane)**
|
||||
- Small hint text ("Summary preview is open →")
|
||||
- Full-width "Resolve & post to CW" button in green
|
||||
|
||||
**Resolution note preview (floating, anchored to Resolve button)**
|
||||
- A persistent popover, NOT a modal
|
||||
- Shows the draft resolution note with Problem / What we confirmed / Root cause / Resolution sections
|
||||
- Displays the target ticket (`CW #48291`) and status change (`Resolved`)
|
||||
- Edit button opens an inline editor; Confirm & post fires the PSA writeback
|
||||
|
||||
### 3.2 Script Generator integration — template match
|
||||
|
||||

|
||||
|
||||
When the suggested fix references an existing Script Library template, clicking the fix opens the Script Generator panel in place of (or sliding over) the task lane. Key behavior:
|
||||
|
||||
- A **Verified template** badge appears above the parameter form
|
||||
- Parameters pre-filled from session context get a cyan `from session` tag and a cyan-tinted input background
|
||||
- Each pre-filled parameter has a hint line explaining the source: *"Pulled from CW company config for Acme Corp"*
|
||||
- The engineer can adjust any pre-filled value before generating
|
||||
- `⌘K` → "script" invokes the generator mid-conversation from anywhere in the session
|
||||
|
||||
### 3.3 Script Generator integration — no template match (three-option dialog)
|
||||
|
||||

|
||||
|
||||
When no template matches the suggested fix, FlowPilot drafts a session-specific script and presents three paths:
|
||||
|
||||
1. **Run as one-off** (neutral outline CTA)
|
||||
- Script generated and captured in session documentation, discarded after
|
||||
- Tradeoffs: fastest, but team won't benefit next time
|
||||
|
||||
2. **Run now, templatize after resolve** (RECOMMENDED, cyan primary CTA)
|
||||
- Script generated for this ticket; draft template queued
|
||||
- Post-resolve prompt offers to templatize (Section 5.3)
|
||||
- Tradeoffs: zero cognitive overhead now, only templatize what works, ~30s review later
|
||||
|
||||
3. **Build as template now** (purple outline CTA)
|
||||
- Full parameterization upfront
|
||||
- Tradeoffs: immediate team benefit, but adds time mid-ticket
|
||||
|
||||
The drafted script renders as a code preview above the option cards with the AI's proposed parameters highlighted in amber.
|
||||
|
||||
### 3.4 Script Generator integration — post-resolve templatization prompt
|
||||
|
||||

|
||||
|
||||
If the engineer picked Option 2 in the three-option dialog and Resolve succeeds, this prompt appears after the resolution note is posted to CW:
|
||||
|
||||
- Success banner confirms the resolution posted
|
||||
- Templatize card shows the script with AI-proposed parameters substituted in as `{{ gateway_host }}`, etc.
|
||||
- Right pane lists extracted parameters with remove buttons (engineer can adjust)
|
||||
- Provenance note: *"generated from CW #48307 · resolved by M. Davis"*
|
||||
- Three actions: Skip / Edit parameters / Save as team template
|
||||
- "Don't ask me again for this team" opt-out in footer
|
||||
|
||||
---
|
||||
|
||||
## 4. Data model changes
|
||||
|
||||
### 4.1 New columns on `ai_sessions`
|
||||
|
||||
```sql
|
||||
ALTER TABLE ai_sessions
|
||||
ADD COLUMN resolution_note_markdown TEXT NULL,
|
||||
ADD COLUMN resolution_note_posted_at TIMESTAMPTZ NULL,
|
||||
ADD COLUMN resolution_note_external_id VARCHAR(128) NULL, -- CW note ID after posting
|
||||
ADD COLUMN escalation_package_markdown TEXT NULL,
|
||||
ADD COLUMN escalation_package_posted_at TIMESTAMPTZ NULL;
|
||||
```
|
||||
|
||||
No migration of `session_type` — the column stays. New sessions all default to the unified FlowPilot type.
|
||||
|
||||
### 4.2 New `session_facts` table (the What we know backing store)
|
||||
|
||||
```sql
|
||||
CREATE TABLE session_facts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
session_id UUID NOT NULL REFERENCES ai_sessions(id) ON DELETE CASCADE,
|
||||
account_id UUID NOT NULL REFERENCES accounts(id), -- for RLS, per multi-tenant architecture
|
||||
text TEXT NOT NULL,
|
||||
source_type VARCHAR(32) NOT NULL CHECK (source_type IN ('question', 'diagnostic_check', 'user_note', 'ai_synthesis')),
|
||||
source_ref UUID NULL, -- FK to session_questions.id or session_diagnostic_checks.id, null for user_note
|
||||
source_summary TEXT NULL, -- free-text provenance label, e.g. "rules out tenant/license"
|
||||
created_by UUID NOT NULL REFERENCES users(id),
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
deleted_at TIMESTAMPTZ NULL
|
||||
);
|
||||
CREATE INDEX idx_session_facts_session ON session_facts(session_id) WHERE deleted_at IS NULL;
|
||||
CREATE INDEX idx_session_facts_account ON session_facts(account_id);
|
||||
```
|
||||
|
||||
**Important:** `source_ref` is a polymorphic FK and should NOT have a database-level FK constraint. Enforce integrity at the service layer.
|
||||
|
||||
### 4.3 New `session_suggested_fixes` table
|
||||
|
||||
```sql
|
||||
CREATE TABLE session_suggested_fixes (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
session_id UUID NOT NULL REFERENCES ai_sessions(id) ON DELETE CASCADE,
|
||||
account_id UUID NOT NULL REFERENCES accounts(id),
|
||||
title VARCHAR(200) NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
confidence_pct INTEGER NOT NULL CHECK (confidence_pct BETWEEN 0 AND 100),
|
||||
script_template_id UUID NULL REFERENCES script_templates(id), -- null if no template match
|
||||
ai_drafted_script TEXT NULL, -- populated if no template match
|
||||
ai_drafted_parameters JSONB NULL, -- AI's proposed parameterization
|
||||
user_decision VARCHAR(32) NULL CHECK (user_decision IN ('one_off', 'draft_template', 'build_template', 'dismissed')),
|
||||
superseded_at TIMESTAMPTZ NULL, -- set when a new suggestion replaces this one
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
CREATE INDEX idx_session_suggested_fixes_session ON session_suggested_fixes(session_id) WHERE superseded_at IS NULL;
|
||||
```
|
||||
|
||||
A session can have multiple suggested fixes over time as the AI's understanding evolves. Only one is active (superseded_at IS NULL) at a time.
|
||||
|
||||
### 4.4 New `draft_templates` table
|
||||
|
||||
Backing store for Option 2 in the three-option dialog — scripts generated during sessions that are pending templatization.
|
||||
|
||||
```sql
|
||||
CREATE TABLE draft_templates (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
account_id UUID NOT NULL REFERENCES accounts(id),
|
||||
source_session_id UUID NOT NULL REFERENCES ai_sessions(id),
|
||||
source_user_id UUID NOT NULL REFERENCES users(id),
|
||||
script_body TEXT NOT NULL,
|
||||
proposed_parameters JSONB NOT NULL, -- {"parameters": [{"key": "...", "label": "...", "type": "..."}]}
|
||||
proposed_name VARCHAR(200) NULL,
|
||||
proposed_category_id UUID NULL REFERENCES script_categories(id),
|
||||
status VARCHAR(32) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'accepted', 'rejected')),
|
||||
resolved_at TIMESTAMPTZ NULL, -- when the user acted on the draft
|
||||
promoted_template_id UUID NULL REFERENCES script_templates(id), -- if accepted, the created template
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
```
|
||||
|
||||
Accepted draft templates produce a new `script_templates` row and record the source session for provenance display.
|
||||
|
||||
### 4.5 Extension to `script_templates`
|
||||
|
||||
```sql
|
||||
ALTER TABLE script_templates
|
||||
ADD COLUMN source_session_id UUID NULL REFERENCES ai_sessions(id),
|
||||
ADD COLUMN source_user_id UUID NULL REFERENCES users(id),
|
||||
ADD COLUMN source_ticket_ref VARCHAR(64) NULL; -- e.g. "CW #48307" for display
|
||||
```
|
||||
|
||||
These fields power the provenance chip in the Script Library: *"generated from CW #48307 · resolved by M. Davis · used 7 times"*.
|
||||
|
||||
### 4.6 Per-account settings
|
||||
|
||||
```sql
|
||||
ALTER TABLE account_settings
|
||||
ADD COLUMN templatize_prompt_enabled BOOLEAN NOT NULL DEFAULT true;
|
||||
```
|
||||
|
||||
Controls whether the post-resolve templatize prompt appears. Toggleable from the prompt's footer ("Don't ask me again for this team") and from admin settings.
|
||||
|
||||
---
|
||||
|
||||
## 5. API endpoints
|
||||
|
||||
All endpoints follow ResolutionFlow conventions: `/api/v1/` prefix, JWT auth, tenant-scoped via RLS.
|
||||
|
||||
### 5.1 Session facts
|
||||
|
||||
```
|
||||
GET /api/v1/sessions/{id}/facts List facts for a session (ordered by created_at ASC)
|
||||
POST /api/v1/sessions/{id}/facts Create a manual fact (user_note source_type)
|
||||
PATCH /api/v1/sessions/{id}/facts/{fact_id} Edit fact text or summary (only for user_note or AI-synthesized facts)
|
||||
DELETE /api/v1/sessions/{id}/facts/{fact_id} Soft-delete
|
||||
POST /api/v1/sessions/{id}/facts/promote Promote a question answer or check result to a fact
|
||||
Body: { source_type, source_ref, proposed_text, proposed_summary }
|
||||
Returns the created fact. Used by the AI synthesis flow and
|
||||
by the engineer's explicit "promote to What we know" action.
|
||||
```
|
||||
|
||||
### 5.2 Suggested fixes
|
||||
|
||||
```
|
||||
GET /api/v1/sessions/{id}/suggested-fixes/active Returns the current active fix (superseded_at IS NULL) or 404
|
||||
POST /api/v1/sessions/{id}/suggested-fixes/{fix_id}/decision
|
||||
Body: { decision: "one_off" | "draft_template" | "build_template" | "dismissed" }
|
||||
Records the user's path choice. Server-side side effects:
|
||||
- one_off: generates script via ScriptTemplateEngine, returns rendered script
|
||||
- draft_template: same as one_off, plus creates draft_templates row
|
||||
- build_template: redirects to full template creation flow
|
||||
- dismissed: marks fix as superseded
|
||||
```
|
||||
|
||||
### 5.3 Draft templates (post-resolve flow)
|
||||
|
||||
```
|
||||
GET /api/v1/draft-templates List pending drafts for the current user's account
|
||||
(used by the Script Library "X scripts ready to review" notification)
|
||||
GET /api/v1/draft-templates/{id} Get a single draft including its proposed parameterization
|
||||
POST /api/v1/draft-templates/{id}/accept Body: { name, category_id, parameters_schema, edits }
|
||||
Creates a new script_templates row with source_session_id set,
|
||||
sets draft status to 'accepted', returns the new template
|
||||
POST /api/v1/draft-templates/{id}/reject Sets status to 'rejected'
|
||||
```
|
||||
|
||||
### 5.4 Resolution notes and escalation packages
|
||||
|
||||
```
|
||||
POST /api/v1/sessions/{id}/resolution-note/preview Generates the draft resolution note from current session state
|
||||
WITHOUT posting. Returns { markdown, target_ticket_ref }.
|
||||
Called when the task lane renders and refreshed whenever
|
||||
facts/suggested fix change.
|
||||
POST /api/v1/sessions/{id}/resolution-note/post Body: { markdown } (engineer-edited version)
|
||||
Posts to the linked PSA ticket, updates ticket status if configured,
|
||||
marks session resolved.
|
||||
POST /api/v1/sessions/{id}/escalation-package/preview Same pattern for escalation
|
||||
POST /api/v1/sessions/{id}/escalation-package/post Posts and transitions session to escalated state
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Services to implement
|
||||
|
||||
### 6.1 `FactSynthesisService` (new)
|
||||
|
||||
**Location:** `services/fact_synthesis_service.py`
|
||||
|
||||
**Purpose:** Converts question answers and diagnostic check results into candidate facts. Called by the AI pipeline when the LLM emits a `[PROMOTE]` marker, and by explicit engineer action.
|
||||
|
||||
**Key methods:**
|
||||
- `synthesize_from_question(question_id: UUID, raw_answer: str) -> dict` — returns `{proposed_text, proposed_summary}` via LLM call. The summary is the short provenance label ("rules out tenant/license").
|
||||
- `synthesize_from_check(check_id: UUID, check_output: str) -> dict` — same pattern for diagnostic check output.
|
||||
- `create_fact(session_id, source_type, source_ref, text, summary, user_id) -> SessionFact` — persists the fact.
|
||||
|
||||
**Prompt engineering note:** The synthesis prompt should be conservative — short, factual statements. Hallucinated specifics are a trust-killer. The prompt must explicitly instruct: *"Use only information present in the answer/output. If the answer does not contain a substantive fact, return null."*
|
||||
|
||||
### 6.2 `ResolutionNoteGeneratorService` (new)
|
||||
|
||||
**Location:** `services/resolution_note_generator.py`
|
||||
|
||||
**Purpose:** Produces the structured resolution note markdown from session state.
|
||||
|
||||
**Input:** session_id
|
||||
**Output:** `{markdown: str, target_ticket_ref: str | None}`
|
||||
|
||||
**Template structure:**
|
||||
```markdown
|
||||
## Problem
|
||||
{ai-synthesized one-paragraph problem statement, pulling from session description + incident header}
|
||||
|
||||
## What we confirmed
|
||||
{bulleted list of session_facts, grouped by source_type}
|
||||
|
||||
## Root cause
|
||||
{ai-synthesized from the active suggested fix + facts}
|
||||
|
||||
## Resolution
|
||||
{description of the fix applied, parameters used if a script ran, outcome}
|
||||
```
|
||||
|
||||
The service pulls from four data sources: `ai_sessions`, `session_facts`, `session_suggested_fixes` (active), and `script_generations` (if scripts ran during the session). Passwords in script_generations.parameters_used must be redacted (already a Script Generator pattern per the existing plan).
|
||||
|
||||
**Critical:** This service is called on every fact/suggestion change to keep the preview live. Cache aggressively — LLM calls for every keystroke will blow the budget. Invalidate the cache on any write to session_facts or session_suggested_fixes.
|
||||
|
||||
### 6.3 `EscalationPackageGeneratorService` (new)
|
||||
|
||||
**Location:** `services/escalation_package_generator.py`
|
||||
|
||||
Same structure as ResolutionNoteGenerator but with a handoff-oriented template:
|
||||
|
||||
```markdown
|
||||
## Problem
|
||||
...
|
||||
|
||||
## What we've confirmed
|
||||
...
|
||||
|
||||
## What we've tried
|
||||
{list of diagnostic_checks run with their outcomes, scripts generated}
|
||||
|
||||
## Current hypothesis
|
||||
{active suggested fix description}
|
||||
|
||||
## Suggested next steps
|
||||
{ai-synthesized from the gap between facts and a complete resolution}
|
||||
```
|
||||
|
||||
### 6.4 `TemplateExtractionService` (new)
|
||||
|
||||
**Location:** `services/template_extraction_service.py`
|
||||
|
||||
**Purpose:** Given a concrete rendered script and session context, propose a parameterization.
|
||||
|
||||
**Input:** `{script_body: str, session_context: dict, ticket_context: dict}`
|
||||
**Output:** `{parameters: [{key, label, type, inferred_from}], templated_body: str}`
|
||||
|
||||
**Implementation approach:**
|
||||
- LLM call with a structured prompt: "Given this script that resolved a ticket, identify values that would change for a different invocation. Propose a parameter schema following the Script Generator conventions (text / password / select / boolean / multi_text / number / textarea)."
|
||||
- Post-process to ensure the proposed template renders back to the original script when given the extracted parameter values.
|
||||
- Conservative default: prefer fewer parameters. If a value looks environment-agnostic (e.g. a command name), don't parameterize it.
|
||||
|
||||
This service is the engine behind Option 2 and Option 3 of the three-option dialog, and behind the post-resolve templatize prompt.
|
||||
|
||||
### 6.5 Extend `PSAWritebackService` (existing)
|
||||
|
||||
Add methods:
|
||||
- `post_resolution_note(session_id, markdown) -> {external_id, posted_at}`
|
||||
- `post_escalation_package(session_id, markdown) -> {external_id, posted_at}`
|
||||
- `transition_ticket_status(ticket_ref, new_status) -> {success, verified_status}`
|
||||
|
||||
The `transition_ticket_status` method must verify the status change took effect (per the existing ConnectWise integration principle: "never told 'success' when CW silently rejected the change").
|
||||
|
||||
### 6.6 Model selection per service
|
||||
|
||||
Each AI-calling service must use a configurable model string from application settings, not a hardcoded model. Use these defaults:
|
||||
|
||||
```python
|
||||
FACT_SYNTHESIS_MODEL = "claude-haiku-4-5-20251001" # short transformation, latency-sensitive
|
||||
RESOLUTION_NOTE_MODEL = "claude-sonnet-4-6" # customer-facing artifact, quality matters
|
||||
ESCALATION_PACKAGE_MODEL = "claude-sonnet-4-6" # same
|
||||
TEMPLATE_EXTRACTION_MODEL = "claude-sonnet-4-6" # creates persistent library artifact
|
||||
MAIN_CONVERSATION_MODEL = "claude-sonnet-4-6" # primary FlowPilot chat
|
||||
```
|
||||
|
||||
Do not hardcode model strings at call sites. Every new service must read from settings with a service-specific key.
|
||||
|
||||
**Instrumentation requirement:** log a `disputed_fact_rate` metric for fact synthesis — the percentage of AI-synthesized facts that engineers subsequently edit or delete. If this exceeds 10% over a 500-session window, escalate `FACT_SYNTHESIS_MODEL` to `claude-sonnet-4-6`. If under 5%, Haiku is performing correctly.
|
||||
|
||||
Do not use Opus 4.7 for any of these services at current scale.
|
||||
|
||||
---
|
||||
|
||||
## 7. Frontend components
|
||||
|
||||
### 7.1 Routes to change
|
||||
|
||||
| Current route | New route | Action |
|
||||
|---|---|---|
|
||||
| `/assistant` | `/pilot` | **Rename** the route. The existing page moves. `/assistant` permanently redirects to `/pilot` with no sunset date. |
|
||||
| `/pilot` (if it exists as a separate guided flow) | REMOVED | Collapse into the unified surface. |
|
||||
| `/pilot/session/:id` | `/pilot/session/:id` | No change (this is where the unified session UI lives) |
|
||||
|
||||
Sidebar nav entry renames from "ResolutionAssist" to "FlowPilot" with the cockpit icon.
|
||||
|
||||
### 7.2 New React components
|
||||
|
||||
Under `src/components/pilot/`:
|
||||
|
||||
```
|
||||
TaskLane.tsx -- The right-side panel, owns all four sections
|
||||
sections/
|
||||
WhatWeKnow.tsx -- New component for the facts list
|
||||
WhatWeKnowItem.tsx -- Single fact card with provenance line
|
||||
AddNoteButton.tsx -- "+ Add a note" inline composer
|
||||
Questions.tsx -- Existing questions rendering (moved if already present)
|
||||
DiagnosticChecks.tsx -- Existing checks rendering (moved if already present)
|
||||
SuggestedFix.tsx -- New or refactored component for the suggested fix card
|
||||
ResolveButton.tsx -- The Resolve CTA at the bottom of the task lane
|
||||
ResolutionNotePreview.tsx -- Floating popover anchored to Resolve button
|
||||
EscalatePackagePreview.tsx -- Same pattern for Escalate
|
||||
|
||||
ScriptGenInline/ -- Script Generator embedded in session context
|
||||
TemplateMatchPanel.tsx -- Scene 1 mockup: template pre-filled
|
||||
NoTemplateDialog.tsx -- Scene 2 mockup: three-option dialog
|
||||
TemplatizePrompt.tsx -- Scene 3 mockup: post-resolve prompt
|
||||
ParameterizationPreview.tsx -- Shared component: script with highlighted params
|
||||
```
|
||||
|
||||
### 7.3 Component behavior contracts
|
||||
|
||||
**`WhatWeKnowItem`**
|
||||
- Props: `{fact: SessionFact, onEdit, onDelete}`
|
||||
- Renders the fact text, a green checkmark, and the provenance line with source-type color coding
|
||||
- Clicking the fact text opens inline edit (only for `user_note` and `ai_synthesis` sources — question/check facts are read-only, edit the source instead)
|
||||
|
||||
**`TaskLane`**
|
||||
- Subscribes to a session state hook that polls for fact / question / check / suggested-fix updates
|
||||
- On any state change, calls `POST /api/v1/sessions/{id}/resolution-note/preview` to refresh the ResolutionNotePreview
|
||||
- Debounce preview refresh to 500ms to avoid LLM spam
|
||||
|
||||
**`NoTemplateDialog`** (three-option dialog)
|
||||
- Props: `{suggestedFix, onDecision}`
|
||||
- Renders the three cards with the middle (draft_template) marked as recommended
|
||||
- `onDecision` posts to `/api/v1/sessions/{id}/suggested-fixes/{fix_id}/decision` and either opens the Script Generator (one_off / draft_template) or navigates to full template creation (build_template)
|
||||
|
||||
**`TemplatizePrompt`**
|
||||
- Rendered after successful Resolve when a draft template exists for the session
|
||||
- Fetches proposed parameters from the draft template record
|
||||
- Save button posts to `/api/v1/draft-templates/{id}/accept`
|
||||
|
||||
---
|
||||
|
||||
## 8. AI prompt changes
|
||||
|
||||
The existing FlowPilot / ResolutionAssist system prompt needs updates to emit the new markers.
|
||||
|
||||
### 8.1 New marker: `[PROMOTE]`
|
||||
|
||||
Used to surface facts to What we know. Syntax:
|
||||
|
||||
```
|
||||
[PROMOTE]
|
||||
source_type: question
|
||||
source_ref: {question_id}
|
||||
text: OWA login and send/receive confirmed working for jsmith
|
||||
summary: rules out tenant/license
|
||||
[/PROMOTE]
|
||||
```
|
||||
|
||||
The AI should emit `[PROMOTE]` blocks in the same message that answers or processes a question/check, so the fact appears in What we know simultaneously with the chat acknowledgment.
|
||||
|
||||
### 8.2 New marker: `[SUGGEST_FIX]`
|
||||
|
||||
```
|
||||
[SUGGEST_FIX]
|
||||
title: Clear cached credentials + rebuild Outlook profile
|
||||
description: Stale cached credential in Credential Manager is holding the pre-reset token...
|
||||
confidence: 94
|
||||
script_template_slug: clear-outlook-credentials # or omitted if no template match
|
||||
ai_drafted_script: | # only if no template match
|
||||
# Generated by FlowPilot...
|
||||
...
|
||||
[/SUGGEST_FIX]
|
||||
```
|
||||
|
||||
### 8.3 Removed markers
|
||||
|
||||
The old `[FORK]` marker from the ResolutionAssist prompt is removed. Forks were a Guided-mode concept; in the unified model, they're replaced by Questions with mutually exclusive answer options.
|
||||
|
||||
---
|
||||
|
||||
## 9. Implementation phases
|
||||
|
||||
Each phase ends with a git commit and verification step. Do not advance to the next phase until verification passes.
|
||||
|
||||
### Phase 0 — Prompt caching infrastructure (prerequisite)
|
||||
|
||||
A codebase audit revealed that prompt caching is only implemented in `assistant_chat_service.py` (the file being deprecated). Every other Anthropic API call site — including all of FlowPilot's 7 call sites through `AnthropicProvider` — is uncached. Phase 0 must land before Phase 2 starts because new services built in Phase 2 will inherit caching from `AnthropicProvider` automatically once it's fixed.
|
||||
|
||||
**Deliverables:**
|
||||
|
||||
- **0.1** Promote `AnthropicProvider.generate_json()` and `generate_text_stream()` in `ai_provider.py` to the cached pattern currently implemented in `assistant_chat_service.py:_call_anthropic_cached()`. Convert the `system` string parameter to a structured system block list with `cache_control: {"type": "ephemeral"}` on the static portion. Add a second breakpoint on the last history message. For the streaming variant, capture the final usage object via `get_final_message()`. Log `cache_read_input_tokens` and `cache_creation_input_tokens` on every response.
|
||||
- **0.2** Update `integrations.py:557` (`/tickets/ai-parse`) to move the members list and team-stable boards data into a cached system block.
|
||||
- **0.3** Add `cache_control` to one-shot generators: `ai_tree_generator`, `kb_conversion`, `ai_fix`, `script_builder`. Same pattern as 0.1.
|
||||
- **0.4** Extract the caching logic from `assistant_chat_service.py:_call_anthropic_cached()` into `AnthropicProvider` and delete `_call_anthropic_cached`. `assistant_chat_service` should call the provider like every other service. This prevents two canonical implementations of the same pattern.
|
||||
|
||||
**Verification:**
|
||||
|
||||
- Hit any FlowPilot endpoint twice within 5 minutes. First call shows `cache_creation_input_tokens > 0`, second call shows `cache_read_input_tokens > 0`.
|
||||
- If the second call returns zero cache reads, inspect the prefix for silent invalidators (timestamps, unsorted JSON keys, varying tool list ordering). Fix before proceeding.
|
||||
|
||||
```
|
||||
git commit -m "feat(ai): promote AnthropicProvider to cached pattern, consolidate caching implementation"
|
||||
```
|
||||
|
||||
**Dependencies:**
|
||||
|
||||
- Phase 1 (route rename and schema) can run in parallel with Phase 0.
|
||||
- Phase 2 (What we know) must not start until Phase 0 is complete and verified.
|
||||
|
||||
### Phase 1 — Data model and route rename (backend + routing only)
|
||||
|
||||
**Deliverables:**
|
||||
- Alembic migration creating `session_facts`, `session_suggested_fixes`, `draft_templates` tables and the column additions to `ai_sessions`, `script_templates`, `account_settings`
|
||||
- All tables include `account_id` and have RLS policies following the multi-tenant architecture (per existing project standard)
|
||||
- `/assistant` → `/pilot` route rename with permanent redirect (stays in place indefinitely; no sunset date)
|
||||
- Sidebar nav entry rename
|
||||
- No UI changes yet beyond the nav label
|
||||
|
||||
**Verification:**
|
||||
- Run migration on a fresh dev database
|
||||
- Confirm RLS policies active via the existing CI grep check for `tenant_filter()`
|
||||
- Navigate to `/assistant` — should 301 to `/pilot`
|
||||
- Navigate to `/pilot` — should render the existing ResolutionAssist UI with the sidebar entry now reading "FlowPilot"
|
||||
|
||||
```
|
||||
git commit -m "feat(pilot): rename /assistant to /pilot, add session_facts + suggested_fixes + draft_templates schema"
|
||||
```
|
||||
|
||||
### Phase 2 — What we know (task lane + service + API)
|
||||
|
||||
**Deliverables:**
|
||||
- `FactSynthesisService` and its LLM prompt
|
||||
- Fact CRUD API endpoints
|
||||
- `WhatWeKnow`, `WhatWeKnowItem`, `AddNoteButton` components
|
||||
- Task lane layout adjustment: What we know section renders above Questions
|
||||
- Counter in task lane header updates to `X / Y answered` format
|
||||
- AI prompt updated to emit `[PROMOTE]` markers; backend parses them and creates facts
|
||||
|
||||
**Verification:**
|
||||
- Open a session, answer a question; within 2 seconds a fact should appear in What we know with correct provenance
|
||||
- Click "+ Add a note", type a manual fact, confirm it appears with `source_type: user_note`
|
||||
- Run a diagnostic check, confirm the check result promotes to a fact
|
||||
- Facts persist across page reloads
|
||||
- RLS: a user from a different account cannot read or write facts for this session
|
||||
|
||||
```
|
||||
git commit -m "feat(pilot): add What we know section with fact synthesis"
|
||||
```
|
||||
|
||||
### Phase 3 — Suggested fix + resolution note preview
|
||||
|
||||
**Deliverables:**
|
||||
- `session_suggested_fixes` API endpoints and data flow
|
||||
- `SuggestedFix` component in the task lane
|
||||
- AI prompt updated to emit `[SUGGEST_FIX]` markers
|
||||
- `ResolutionNoteGeneratorService` and preview endpoint
|
||||
- `ResolutionNotePreview` floating popover anchored to Resolve button
|
||||
- Preview refreshes on fact / suggested-fix changes (debounced)
|
||||
|
||||
**Verification:**
|
||||
- Session with ≥3 facts and an active suggested fix shows a populated Resolve preview
|
||||
- Editing a fact updates the preview within 1 second
|
||||
- Preview markdown renders correctly with all four sections (Problem / What we confirmed / Root cause / Resolution)
|
||||
- Preview contains no hallucinated information not present in session state (human review of 5 real-ish sessions)
|
||||
|
||||
```
|
||||
git commit -m "feat(pilot): add suggested fix tracking and Resolve note preview"
|
||||
```
|
||||
|
||||
### Phase 4 — Resolve and Escalate PSA writebacks
|
||||
|
||||
**Deliverables:**
|
||||
- `transition_ticket_status` method with CW verification
|
||||
- `post_resolution_note` endpoint and CW integration
|
||||
- Resolve button fires: post note → transition status → mark session resolved → show templatize prompt (if applicable)
|
||||
- `EscalationPackageGeneratorService` and parallel flow for Escalate
|
||||
- Escalate button fires: post package → transition status → mark session escalated → route via CW rules
|
||||
|
||||
**Verification:**
|
||||
- Complete a session end-to-end with a ConnectWise test instance
|
||||
- Click Resolve, edit the preview, confirm post — verify the note appears in CW and status changes to Resolved
|
||||
- Click Escalate on a different session — verify the package is posted and the ticket routes correctly
|
||||
- Attempt to Resolve without a linked PSA ticket — should mark the session resolved without erroring, note stored in `resolution_note_markdown` only
|
||||
|
||||
```
|
||||
git commit -m "feat(pilot): wire Resolve and Escalate to ConnectWise writeback"
|
||||
```
|
||||
|
||||
### Phase 5 — Script Generator inline integration
|
||||
|
||||
**Deliverables:**
|
||||
- `ScriptGenInline/TemplateMatchPanel` — when suggested fix has `script_template_id`, clicking the fix opens this panel with pre-filled parameters from session context
|
||||
- Parameter pre-fill logic: pulls from session facts, ticket context (company configs), and AI-suggested values in the `[SUGGEST_FIX]` marker
|
||||
- `ScriptGenInline/NoTemplateDialog` — three-option dialog when no template match
|
||||
- User decision persisted on `session_suggested_fixes.user_decision`
|
||||
- `TemplateExtractionService` for generating parameterization proposals
|
||||
- Script generation flow produces a `script_generations` record linked to the session (existing Script Generator behavior)
|
||||
|
||||
**Verification:**
|
||||
- Session with a template-matched suggested fix: clicking opens generator with ≥2 pre-filled parameters
|
||||
- Session with a custom script suggested fix: dialog appears with three options, script preview shows parameters highlighted
|
||||
- All three paths end correctly: one-off generates and closes, draft creates `draft_templates` row and generates, build_template opens full template creation
|
||||
- `⌘K` → "script" anywhere in a session opens the generator directly
|
||||
|
||||
```
|
||||
git commit -m "feat(pilot): integrate Script Generator inline with suggested fixes"
|
||||
```
|
||||
|
||||
### Phase 6 — Post-resolve templatize prompt
|
||||
|
||||
**Deliverables:**
|
||||
- `TemplatizePrompt` component
|
||||
- Logic: after Resolve success, check for pending `draft_templates` rows for this session; if any, show the prompt
|
||||
- Accept flow creates a new `script_templates` row with `source_session_id`, `source_user_id`, `source_ticket_ref` set
|
||||
- "Don't ask me again" writes to `account_settings.templatize_prompt_enabled`
|
||||
- Script Library sidebar shows a small badge when `draft_templates` with `status='pending'` exist for the current user
|
||||
|
||||
**Verification:**
|
||||
- Resolve a session where the engineer picked Option 2 — templatize prompt appears with AI-proposed parameters
|
||||
- Accept the prompt — new template appears in the Script Library with the provenance chip ("generated from CW #...")
|
||||
- Skip the prompt — draft marked rejected, Script Library shows no new template
|
||||
- Toggle "don't ask me again" — next session Resolve skips the prompt even with a pending draft
|
||||
|
||||
```
|
||||
git commit -m "feat(pilot): add post-resolve templatize prompt for draft templates"
|
||||
```
|
||||
|
||||
### Phase 7 — Polish
|
||||
|
||||
**Deliverables:**
|
||||
- Visual polish against the mockup files (spacing, colors, animations)
|
||||
- Loading states for LLM calls (fact synthesis, preview generation, template extraction)
|
||||
- Empty states (new session with no facts yet, no active suggested fix, no draft templates pending)
|
||||
- Keyboard shortcuts: `⌘K` (command menu), `⌘↵` (send composer), `⌘G` (generator), `⌘R` (resolve with confirm)
|
||||
- Responsive behavior: task lane collapses on <1200px viewports into a bottom drawer
|
||||
|
||||
**Verification:**
|
||||
- Compare each major screen side-by-side with the mockup PNG files — colors, spacing, typography within 5px / exact color match
|
||||
- All flows work on a 1280px viewport without horizontal scroll
|
||||
- Keyboard shortcuts documented in-app via `?` overlay
|
||||
|
||||
```
|
||||
git commit -m "feat(pilot): visual polish and keyboard shortcuts"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Design system reference
|
||||
|
||||
All components must use the existing ResolutionFlow design system. Pulling the key tokens from the mockup CSS for quick reference — these should already exist in your tokens file; if they don't, add them:
|
||||
|
||||
```css
|
||||
/* Backgrounds */
|
||||
--bg-0: #070b12; /* page background */
|
||||
--bg-1: #0d131c; /* sidebar / chrome */
|
||||
--bg-2: #121a25; /* card / bubble background */
|
||||
--bg-3: #1a2332; /* raised element */
|
||||
|
||||
/* Borders */
|
||||
--border: rgba(148, 163, 184, 0.12);
|
||||
--border-strong: rgba(148, 163, 184, 0.22);
|
||||
|
||||
/* Text */
|
||||
--text-primary: #e2e8f0;
|
||||
--text-secondary: #94a3b8;
|
||||
--text-tertiary: #64748b;
|
||||
|
||||
/* Brand cyan (FlowPilot accent) */
|
||||
--cyan-400: #22d3ee;
|
||||
--cyan-500: #06b6d4;
|
||||
--cyan-600: #0891b2;
|
||||
--cyan-bg: rgba(34, 211, 238, 0.10);
|
||||
--cyan-border: rgba(34, 211, 238, 0.30);
|
||||
|
||||
/* Semantic */
|
||||
--success: #34d399; /* Resolve, facts */
|
||||
--warning: #fbbf24; /* Escalate, proposed parameters */
|
||||
--danger: #f87171;
|
||||
--purple: #a78bfa; /* Script Generator / templates */
|
||||
```
|
||||
|
||||
**Typography:**
|
||||
- Body: IBM Plex Sans, 14px/1.5
|
||||
- Headings: Bricolage Grotesque, 500 weight, -0.01em letter-spacing
|
||||
- Code: JetBrains Mono
|
||||
|
||||
**Icons:** Phosphor Icons (Duotone) per the memory-recorded design decision to migrate off Lucide.
|
||||
|
||||
---
|
||||
|
||||
## 11. Non-goals for this migration
|
||||
|
||||
Do not build these as part of this work. They belong to later phases of the roadmap.
|
||||
|
||||
- **Confidence tiers (Discovery / Exploring / Guided).** We explicitly removed these. The task lane itself is the progress signal.
|
||||
- **Mode toggle between Guided and Quick ask.** There is one mode.
|
||||
- **"Convert to guided" promotion flow.** No longer applicable.
|
||||
- **Team Wiki compilation from resolved sessions.** Tracked separately; depends on this migration but is not part of it.
|
||||
- **SharePoint integration.** Sequenced after ConnectWise per roadmap.
|
||||
- **Template marketplace / sharing across accounts.** Tracked under Client Context System roadmap item.
|
||||
|
||||
---
|
||||
|
||||
## 12. Risks and mitigations
|
||||
|
||||
| Risk | Mitigation |
|
||||
|---|---|
|
||||
| LLM fact synthesis hallucinates specifics not in the answer | Conservative prompt; engineer can edit/delete any AI-synthesized fact; provenance line shows the source so the engineer can verify |
|
||||
| Resolution note preview LLM cost at scale | Cache aggressively, invalidate only on session state write; debounce UI updates to 500ms; consider lower-tier model for preview generation (final post-to-CW version can use the better model) |
|
||||
| ConnectWise silently rejects status change | `transition_ticket_status` must re-fetch and verify; fail loudly if the change didn't stick |
|
||||
| Template extraction proposes bad parameterization | Engineer reviews before saving; draft templates never silently become real templates; provenance chip lets team admins audit |
|
||||
| Users lose muscle memory from `/assistant` → `/pilot` rename | Permanent redirect (no sunset date); inline toast on first `/pilot` visit explaining the rename |
|
||||
| Existing sessions have no `session_facts` entries, so What we know is empty | Acceptable — Phase 2 deliberately does not backfill; facts only accumulate for new or ongoing sessions after deploy. Document in release notes. |
|
||||
|
||||
---
|
||||
|
||||
## 13. Questions for Michael before implementation starts
|
||||
|
||||
These are the decisions Claude Code cannot make unilaterally. Answer these inline in the doc or in chat before kicking off Phase 1.
|
||||
|
||||
1. **Keyboard shortcut for Resolve** — I've proposed `⌘R` (with a confirm). Browsers intercept `⌘R` for page reload. Alternative: `⌘⇧R` or no shortcut. Preference?
|
||||
2. **Default `templatize_prompt_enabled` value** — I defaulted to `true`. If your beta testers find it annoying we'll learn fast, but it's a tradeoff between "every engineer sees the prompt" and "feature gets discovered only by those who know about it".
|
||||
3. **Resolution note posts immediately, or stage for review?** — Current design: engineer edits preview inline, clicks Confirm & post. Alternative: stage in CW as draft note for a supervisor to approve before posting. Affects MSPs with strict compliance.
|
||||
|
||||
---
|
||||
|
||||
## End of document
|
||||
1320
docs/FlowAssist_Migration/mockups/01-session-primary.html
Normal file
1320
docs/FlowAssist_Migration/mockups/01-session-primary.html
Normal file
File diff suppressed because it is too large
Load Diff
BIN
docs/FlowAssist_Migration/mockups/01-session-primary.png
Normal file
BIN
docs/FlowAssist_Migration/mockups/01-session-primary.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 505 KiB |
1516
docs/FlowAssist_Migration/mockups/02-04-script-integration.html
Normal file
1516
docs/FlowAssist_Migration/mockups/02-04-script-integration.html
Normal file
File diff suppressed because it is too large
Load Diff
BIN
docs/FlowAssist_Migration/mockups/02-script-template-match.png
Normal file
BIN
docs/FlowAssist_Migration/mockups/02-script-template-match.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 282 KiB |
BIN
docs/FlowAssist_Migration/mockups/03-script-three-options.png
Normal file
BIN
docs/FlowAssist_Migration/mockups/03-script-three-options.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 341 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 381 KiB |
Reference in New Issue
Block a user