* feat: add device_types table with system seed data
Creates DeviceType SQLAlchemy model and migration 073 that provisions the
device_types table with 28 system-seeded device types across 7 categories
(network, compute, storage, cloud, endpoint, infrastructure, security).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add network_diagrams table
Create NetworkDiagram SQLAlchemy model with JSONB nodes/edges, team-scoped with client/asset metadata, and Alembic migration 074.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add Pydantic schemas for device types and network diagrams
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add device types CRUD router
Adds GET/POST/PUT/DELETE endpoints at /device-types with team-scoped access. System types are read-only; custom types are scoped to the creating team.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add AI generation service for network diagrams
Adds network_diagram_ai_service.py with generate_diagram() function that
calls the AI provider to convert plain-English network descriptions into
structured DiagramNode/DiagramEdge data. Registers the action in
ACTION_MODEL_MAP as a standard-tier route.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add network diagrams CRUD + AI generate + export/import router
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add TypeScript types for network diagrams
Adds all interfaces for network diagrams and device types including
DiagramNode, DiagramEdge, DeviceProperties, NetworkDiagramResponse,
AI generate request/response, import/export shapes, and list item types.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add frontend API clients for device types and network diagrams
Adds deviceTypesApi (list, create, update, remove) and networkDiagramsApi
(list, get, create, update, archive, duplicate, exportJson, importJson,
aiGenerate, listClients) following the existing apiClient module pattern.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add device registry, DeviceNode, ConnectionEdge for React Flow
Creates the React Flow building blocks for the network diagram editor:
device type registry with icon/color mappings, DeviceNode component with
status indicators and connection handles, ConnectionEdge with per-type
styling, and nodeTypes/edgeTypes registration maps.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add DeviceToolbar panel with search, categories, drag-drop, custom type creation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add PropertiesPanel for node and edge property editing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add AIAssistPanel with replace and merge modes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add NetworkCanvas wrapper and DiagramHeader components
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add DiagramEditor page assembling all panels with auto-save and AI generation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add Network Diagrams list page with search, client filter, import
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add Network Maps to sidebar navigation and router
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: resolve TypeScript errors in DeviceToolbar and DiagramEditor
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: resolve stale selection bug in network diagram PropertiesPanel
Selection state now stores IDs and derives objects from live arrays,
so edits in PropertiesPanel inputs reflect immediately.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add React Flow UI foundation components for network diagrams
BaseNode (structured node shell with header/content/footer slots),
BaseHandle (styled connection handle), LabeledHandle (handle with
port label), NodeStatusIndicator (status border effect),
NodeTooltip (hover details via NodeToolbar).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add LabeledGroupNode and AnimatedSvgEdge components
GroupNode for subnet/VLAN/site grouping with positioned label badge.
AnimatedSvgEdge for traffic flow visualization with animated SVG
shape along edge path. Both registered in type maps.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: DeviceNode uses BaseNode, BaseHandle, StatusIndicator, Tooltip
Replaces hand-rolled node layout with composable React Flow UI
components. Status is now a border effect instead of a dot.
Hover tooltip shows hostname, IP, vendor, role, notes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add grouping toolbar items and traffic flow toggle
DeviceToolbar gets Subnet/VLAN/Site/DMZ grouping section with
drag-drop. PropertiesPanel gets Show Traffic toggle that switches
edges between connection and animated types. DiagramEditor handles
both device and group node drops.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address code review findings for React Flow UI integration
- Use screenToFlowPosition() for drop coordinates (fixes zoom/pan bug)
- Remove duplicate selection border from DeviceNode (BaseNode handles it)
- Add w-full to GroupNode for proper container sizing
- Remove unused 'selected' destructuring from DeviceNode
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add ISP icon to network diagram device registry
Globe icon with accent color, under cloud category.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: improve drag-and-drop feel in network diagram editor
Grip icons on draggable toolbar items, press effect on drag start,
dashed border overlay with 'Drop to add' text when dragging over canvas.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add ContextMenu component for network diagram editor
Charcoal-styled context menu with action factories for node
and canvas variants. Viewport-clamped positioning, auto-dismiss
on click outside, escape, or scroll.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add useCanvasShortcuts hook for copy/paste/duplicate
Keyboard shortcuts with preventDefault and input guard.
Clipboard stores nodes with relative positions and edge indices.
Paste computes canvas center via screenToFlowPosition.
Duplicate offsets +30px. Supports both device and group nodes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: wire context menu and keyboard shortcuts into diagram editor
Right-click context menus for nodes (copy/duplicate/delete) and
canvas (paste/select-all/fit-view). Right-click selects the node
per spec. serializeNodes now handles group nodes correctly.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: context menu dismisses on pane click, ISP in toolbar
Context menu now closes when clicking anywhere on the canvas via
onPaneClick prop. ISP device added as built-in toolbar item under
Internet section so it's always available without a database entry.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: backend code review fixes for network diagrams
- Replace legacy Optional imports with modern str | None syntax
- Type JSONB columns as Mapped[list[dict[str, Any]]]
- Escape SQL LIKE wildcards (%, _) in diagram search
- Type DiagramNode.position as Position(x, y) Pydantic model
- Wrap AI response parsing in KeyError handler for clean 422 errors
- Remove unused Optional/TYPE_CHECKING imports from schemas/models
- Extract _get_available_slugs helper to DRY duplicate queries
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: network diagram editor UX — straight edges, snap-to-grid, ISP in Cloud, group resize
- Straight edges: replace SmoothStepEdge with BaseEdge + getStraightPath so
connections draw direct diagonal lines instead of orthogonal bent paths
- Snap-to-grid: add snapToGrid/snapGrid=[20,20] to NetworkCanvas so nodes
align consistently when dragged
- ISP in Cloud: remove standalone "Internet" sidebar section, inject ISP into
the Cloud category loop with search support and correct item count
- Group node resize: add NodeResizer to GroupNode (subnet/VLAN/site/DMZ),
handles visible when selected; dimensions saved/restored correctly on
reload (also fixes group node load bug where type was always 'device')
- DiagramNode type: add nodeType and style optional fields
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: network diagram team_id guard + multi-style edge routing
Backend:
- Guard create_diagram with 422 if current_user.team_id is None (prevents
NOT NULL constraint crash for accounts not yet assigned to a team)
- Add routing field to DiagramEdge schema (straight/curved/step)
Frontend:
- ConnectionEdge now supports straight (default), curved (bezier), and
step (smooth-step) routing per-edge via routing field in edge data
- PropertiesPanel Connection section gets a Line Style toggle:
Straight | Curved | Step buttons, active state highlights in accent
- handleEdgeUpdate and serializeEdges now propagate the routing field
- DiagramEdge type gets optional routing field
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: network diagrams UX overhaul — icons, empty canvas, properties panel
- Colorize: semantic category colors for all device types (network=blue,
security=orange, compute=emerald, endpoint=amber, storage=violet,
cloud=cyan, infra=steel); better icons (Router, ShieldAlert, Boxes,
Package, Gauge, PlugZap, Video, Radio); MiniMap uses category colors
- Onboard: centered AI generate prompt on empty canvas with 5 MSP-specific
example chips, ⌘↵ shortcut, spinner; AIAssistPanel only shown with nodes
- Arrange: properties panel — status badge grid at top, fields grouped into
Network (IP/Subnet/VLAN) and Hardware (Hostname/Vendor/Model/Role) sections
- Delight: segmented topology color bar on listing cards; backend returns
category_counts via single extra query on list endpoint
- Harden: real PNG export via html-to-image + getNodesBounds/getViewportForBounds
- Polish: ChevronDown replaces unicode ▾, click-outside for client filter,
consistent spinner in empty prompt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: drop changelog noise from network extraction
* fix: align network map builder with account isolation
* feat: add manual create option for network maps
* feat: make manual network map creation easier to discover
* fix(network-maps): address design critique — harden, normalize, clarify, polish
- Archive: two-step inline confirm in card dropdown menu
- Delete Device/Edge: two-step inline confirm in PropertiesPanel footer
- Context menu Delete: floating confirm bar instead of immediate deletion
- AI Generate New: two-step confirm when replacing existing diagram nodes
- DiagramHeader: show 'Unsaved changes' in amber when isDirty and not saving
- deviceRegistry: SECURITY_COLOR #f97316 → #f87171 (deprecated ember orange removed)
- CanvasEmptyPrompt: remove backdrop-blur (design system violation)
- CanvasEmptyPrompt: remove redundant 'Skip AI' bottom button (duplicate of Build manually card)
- CanvasEmptyPrompt: rounded-xl/rounded-2xl → rounded-lg, border-2 → border
- Topology bar: h-1 → h-2 + native tooltip with category breakdown
- AIAssistPanel: replace pulse-dot loading with spinner (consistent with rest of feature)
- ContextMenu: add shadow-lg (consistent with other dropdowns)
- DeviceNode tooltip: Position.Bottom → Position.Top (avoids canvas-edge clipping)
- CanvasEmptyPrompt: raise ⌘↵ hint from /50 opacity to full text-muted-foreground
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(network-maps): bring to front / send to back layering for nodes
Three entry points for z-index control:
- Right-click context menu: Bring to Front / Send to Back with ] / [ shortcuts, separated by dividers from copy/delete groups
- Properties panel: Layer row with Bring Front + Send Back buttons, tooltip shows keyboard shortcut
- Keyboard: ] brings selected node(s) to front, [ sends to back (skips when input focused)
Context menu also gains divider support (dividerBefore flag) for visual grouping.
Layering handlers use max/min zIndex across all nodes so repeated presses always stack correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: swap switch icon from Layers → Network (Lucide)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: icon size picker (S/M/L) on device nodes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: drag-to-resize device nodes + BrickWallFire for firewall
- NodeResizer on DeviceNode (same pattern as group nodes); icon scales
proportionally with node width, clamped 16–60px
- Removes S/M/L static picker — resize is now direct manipulation
- firewall: ShieldAlert → BrickWallFire
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: trigger Railway rebuild
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: add missing hero_001.jpg to git (was untracked, broke Railway deploy)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: ShieldAlert still referenced in CATEGORY_DEFAULTS after icon swap
Removed ShieldAlert from imports when swapping firewall icon to BrickWallFire
but left it in CATEGORY_DEFAULTS — runtime crash, device toolbar empty.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(network): proportional node resize with locked aspect ratio
Nodes grew into rectangles because NodeResizer had no aspect ratio
constraint, minWidth != minHeight, and icon/text only scaled from width.
- DeviceNode: add keepAspectRatio + equal minWidth/minHeight (80×80),
maxWidth/maxHeight (280×280), scale icon and label/IP font sizes from
Math.min(width, height) so all content grows uniformly
- DiagramEditor: set explicit 120×120 style on dropped device nodes so
React Flow has a definite starting size for aspect ratio calculation
- DiagramEditor: persist device node style (width/height) in
serializeNodes and restore it on load so size survives save/reload
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(lint): suppress ESLint errors in network diagram components
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend: start_session, prepare_session, batch_launch_sessions all missing
account_id=current_user.account_id — Phase 1 NOT NULL constraint made these
500 in test suite (test_ratings.py fixture couldn't create sessions).
Frontend ESLint:
- TaskLane.tsx: suppress react-refresh/only-export-components for clearTaskState
- TeamSummary.tsx: init loading from isAccountOwner to avoid sync setState in effect
- ScriptBodyEditor.tsx: move lastValueRef.current assignment into useEffect
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three fixes from beta tester session feedback:
1. MCP error handling (backend/app/services/assistant_chat_service.py)
- The MCP Microsoft Learn integration was catching only BadRequestError.
Any other error type (APIStatusError, APIConnectionError, timeout) from
the external MCP server propagated as a 502, causing the generic error.
- Now catches all Exception types when MCP is active and retries without
MCP using the stable client.messages.create endpoint.
2. Frontend error UX (frontend/src/pages/AssistantChatPage.tsx)
- catch {} was silently swallowing all errors and inserting a generic
assistant message. Now: differentiates 429 (rate limit) vs 502/503
(AI unavailable), removes the optimistic user message on failure,
restores the failed message to the input so users can retry without
retyping, and logs errors to console for debugging.
3. Image attachments visible in chat (frontend/src/components/assistant/ChatMessage.tsx)
- Uploaded images were sent to the AI correctly but never shown in the
chat thread. Now captures preview URLs before clearing pendingUploads
and renders thumbnails above the user bubble, clickable to full size.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add persistent session header with title, status badge, Resolve,
Escalate, and Update Ticket/Share Update buttons — mirrors
FlowPilotSessionPage pattern exactly
- Update Ticket label when psa_ticket_id present, Share Update otherwise
- Full mobile support via ⋯ overflow menu (Resolve, Escalate, Update, Pause)
- Strip _(not yet completed)_ markers from stored conversation_messages
in unified_chat_service to prevent stale task lane items from prior
turns leaking into new sessions via the AI's re-include instruction
- Add currentChatRef guard to handleResumeNew (was missing unlike handleSend)
- Remove Update/Conclude from chatbar — toolbar is now input utilities only
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- .gitignore: keep both graphify-out/ entries and main's .gitnexus entry
- ScriptCodeBlock/ScriptPreviewModal: take main's border-border and text-accent-text
for filename labels; use neutral ghost style for Save button in ScriptCodeBlock;
use bg-accent (normalized from bg-primary) for Save button in ScriptPreviewModal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous fix (990f044) moved state clears before the createChatSession
await but left currentChatRef.current pointing at the old session during the
entire network call. Any in-flight handleSend/handleTaskSubmit for the old
session would pass the guard (oldId === oldId) and re-apply stale task lane
data to the new empty session.
Setting currentChatRef.current = null before the await ensures in-flight
handlers from the previous session see a mismatch and bail — matching the
same pattern already used correctly in selectChat.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three race conditions in AssistantChatPage:
1. handleNewChat cleared showTaskLane/activeQuestions/activeActions
AFTER the createChatSession await — old lane was visible during
the network call. Moved clears before the await.
2. handleResumeNew never cleared old TaskLane state at all. Added
upfront clears before the first await.
3. handleSend and handleTaskSubmit had no stale-session guard. If
the user switched chats while sendChatMessage was in flight, the
response would set showTaskLane on the wrong session. Added
sentForChatId snapshot + currentChatRef guard (same pattern
already used in selectChat).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Import and call clearTaskState before updating questions/actions in
handleSend and handleTaskSubmit so new AI tasks always replace stale
sessionStorage cache instead of being overridden by it
- Include pending (not yet completed) tasks in the AI message on partial
submit so the AI knows which tasks were left unanswered
- Fix stale closure in TaskLane saveTaskLane useEffect — use refs for
questions/actions so the debounced backend save always uses current values
- Add responses field to pending_task_lane TypeScript type, removing the
unsafe double-cast in selectChat
- Instruct the AI to re-surface incomplete tasks unless ≥75% confident
the information is no longer needed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Reformat PSA resolution/escalation notes: clean single-line header,
steps with engineer responses inline, remove duplicate timing blocks,
remove AI confidence section, add follow-up recommendations
- Standardize time display to decimal hours (e.g. 0.25 hrs) across all
note formatters and status update context
- Add follow_up_recommendations to SessionDocumentation schema and
surface in SessionDocView; extracted from resolution suggestion steps
- Add _build_what_we_know() helper: uses session.evidence_items when
cockpit branch merges, falls back to deriving findings from steps
- Fix option label lookup in generate_status_update (was passing raw
machine values to AI instead of human-readable labels)
- Add 'What We Know' section to status update ticket notes prompt
- Improve _build_session_context in resolution_output_generator to
include intake text and full step details instead of truncated chat
- Add request_info audience type: client-facing information request
that skips the length step and generates a numbered question list
- Improve client_update and email_draft prompts with per-context
guidance (status/resolution/escalation) and fix escalation subject
line from 'Specialist Review' to 'Specialist Assistance'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
#60a5fa (electric blue) is a light colour — near-white and muted-foreground
text on it produced ~1.9–2.1:1 contrast, well below WCAG AA.
- TreeNavigationPage: option number badges + timer badge → text-[#0e1016]
- StepChecklist: active step was blue badge on blue row (invisible); now
inverts to navy circle with blue number when current, dark-on-blue otherwise
- StepDetail: step number circle → text-[#0e1016] (was near-white on light blue)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Added 'All Scripts' as the first/default tab (no mine/shared filter) so the
page opens with every script the user can access. My Scripts and Team Scripts
tabs remain for filtered views.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
setCategory and setSearch called loadTemplates() with no arguments, dropping
the mine/shared filter set by the active tab — causing the list to show all
templates instead of the current user's scripts after any filter interaction.
Store now persists tabFilters whenever loadTemplates is called with explicit
filters, and reuses them for subsequent no-arg calls from setCategory/setSearch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- script_builder endpoint: pg_advisory_xact_lock on user_id before
session count check, preventing concurrent creates from both passing
the MAX_SESSIONS_PER_USER guard
- script_builder_service send_message: pg_advisory_xact_lock on session_id
before message count check, preventing concurrent sends from both
passing the MAX_MESSAGES_PER_SESSION guard
- script_builder_service save_to_library: replace check-then-insert slug
logic with IntegrityError retry loop (3 attempts with fresh UUID suffix);
add unique constraint on script_templates.slug (migration 070)
- ScriptBuilderPage: add creatingSessionRef to serialize concurrent
handleSend calls that would otherwise both call createSession() while
session is still null
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Race condition: on page remount, selectChat(oldId) loads session data async.
If the user clicks New Chat before the API returns, the old session's
pending_task_lane was being applied to the new session's state, showing
stale tasks and blocking new ones from appearing.
Fix: currentChatRef tracks the most recently requested chat ID synchronously.
All chat-creation paths (selectChat, handleNewChat, handleResumeNew) update it
immediately. After each await in selectChat, bail if the ref no longer matches.
Also documents the pattern as Lesson 106 in CLAUDE.md for future reference.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
VITE_SENTRY_DSN is already set in Railway as a build arg. The hardcoded
fallback was unnecessary and triggered GitHub secret scanning alerts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- landing.css: hardcode --lp-btn to #60a5fa (lesson 104 — no var(--color-*) in landing.css)
- ScriptBuilderInput: suggestion chips now correctly disabled during generation
- ChatSidebar: wrapper onClick no longer fires onSelect while in confirming state
- SessionHistoryPage: fix loadMoreAiSessions race condition with generation counter;
flow session tab auto-activates when URL params target flow session filters
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Slower chat stagger (1.2s between lines, not 0.6s) so each message
is clearly individual and watchable
- Messages slide in from left (translateX -20px) not just fade up
- Typing indicator is bigger with blue tinted background, border,
and "FlowPilot is thinking..." label
- Typing indicator holds for 3s before collapsing (was 1.8s)
- App preview has cinematic entrance (scale 0.95 → 1 + translateY)
- AI responses wait until typing indicator finishes, then cascade
- Doc confirmation has extra pause before appearing (9.6s total)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
A) Live App Preview:
- Chat messages animate in with staggered timing (0.6s apart)
- Typing indicator with bouncing dots appears before AI response,
then fades out as the response lines arrive
- Sidebar items stagger in during the entrance sequence
- Creates a "show don't tell" demo moment in the hero
B) Scroll-Driven Enhancements (@supports animation-timeline):
- Sections use CSS scroll-driven animations instead of JS IntersectionObserver
- Problem cards, feature cards, pricing cards, and step cards stagger
within their parent as they enter the viewport
- Social proof bar has subtle parallax drift
- Falls back to existing JS-based reveal for Firefox/older browsers
Accessibility:
- prefers-reduced-motion removes all chat animations, shows content
immediately, hides typing indicator entirely
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bg-accent (#f97316 orange) with text-muted-foreground (#848b9b gray)
is nearly invisible. Replaced with bg-elevated + border pattern for
readable contrast across TagBadges, StepForm, StepDetailModal, and
StepLibraryBrowser. Also fixed emerald → success-dim token.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- FolderTree, Plus, ListOrdered, Wrench are still used in empty state
and tree card rendering — restore the imports
- SessionHistoryPage needs default export for lazyWithRetry
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Session History:
- Split into AI Sessions / Flow Sessions tabs (AI default)
- Load More pagination (25 per page) instead of 50-item hard cap
- Dynamic problem domain filter from actual session data
- Fix all blue focus rings to ember orange
- Fix badge colors to use design system tokens
Escalation Queue:
- Add wait-time color coding (muted <1h, amber 1-4h, red >4h)
- Sort oldest-first for triage urgency
- Compact right-aligned pickup button
- Widen container, dynamic session count in subtitle
- Fix typos and non-system color tokens
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Change "Questions" and "Diagnostic Checks" headers from text-muted
(#4f5666, barely visible on sidebar) to text-muted-foreground (#848b9b).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
orange-400→blue-400, orange-500→blue-500, orange-600→blue-600
across ~21 component files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mechanical find-and-replace: rgba(249,115,22,...) → rgba(96,165,250,...)
across ~40 component and page files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Two issues fixed:
1. TaskLane useEffect on [questions, actions] was resetting all tasks
to pending with empty values, wiping restored user answers. Now
checks sessionStorage for saved state before resetting.
2. selectChat was setting activeQuestions/activeActions before writing
responses to sessionStorage, causing a race where TaskLane mounted
with new props but empty sessionStorage. Now writes responses to
sessionStorage first so TaskLane can restore them on prop change.
The backend saveTaskLane debounce (2s) persists responses to the DB,
and selectChat restores them via pending_task_lane.responses. This
chain now survives browser close.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The non-streaming fallback used getDocumentation which relies on
session.steps — empty for chat sessions, producing only the bare
resolution_summary text. Switch fallback to generateStatusUpdate
which reads conversation_messages and generates proper context-aware
ticket notes for both chat and guided sessions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The sendPrefill flow (dashboard handoff) did not clear activeQuestions/
activeActions before creating the new session. The task lane initializer
loaded stale data from sessionStorage keyed to the previous session ID,
showing old tasks while the new session was processing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The SSE stream URL was /api/ai-sessions/ but the backend mounts all
routes under /api/v1/. This caused a 404, falling through to a
non-streaming fallback that returned empty documentation for chat
sessions. This is why "Conclude → Resolved" never showed ticket notes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wire StatusUpdateModal into AssistantChatPage with "Update" button in
the chat toolbar. Enhance ConcludeSessionModal pause/escalate outcomes
to offer ticket notes, client update, or email draft generation instead
of static messages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Opens the ParameterizeAndSavePanel in paste mode, letting users import
raw scripts with parameter detection and review before saving to library.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>