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>
Remove duplicate Update/Close actions from chat toolbars (FlowPilotPage,
CockpitPage) — session lifecycle actions now live only in headers. Redesign
ViewToggle as a persistent tab bar with bottom-border active indicator and
ARIA attributes. Standardize all action naming: Resolve (emerald), Update
(blue), Close (rose), Pause (muted). Fix IncidentHeader Resolve from orange
to emerald. Delete unused FlowPilotActionBar component (227 lines). Update
ConcludeSessionModal copy to use forward-facing action verbs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Eliminates the dedicated ViewToggle row on CockpitPage by merging
it into IncidentHeader's action group via extraActions prop. Removes
subtitle from ViewToggle component entirely — the icon + label is
self-explanatory. Cleans up showSubtitle prop from all call sites.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The IncidentHeader overflow menu was see-through due to bg-elevated on
bg-card. Switched to bg-card with shadow-xl and fixed-scrim dismiss
pattern matching production FlowPilotSessionPage. Replaced unicode
ellipsis with MoreHorizontal icon + aria-label. Added Update button
(StatusUpdateModal) to IncidentHeader and FlowPilotPage header bar
for feature parity with production.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix return type annotation on unified_chat_service.send_chat_message (6→7 tuple)
- Fix stale closure in CockpitPage handleStepComplete auto-advance logic
- Fix IncidentHeader copy link hardcoding /assistant/ path (now uses current URL)
- Wire psaTicketId from session data through to CockpitPage incident header
- Fix FlowPilotAsks showing only first question — add chevron navigation for all
- Redesign ViewToggle: add icons (MessageSquare/LayoutDashboard) and subtitles
- Move view toggle from chatbar toolbar to standalone row above input on dashboard
- Standardize toggle placement across dashboard, FlowPilot, and Cockpit pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backend: stop wiping pending_task_lane when AI response has no new
[ACTIONS]/[QUESTIONS] markers — previous task lane state is still
relevant until replaced by new markers.
Frontend (selectChat): don't eagerly clear task lane before server
response arrives; restore from sessionStorage as fallback when
pending_task_lane is null (covers sessions before backend fix).
StepsPanel: show description and command for all steps instead of
hiding behind hover/active-only visibility. Commands render as
inline code blocks.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- IncidentHeader: labelled fields with per-field edit popovers
- StepsPanel: ordered step checklist (✓/→/○) with script CTA
- FlowPilotAsks: quick-reply buttons or free-text input
- WhatWeKnow: evidence list with status toggle and inline editing
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>
- 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>
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>
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>
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>
Slide-in panel for saving scripts to library with parameter detection,
stepper review, template rewriting, and metadata collection. Supports
both script mode (from AI builder) and paste mode (raw script import).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ConcludeSessionModal now resolves instantly (Phase 1) then streams
ticket notes via SSE (Phase 2), with skeleton loading and fallback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ScriptBodyEditor's onChange fired when the value prop changed externally
(from handleAcceptCandidate inserting placeholders), creating a feedback
loop that reset acceptingCandidateRef before the second useEffect cycle.
Guard onChange to only propagate when the value actually differs from the
current prop.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
_build_session_detail was omitting pending_task_lane, is_branching, and
active_branch_id from the GET /ai-sessions/{id} response. The fields
existed on the schema and model but were never passed in the manual
constructor, so task lane state could never be restored on navigation.
Also adds console logging to AssistantChatPage selectChat flow to
diagnose message restoration, and fixes ScriptTemplateEditor stepper
dismiss firing during programmatic script_body updates.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add PUT /ai-sessions/{id}/task-lane endpoint that saves the full task
lane state (AI questions/actions + user's in-progress responses) to
the pending_task_lane JSONB column. TaskLane debounce-saves to the
backend every 2s after changes. On session load, user responses are
restored from the backend into sessionStorage so TaskLane picks them
up on mount. Users can now close the browser, come back later, and
find their task lane exactly where they left it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TaskLane now saves user's in-progress answers (typed text, checked
items) to sessionStorage keyed by session ID. On reload or session
switch, the full task lane state restores — including partial work.
- TaskLane: saves tasks array to sessionStorage on every change,
restores from sessionStorage on mount
- AssistantChatPage: saves task lane metadata (visibility, questions,
actions, chatId) to sessionStorage, restores on mount
- Closing the task lane clears its sessionStorage entry
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TaskLane had `if (submitted) return null` which immediately hid the
component after submit, before the AI could respond. Now the parent
controls visibility: the lane stays visible during the AI call, then
either updates with new tasks or clears when the AI sends none.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Task lane questions/actions are now saved to a pending_task_lane JSONB
column on ai_sessions, restoring them on session switch or page reload.
Partial submit no longer force-clears the lane — the AI response
controls what stays. Also removes redundant "New Session" button from
the sidebar (dashboard already provides this).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
eslint-disable-next-line only covers the next line, not lines further
down. Moved the comments from before useEffect() to before the actual
setState call inside the effect body.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- eslint-disable for unused _ticket param (needed for onSelect type compat)
- eslint-disable for setState in lazy-load useEffect
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add back_populates to SessionBranch.session ↔ AISession.branches
to fix SQLAlchemy InvalidRequestError that broke all backend tests
- Remove unused 'tree' variable in command-palette.spec.ts
- Suppress setState-in-effect lint rule in TaskLane (intentional sync)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ViewTransitionOutlet was using animate-fade-in-up (opacity + translateY)
on every route change, causing visible content shift on navigation.
Switch to animate-fade-in (opacity only) for a subtler transition.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Resolve focus ring conflict in StartSessionInput — keep explicit
rgba values over Tailwind primary/20 for consistency with design system.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>