Add the ability to reset a project to its initial state with two options:
- Quick Reset: Clears features.db, assistant.db, and settings files while
preserving app spec and prompts
- Full Reset: Deletes everything including prompts directory, triggering
the setup wizard for project reconfiguration
Backend changes:
- Add POST /{name}/reset endpoint to projects router with full_reset query param
- Validate agent lock file to prevent reset while agent is running (409 Conflict)
- Dispose database engines before deleting files to release Windows file locks
- Add engine caching to api/database.py for better connection management
- Add dispose_engine() functions to both database modules
- Delete WAL mode journal files (*.db-wal, *.db-shm) during reset
Frontend changes:
- Add ResetProjectModal component with toggle between Quick/Full reset modes
- Add ProjectSetupRequired component shown when has_spec is false
- Add resetProject API function and useResetProject React Query hook
- Integrate reset button in header (disabled when agent running)
- Add 'R' keyboard shortcut to open reset modal
- Show ProjectSetupRequired when project needs setup after full reset
This implements the feature from PR #4 directly on master to avoid merge
conflicts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add `default_concurrency` column to the projects table in the registry
database, allowing each project to remember its preferred concurrency
setting (1-5 agents). The value persists across page refreshes and
app restarts.
Backend changes:
- Add `default_concurrency` column to Project model in registry.py
- Add database migration for existing databases (ALTER TABLE)
- Add get/set_project_concurrency() CRUD functions
- Add ProjectSettingsUpdate schema with validation
- Add PATCH /{name}/settings endpoint in projects router
- Include default_concurrency in ProjectSummary/ProjectDetail responses
Frontend changes:
- Add default_concurrency to ProjectSummary TypeScript interface
- Add ProjectSettingsUpdate type and updateProjectSettings API function
- Add useUpdateProjectSettings React Query mutation hook
- Update AgentControl to accept defaultConcurrency prop
- Sync local state when project changes via useEffect
- Debounce slider changes (500ms) before saving to backend
- Pass defaultConcurrency from selectedProjectData in App.tsx
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create shared `isSubmitEnter()` utility in `ui/src/lib/keyboard.ts`
for IME-aware Enter key handling across all input components
- Extract magic number 48 to named constant `COLLAPSED_DEBUG_PANEL_CLEARANCE`
with explanatory comment (40px panel header + 8px margin)
- Update 5 components to use the new utility:
- AssistantChat.tsx
- ExpandProjectChat.tsx
- SpecCreationChat.tsx
- FolderBrowser.tsx
- TerminalTabs.tsx
This follows up on PR #121 which added IME composition checks. The
refactoring centralizes the logic for easier maintenance and documents
the padding value that prevents Kanban cards from being cut off when
the debug panel is collapsed.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add sticky positioning and glassmorphism effect to the top navigation:
- sticky top-0 z-50 for fixed positioning above content
- bg-card/80 for 80% opacity background
- backdrop-blur-md for frosted glass effect
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change CSS import from bare module specifier to url() syntax to fix
Vite/Tailwind CSS resolution issues on some systems.
- Changed `@import "tw-animate-css"` to `@import url("tw-animate-css")`
- The url() wrapper ensures proper package resolution across platforms
- Fixes "Can't resolve 'tw-animate-css'" build error
The bare import syntax failed because Vite's CSS processing didn't
properly resolve the package exports. Using url() bypasses this issue
while still correctly resolving the npm package from node_modules.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace hardcoded violet/purple colors in OrchestratorStatusCard with
standard primary color CSS variables to ensure proper theming across
all theme variants (light/dark mode, Twitter, Claude, Neo Brutalism,
Aurora, Retro Arcade).
Changes:
- Card background: bg-primary/10 with border-primary/30
- Maestro title and state text: text-primary
- Activity button: text-primary hover:bg-primary/10
- Events border and timestamps: use primary color variants
Also includes:
- Enhanced review-pr command with vision alignment checks
- CLAUDE.md improvements: prerequisites, testing section, React 19 update
- Simplified parallel mode documentation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace warm off-white with cool blue-gray concrete tone
- More corporate and industrial aesthetic
- Sidebar background adjusted to match
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change primary color to deep navy #000e4e
- Replace teal accent with gray monochrome scale
- Add warm off-white background
- Enhance card shadows for modern depth (2026 UI trend)
- Update chart colors to navy-gray gradient scale
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add a new "Business" theme designed for corporate/professional use cases.
The theme features a sophisticated navy and gray color palette that conveys
trust and professionalism while maintaining excellent readability.
Key characteristics:
- Deep navy primary color for trust and professionalism
- Off-white/charcoal backgrounds (avoiding harsh pure white/black)
- Teal accent for CTAs and highlights
- Soft, professional shadows
- System fonts for native feel
- High contrast ratios (WCAG AA compliant)
Files changed:
- globals.css: Added .theme-business light and dark mode variables
- useTheme.ts: Added 'business' to ThemeId and THEMES array
- ThemeSelector.tsx: Added business theme class handling
Add isComposing check to prevent Enter key from submitting messages
while Japanese (or other) IME input is in progress.
Affected components:
- AssistantChat
- ExpandProjectChat
- SpecCreationChat
- FolderBrowser
- TerminalTabs
Add a comprehensive theme system allowing users to switch between three
distinct visual themes, each supporting both light and dark modes:
- Twitter (default): Clean blue design with soft shadows
- Claude: Warm beige/cream tones with orange primary accents
- Neo Brutalism: Bold colors, hard shadows, 0px border radius
New files:
- ui/src/hooks/useTheme.ts: Theme state management hook with localStorage
persistence for both theme selection and dark mode preference
- ui/src/components/ThemeSelector.tsx: Header dropdown with hover preview
and color swatches for quick theme switching
Modified files:
- ui/src/styles/globals.css: Added CSS custom properties for Claude and
Neo Brutalism themes with light/dark variants, shadow variables
integrated into @theme inline block
- ui/src/App.tsx: Integrated useTheme hook and ThemeSelector component
- ui/src/components/SettingsModal.tsx: Added theme selection UI with
preview swatches and dark mode toggle
- ui/index.html: Added DM Sans and Space Mono fonts for Neo Brutalism
Features:
- Independent theme and dark mode controls
- Smooth CSS transitions when switching themes
- Theme-specific shadow styles (soft vs hard)
- Theme-specific fonts and border radius
- Persisted preferences in localStorage
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove translate-x/translate-y CSS selectors that broke layout utilities
(AssistantPanel slide animation, DebugLogViewer resize handle)
- Add browser validation to get_playwright_browser() with warning for
invalid values (matches get_playwright_headless() behavior)
- Remove phantom SQLite documentation from CUSTOM_UPDATES.md that
described features not present in PR #93
- Update checklist and revert instructions to match actual changes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Check for 'not found' message (server response) in addition to '404'
- Only clear stored conversation ID on actual 404 errors
- Prevent unnecessary retries for deleted conversations
- Don't clear conversation on transient network errors
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a stored conversation ID no longer exists (e.g., database was reset
or conversation was deleted), the UI would repeatedly try to fetch it,
causing endless 404 errors in the console.
This fix:
- Stops retrying on 404 errors (conversation doesn't exist)
- Automatically clears the stored conversation ID from localStorage
when a 404 is received, allowing the user to start fresh
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add focus-visible styles for keyboard navigation accessibility and
improve PLAYWRIGHT_HEADLESS environment variable validation to warn
users about invalid values instead of silently defaulting.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
UI Changes:
- Replace neobrutalism with clean Twitter/Supabase-style design
- Remove all shadows, use thin borders (1px)
- Single accent color (Twitter blue) for all status indicators
- Rounded corners (1.3rem base)
- Fix dark mode contrast and visibility
- Make KanbanColumn themeable via CSS classes
Backend Changes:
- Default Playwright browser changed to Firefox (lower CPU)
- Default Playwright mode changed to headless (saves resources)
- Add PLAYWRIGHT_BROWSER env var support
Documentation:
- Add CUSTOM_UPDATES.md with all customizations documented
- Update .env.example with new Playwright options
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create custom-theme.css for theme overrides that won't conflict
with upstream updates. The file loads after globals.css, so its
CSS variables take precedence.
This approach ensures:
- Zero merge conflicts on git pull (new file, not in upstream)
- Theme persists across upstream updates
- Easy to modify without touching upstream code
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, agents that completed their work would remain visible in the
Mission Control UI until a manual page refresh. This occurred because
the AgentTracker._handle_agent_complete method silently dropped completion
messages when an agent wasn't tracked (e.g., due to missed start messages
from WebSocket connection issues).
Backend changes:
- Modified _handle_agent_complete in server/websocket.py to always emit
completion messages, even for untracked agents
- Synthetic completions use agentIndex=-1 and agentName='Unknown' as
sentinel values to indicate untracked agents
Frontend changes:
- Updated useWebSocket.ts to handle synthetic completions by removing
agents by featureId when agentIndex is -1
- Added 30-minute stale agent cleanup as defense-in-depth for users who
leave the UI open for extended periods
- Updated TypeScript types to allow 'Unknown' as valid agent name
Component updates:
- AgentAvatar.tsx: Added UNKNOWN_COLORS and UnknownSVG fallback for
rendering unknown agents with a neutral gray question mark icon
- CelebrationOverlay.tsx, DependencyGraph.tsx: Updated interfaces to
accept 'Unknown' agent names
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add real-time visibility into the parallel orchestrator's decisions
and state in the Mission Control UI. The orchestrator now has its
own avatar ("Maestro") and displays capacity/queue information.
Backend changes (server/websocket.py):
- Add OrchestratorTracker class that parses orchestrator stdout
- Define regex patterns for key orchestrator events (spawn, complete, capacity)
- Track coding/testing agent counts, ready queue, blocked features
- Emit orchestrator_update WebSocket messages
- Reset tracker state when agent stops or crashes
Frontend changes:
- Add OrchestratorState, OrchestratorStatus, OrchestratorEvent types
- Add WSOrchestratorUpdateMessage to WSMessage union
- Handle orchestrator_update in useWebSocket hook
- Create OrchestratorAvatar component (Maestro - robot conductor)
- Create OrchestratorStatusCard with capacity badges and event ticker
- Update AgentMissionControl to show orchestrator above agent cards
- Add conducting/baton-tap CSS animations for Maestro
The orchestrator status card shows:
- Maestro avatar with state-based animations
- Current orchestrator state and message
- Coding agents, testing agents, ready queue badges
- Blocked features count (when > 0)
- Collapsible recent events list
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Major refactoring of the parallel orchestrator to run regression testing
agents independently from coding agents. This improves system reliability
and provides better control over testing behavior.
Key changes:
Database & MCP Layer:
- Add testing_in_progress and last_tested_at columns to Feature model
- Add feature_claim_for_testing() for atomic test claim with retry
- Add feature_release_testing() to release claims after testing
- Refactor claim functions to iterative loops (no recursion)
- Add OperationalError retry handling for transient DB errors
- Reduce MAX_CLAIM_RETRIES from 10 to 5
Orchestrator:
- Decouple testing agent lifecycle from coding agents
- Add _maintain_testing_agents() for continuous testing maintenance
- Fix TOCTOU race in _spawn_testing_agent() - hold lock during spawn
- Add _cleanup_stale_testing_locks() with 30-min timeout
- Fix log ordering - start_session() before stale flag cleanup
- Add stale testing_in_progress cleanup on startup
Dead Code Removal:
- Remove count_testing_in_concurrency from entire stack (12+ files)
- Remove ineffective with_for_update() from features router
API & UI:
- Pass testing_agent_ratio via CLI to orchestrator
- Update testing prompt template to use new claim/release tools
- Rename UI label to "Regression Agents" with clearer description
- Add process_utils.py for cross-platform process tree management
Testing agents now:
- Run continuously as long as passing features exist
- Can re-test features multiple times to catch regressions
- Are controlled by fixed count (0-3) via testing_agent_ratio setting
- Have atomic claiming to prevent concurrent testing of same feature
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changes:
- Revert incorrect import from claude_code_sdk to claude_agent_sdk in agent.py
(PR #50 introduced an undocumented change to a deprecated package)
- Clear activeAgents and recentActivity in useWebSocket when agent stops
to prevent stale UI state
The claude_code_sdk package is deprecated (last updated Sep 2025) while
claude_agent_sdk is the active, maintained package. The import change in
PR #50 was undocumented and would have caused ImportError since only
claude-agent-sdk is specified in requirements.txt.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Performance improvements:
- Fix N+1 query in get_conversations() using COUNT subquery instead of
len(c.messages) which triggered lazy loading for each conversation
- Add SQLAlchemy engine caching to avoid creating new database connections
on every request
- Add React.memo to ChatMessage component to prevent unnecessary re-renders
during message streaming
- Move BOLD_REGEX to module scope to avoid recreating on each render
Code quality improvements:
- Remove 10+ console.log debug statements from AssistantChat.tsx and
AssistantPanel.tsx that were left from development
- Add user feedback for delete errors in ConversationHistory - dialog now
stays open and shows error message instead of silently failing
- Update ConfirmDialog to accept ReactNode for message prop to support
rich error content
These changes address issues identified in the code review of PR #74
(conversation history feature).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit fixes several issues identified in the agent scheduling
feature from PR #75:
Frontend Fixes:
- Add day boundary handling in timeUtils.ts for timezone conversions
- Add utcToLocalWithDayShift/localToUTCWithDayShift functions
- Add shiftDaysForward/shiftDaysBackward helpers for bitfield adjustment
- Update ScheduleModal to correctly adjust days_of_week when crossing
day boundaries during UTC conversion (fixes schedules running on
wrong days for users in extreme timezones like UTC+9)
Backend Fixes:
- Add MAX_SCHEDULES_PER_PROJECT (50) limit to prevent resource exhaustion
- Wire up crash recovery callback in scheduler_service._start_agent()
- Convert schedules.py endpoints to use context manager for DB sessions
- Fix race condition in override creation with atomic delete-then-create
- Replace deprecated datetime.utcnow with datetime.now(timezone.utc)
- Add DB-level CHECK constraints for Schedule model fields
Files Modified:
- api/database.py: Add _utc_now helper, CheckConstraint imports, constraints
- progress.py: Replace deprecated datetime.utcnow
- server/routers/schedules.py: Add context manager, schedule limits
- server/services/assistant_database.py: Replace deprecated datetime.utcnow
- server/services/scheduler_service.py: Wire crash recovery, fix race condition
- ui/src/components/ScheduleModal.tsx: Use day shift functions
- ui/src/lib/timeUtils.ts: Add day boundary handling functions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Security fixes to restore defense-in-depth after merging PR #78:
**client.py:**
- Revert permission mode from "bypassPermissions" to "acceptEdits"
- Remove redundant web_tools_auto_approve_hook from PreToolUse hooks
- Remove unused import of web_tools_auto_approve_hook
**security.py:**
- Remove web_tools_auto_approve_hook function (was redundant and
returned {} for ALL tools, not just WebFetch/WebSearch)
**server/services/spec_chat_session.py:**
- Restore allowed_tools restriction: [Read, Write, Edit, Glob,
WebFetch, WebSearch]
- Revert permission mode from "bypassPermissions" to "acceptEdits"
- Keeps setting_sources=["project", "user"] for global skills access
**ui/src/components/AgentAvatar.tsx:**
- Remove unused getMascotName export to fix React Fast Refresh warning
- File now only exports AgentAvatar component as expected
The bypassPermissions mode combined with unrestricted tool access in
spec_chat_session.py created a security gap where Bash commands could
execute without validation (sandbox disabled, no bash_security_hook).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
UI Changes:
- Add "Create Spec with AI" button in empty kanban when project has no spec
- Button opens SpecCreationChat to guide users through spec creation
- Shows in Pending column when has_spec=false and no features exist
Windows Fixes:
- Fix asyncio subprocess NotImplementedError on Windows
- Set WindowsProactorEventLoopPolicy in server/__init__.py
- Remove --reload from uvicorn (incompatible with Windows subprocess)
- Add process cleanup on startup in start_ui.bat
Spec Chat Improvements:
- Enable full tool access (remove allowed_tools restriction)
- Add "user" to setting_sources for global skills access
- Use bypassPermissions mode for auto-approval
- Add WebFetch/WebSearch auto-approve hook
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add comprehensive scheduling system that allows agents to automatically
start and stop during configured time windows, helping users manage
Claude API token limits by running agents during off-hours.
Backend Changes:
- Add Schedule and ScheduleOverride database models for persistent storage
- Implement APScheduler-based SchedulerService with UTC timezone support
- Add schedule CRUD API endpoints (/api/projects/{name}/schedules)
- Add manual override tracking to prevent unwanted auto-start/stop
- Integrate scheduler lifecycle with FastAPI startup/shutdown
- Fix timezone bug: explicitly set timezone=timezone.utc on CronTrigger
to ensure correct UTC scheduling (critical fix)
Frontend Changes:
- Add ScheduleModal component for creating and managing schedules
- Add clock button and schedule status display to AgentControl
- Add timezone utilities for converting between UTC and local time
- Add React Query hooks for schedule data fetching
- Fix 204 No Content handling in fetchJSON for delete operations
- Invalidate nextRun cache when manually stopping agent during window
- Add TypeScript type annotations to Terminal component callbacks
Features:
- Multiple overlapping schedules per project supported
- Auto-start at scheduled time via APScheduler cron jobs
- Auto-stop after configured duration
- Manual start/stop creates persistent overrides in database
- Crash recovery with exponential backoff (max 3 retries)
- Server restart preserves schedules and active overrides
- Times displayed in user's local timezone, stored as UTC
- Immediate start if schedule created during active window
Dependencies:
- Add APScheduler for reliable cron-like scheduling
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Introduce a new testing agent architecture that runs regression tests
independently from coding agents, improving quality assurance in
parallel mode.
Key changes:
Testing Agent System:
- Add testing_prompt.template.md for dedicated testing agent role
- Add feature_mark_failing MCP tool for regression detection
- Add --agent-type flag to select initializer/coding/testing mode
- Remove regression testing from coding prompt (now handled by testing agents)
Parallel Orchestrator Enhancements:
- Add testing agent spawning with configurable ratio (--testing-agent-ratio)
- Add comprehensive debug logging system (DebugLog class)
- Improve database session management to prevent stale reads
- Add engine.dispose() calls to refresh connections after subprocess commits
- Fix f-string linting issues (remove unnecessary f-prefixes)
UI Improvements:
- Add testing agent mascot (Chip) to AgentAvatar
- Enhance AgentCard to display testing agent status
- Add testing agent ratio slider in SettingsModal
- Update WebSocket handling for testing agent updates
- Improve ActivityFeed to show testing agent activity
API & Server Updates:
- Add testing_agent_ratio to settings schema and endpoints
- Update process manager to support testing agent type
- Enhance WebSocket messages for agent_update events
Template Changes:
- Delete coding_prompt_yolo.template.md (consolidated into main prompt)
- Update initializer_prompt.template.md with improved structure
- Streamline coding_prompt.template.md workflow
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Memoize onNodeClick callback in App.tsx to prevent unnecessary re-renders
- Add useRef pattern in DependencyGraph to store callback without triggering
useMemo recalculation when callback identity changes
- Add hash-based change detection to only update ReactFlow state when
actual graph data changes (node status, edges), not on every parent render
- Add GraphErrorBoundary class component to catch ReactFlow rendering errors
and provide a "Reload Graph" recovery button instead of blank screen
- Wrap DependencyGraph with error boundary and resetKey for graceful recovery
The root cause was frequent WebSocket updates during active agent sessions
causing parent re-renders, which created new inline callback functions,
triggering useMemo/useEffect chains that corrupted ReactFlow's internal state
over time (approximately 1 minute of continuous updates).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changes:
- Add per-agent log viewer with copy-to-clipboard functionality
- New AgentLogEntry type for structured log entries
- Logs stored per-agent in WebSocket state (up to 500 entries)
- Log modal rendered via React Portal to avoid overflow issues
- Click log icon on agent card to view full activity history
- Fix agents getting stuck in "failed" state
- Wrap client context manager in try/except (agent.py)
- Remove failed agents from UI on error state (useWebSocket.ts)
- Handle permanently failed features in get_all_complete()
- Add friendlier agent state labels
- "Hit an issue" → "Trying plan B..."
- "Retrying..." → "Being persistent..."
- Softer colors (yellow/orange instead of red)
- Add scheduling scores for smarter feature ordering
- compute_scheduling_scores() in dependency_resolver.py
- Features that unblock others get higher priority
- Update CLAUDE.md with parallel mode documentation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Major feature implementation for parallel agent execution with dependency-aware
scheduling and an engaging multi-agent UI experience.
Backend Changes:
- Add parallel_orchestrator.py for concurrent feature processing
- Add api/dependency_resolver.py with cycle detection (Kahn's algorithm + DFS)
- Add atomic feature_claim_next() with retry limit and exponential backoff
- Fix circular dependency check arguments in 4 locations
- Add AgentTracker class for parsing agent output and emitting updates
- Add browser isolation with --isolated flag for Playwright MCP
- Extend WebSocket protocol with agent_update messages and log attribution
- Add WSAgentUpdateMessage schema with agent states and mascot names
- Fix WSProgressMessage to include in_progress field
New UI Components:
- AgentMissionControl: Dashboard showing active agents with collapsible activity
- AgentCard: Individual agent status with avatar and thought bubble
- AgentAvatar: SVG mascots (Spark, Fizz, Octo, Hoot, Buzz) with animations
- ActivityFeed: Recent activity stream with stable keys (no flickering)
- CelebrationOverlay: Confetti animation with click/Escape dismiss
- DependencyGraph: Interactive node graph visualization with dagre layout
- DependencyBadge: Visual indicator for feature dependencies
- ViewToggle: Switch between Kanban and Graph views
- KeyboardShortcutsHelp: Help overlay accessible via ? key
UI/UX Improvements:
- Celebration queue system to handle rapid success messages
- Accessibility attributes on AgentAvatar (role, aria-label, aria-live)
- Collapsible Recent Activity section with persisted preference
- Agent count display in header
- Keyboard shortcut G to toggle Kanban/Graph view
- Real-time thought bubbles and state animations
Bug Fixes:
- Fix circular dependency validation (swapped source/target arguments)
- Add MAX_CLAIM_RETRIES=10 to prevent stack overflow under contention
- Fix THOUGHT_PATTERNS to match actual [Tool: name] format
- Fix ActivityFeed key prop to prevent re-renders on new items
- Add featureId/agentIndex to log messages for proper attribution
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix duplicate onConversationCreated callbacks by tracking activeConversationId
- Fix history loss when switching conversations with Map-based deduplication
- Disable input while conversation is loading to prevent message routing issues
- Gate WebSocket debug logs behind DEV flag (import.meta.env.DEV)
- Downgrade server logging from info to debug level for reduced noise
- Fix .gitignore prefixes for playwright paths (ui/playwright-report/, ui/test-results/)
- Remove debug console.log from ConversationHistory.tsx
- Add staleTime (30s) to single conversation query for better caching
- Increase history message cap from 20 to 35 for better context
- Replace fixed timeouts with condition-based waits in e2e tests