From ce118b51d880b983b8b5555e4cc6906f74dffdcb Mon Sep 17 00:00:00 2001 From: chihlasm Date: Thu, 19 Mar 2026 03:10:11 +0000 Subject: [PATCH] fix(flowpilot): fix 4 Phase 2 escalation bugs + update Tailwind version in CLAUDE.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix escalation status mismatch: hook set 'escalated' but backend returns 'requesting_escalation' - Fix list_sessions to include sessions picked up by Engineer B via escalation_package->>'picked_up_by' JSONB query - Fix sidebar escalation icon color: was Tailwind class 'text-amber-400' passed to style={{color}}, now hex '#fbbf24' - Replace window.location.reload() after ticket linking with onReloadSession callback to preserve session state - Update CLAUDE.md: Tailwind CSS v3 → v4 (@tailwindcss/vite, CSS-only config) Co-Authored-By: Claude Opus 4.6 (1M context) --- CLAUDE.md | 6 +++--- backend/app/api/endpoints/ai_sessions.py | 12 +++++++++--- .../src/components/flowpilot/FlowPilotSession.tsx | 6 +++++- frontend/src/components/layout/Sidebar.tsx | 4 ++-- frontend/src/hooks/useFlowPilotSession.ts | 2 +- frontend/src/pages/FlowPilotSessionPage.tsx | 1 + 6 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 1da4cc4e..5caf510b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -23,7 +23,7 @@ - **Fonts:** Bricolage Grotesque (`font-heading`, headings/titles), IBM Plex Sans (`font-sans`, body text), JetBrains Mono (`font-label`, labels/badges/timestamps) — loaded via Google Fonts - **Logo:** Inline SVG in `BrandLogo.tsx` (decision-tree icon with cyan gradient). Wordmark: "Resolution" in `text-foreground` + "Flow" in `text-gradient-brand` - **Brand assets:** `brand-assets/` (source SVGs + brand-guide.html), `frontend/src/assets/brand/` (app assets), `frontend/public/icons/` (favicon) -- **CSS utilities:** `text-gradient-brand`, `bg-gradient-brand`, `bg-gradient-brand-hover` (defined in `tailwind.config.js` and `index.css`). Glass utilities: `.glass-card` (interactive, `scale(1.02)` hover), `.glass-card-static` (no hover transform), `.active-glow` (breathing cyan shadow) +- **CSS utilities:** `text-gradient-brand`, `bg-gradient-brand`, `bg-gradient-brand-hover` (defined in `index.css` via `@theme`). Glass utilities: `.glass-card` (interactive, `scale(1.02)` hover), `.glass-card-static` (no hover transform), `.active-glow` (breathing cyan shadow) - **Layout:** App shell with persistent sidebar + top bar + main content (CSS Grid). Two fixed atmosphere orbs (cyan top-right, purple bottom-left) behind the shell for ambient glow. See [UI-DESIGN-SYSTEM.md](UI-DESIGN-SYSTEM.md) - **Navigation:** Sidebar nav with type sub-items (All Flows → Troubleshooting / Projects / Maintenance). Pinned flows section for quick access. NO workspace switcher. See [UI-DESIGN-SYSTEM.md](UI-DESIGN-SYSTEM.md) - **Terminology:** User-facing label is "Flows" (not "Trees"). Procedural flows are called "Projects" in the UI. Maintenance flows are called "Maintenance" in the UI. `tree_type` column values unchanged in DB. @@ -91,7 +91,7 @@ When adding new pages/components: use "ResolutionFlow" branding, ice-cyan gradie ### Frontend - **Framework:** React 19 + Vite + TypeScript -- **Styling:** Tailwind CSS v3 — dark-first with purple gradient accents (see Branding section) +- **Styling:** Tailwind CSS v4 (`@tailwindcss/vite` plugin, CSS-only config in `index.css`) — dark-first with ice-cyan gradient accents (see Branding section) - **State:** Zustand (with immer + zundo for undo/redo) - **Routing:** React Router v7 - **API Client:** Axios with token refresh interceptor @@ -124,7 +124,7 @@ patherly/ │ │ ├── pages/ # All page components │ │ ├── store/ # Zustand stores (auth, treeEditor, proceduralEditor, userPreferences) │ │ └── types/ # TypeScript interfaces -│ └── tailwind.config.js +│ └── (Tailwind v4: CSS-only config in src/index.css) ├── docs/plans/archive/ # Archived design/impl docs (pre-March 2026) ├── CLAUDE.md # This file ├── CURRENT-STATE.md # Detailed feature status diff --git a/backend/app/api/endpoints/ai_sessions.py b/backend/app/api/endpoints/ai_sessions.py index 54bd548b..8bddc79d 100644 --- a/backend/app/api/endpoints/ai_sessions.py +++ b/backend/app/api/endpoints/ai_sessions.py @@ -15,7 +15,7 @@ from typing import Annotated, Optional from uuid import UUID from fastapi import APIRouter, Depends, HTTPException, Query, Request, status -from sqlalchemy import select, func +from sqlalchemy import or_, select, func from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload @@ -465,10 +465,16 @@ async def list_sessions( skip: int = Query(0, ge=0), limit: int = Query(20, ge=1, le=100), ): - """List the current user's AI sessions.""" + """List the current user's AI sessions (owned or picked up).""" + user_id_str = str(current_user.id) query = ( select(AISession) - .where(AISession.user_id == current_user.id) + .where( + or_( + AISession.user_id == current_user.id, + AISession.escalation_package["picked_up_by"].as_string() == user_id_str, + ) + ) .order_by(AISession.created_at.desc()) .offset(skip) .limit(limit) diff --git a/frontend/src/components/flowpilot/FlowPilotSession.tsx b/frontend/src/components/flowpilot/FlowPilotSession.tsx index 8ddccfca..b3dcb80b 100644 --- a/frontend/src/components/flowpilot/FlowPilotSession.tsx +++ b/frontend/src/components/flowpilot/FlowPilotSession.tsx @@ -35,6 +35,7 @@ interface FlowPilotSessionProps { onPause?: () => Promise onResume?: () => Promise onRate: (rating: number) => void + onReloadSession?: () => Promise } export function FlowPilotSession({ @@ -54,6 +55,7 @@ export function FlowPilotSession({ onPause, onResume, onRate, + onReloadSession, }: FlowPilotSessionProps) { const scrollRef = useRef(null) const [showTicketPicker, setShowTicketPicker] = useState(false) @@ -87,7 +89,9 @@ export function FlowPilotSession({ }) toast.success(`Linked to ticket #${ticketId}`) // Reload session to get updated ticket_data - window.location.reload() + if (onReloadSession) { + await onReloadSession() + } } catch { toast.error('Failed to link ticket') } finally { diff --git a/frontend/src/components/layout/Sidebar.tsx b/frontend/src/components/layout/Sidebar.tsx index 7f1be0b0..c85a8d80 100644 --- a/frontend/src/components/layout/Sidebar.tsx +++ b/frontend/src/components/layout/Sidebar.tsx @@ -86,7 +86,7 @@ export function Sidebar() { - + @@ -136,7 +136,7 @@ export function Sidebar() { Resolve - + prev ? { ...prev, status: 'escalated' } : null) + setSession(prev => prev ? { ...prev, status: 'requesting_escalation' } : null) setDocumentation(result.documentation) setPsaPushStatus(result.psa_push_status) setPsaPushError(result.psa_push_error) diff --git a/frontend/src/pages/FlowPilotSessionPage.tsx b/frontend/src/pages/FlowPilotSessionPage.tsx index 72a88deb..8652990e 100644 --- a/frontend/src/pages/FlowPilotSessionPage.tsx +++ b/frontend/src/pages/FlowPilotSessionPage.tsx @@ -179,6 +179,7 @@ export default function FlowPilotSessionPage() { onPause={fp.pauseSession} onResume={fp.resumeOwnSession} onRate={fp.rateSession} + onReloadSession={() => fp.loadSession(fp.session!.id)} />