fix(flowpilot): fix 4 Phase 2 escalation bugs + update Tailwind version in CLAUDE.md
- 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) <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -35,6 +35,7 @@ interface FlowPilotSessionProps {
|
||||
onPause?: () => Promise<void>
|
||||
onResume?: () => Promise<void>
|
||||
onRate: (rating: number) => void
|
||||
onReloadSession?: () => Promise<void>
|
||||
}
|
||||
|
||||
export function FlowPilotSession({
|
||||
@@ -54,6 +55,7 @@ export function FlowPilotSession({
|
||||
onPause,
|
||||
onResume,
|
||||
onRate,
|
||||
onReloadSession,
|
||||
}: FlowPilotSessionProps) {
|
||||
const scrollRef = useRef<HTMLDivElement>(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 {
|
||||
|
||||
@@ -86,7 +86,7 @@ export function Sidebar() {
|
||||
<NavItem href="/pilot" icon={Sparkles} label="New Session" iconColor={NAV_COLORS.dashboard} collapsed />
|
||||
<NavItem href="/" icon={LayoutGrid} label="Dashboard" iconColor={NAV_COLORS.dashboard} collapsed />
|
||||
<NavItem href="/sessions" icon={Clock} label="Sessions" badge={stats?.active_count || undefined} iconColor={NAV_COLORS.sessions} collapsed />
|
||||
<NavItem href="/escalations" icon={AlertTriangle} label="Escalations" iconColor="text-amber-400" collapsed />
|
||||
<NavItem href="/escalations" icon={AlertTriangle} label="Escalations" iconColor="#fbbf24" collapsed />
|
||||
<NavItem href="/trees" icon={Network} label="All Flows" matchPaths={['/trees', '/flows']} iconColor={NAV_COLORS.flows} collapsed />
|
||||
<NavItem href="/assistant" icon={Brain} label="FlowPilot" iconColor={NAV_COLORS.flowPilot} collapsed />
|
||||
<NavItem href="/scripts" icon={Code2} label="Script Library" iconColor={NAV_COLORS.scripts} collapsed />
|
||||
@@ -136,7 +136,7 @@ export function Sidebar() {
|
||||
Resolve
|
||||
</div>
|
||||
<NavItem href="/sessions" icon={Clock} label="Sessions" badge={stats?.active_count || undefined} iconColor={NAV_COLORS.sessions} />
|
||||
<NavItem href="/escalations" icon={AlertTriangle} label="Escalations" iconColor="text-amber-400" />
|
||||
<NavItem href="/escalations" icon={AlertTriangle} label="Escalations" iconColor="#fbbf24" />
|
||||
<NavItem
|
||||
href="/trees"
|
||||
icon={Network}
|
||||
|
||||
@@ -151,7 +151,7 @@ export function useFlowPilotSession(): UseFlowPilotSession {
|
||||
setIsProcessing(true)
|
||||
try {
|
||||
const result = await aiSessionsApi.escalateSession(session.id, data)
|
||||
setSession(prev => 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)
|
||||
|
||||
@@ -179,6 +179,7 @@ export default function FlowPilotSessionPage() {
|
||||
onPause={fp.pauseSession}
|
||||
onResume={fp.resumeOwnSession}
|
||||
onRate={fp.rateSession}
|
||||
onReloadSession={() => fp.loadSession(fp.session!.id)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user