Replace ai-sandbox.oliver.solutions with optical-dev.oliver.solution
across all config, env, docs, and source files.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix missing await on FocusGroup.get_messages() (N-L1)
- Replace time.sleep with asyncio.sleep in key_theme_service and focus_group_service (N-P10)
- Replace flask import with quart in focus_groups.py (N-S3)
- Add logger.error before all 500 returns in focus_groups.py (N-P6)
- Add logging to silent except blocks across routes (N-M10, N-M11)
- Add @rate_limit to 6 remaining AI endpoints (N-H4)
- Add --confirm flag to populate scripts before delete_many (S-H2)
- Remove hardcoded Azure ID fallbacks from msal_service.py and msalConfig.ts (A-M2, F-H4)
- Centralize make_serializable() in utils.py, remove duplicates from 3 route files (N-P7)
- Replace all datetime.utcnow() with datetime.now(timezone.utc) across entire backend (M-L2)
- AuthContext.tsx: only mark token validated on 200 success, not on non-401 errors (F-H2)
- Rename authType → auth_type in auth.py (N-S4)
- Add security_report.md and security_report.pdf with full 92-finding status
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Create comprehensive technical architecture document (PDF) with 11
chapters covering system architecture, frontend/backend design, data
model, auth, WebSocket communication, LLM integration, and core
feature flows. Includes 11 Mermaid diagrams rendered as PNGs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrites the outdated README to accurately reflect the current state of the
project: corrects framework references (Quart/Hypercorn instead of Flask/Gunicorn),
documents all major features (autonomous AI conversations, multi-model LLM support,
WebSocket communication, Microsoft SSO, theme extraction), updates the project
structure and tech stack, adds architecture overview, environment configuration
table, and deployment instructions using deploy.sh/systemd.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Focus groups created before the gpt-5.2 rename have llm_model='gpt-5'
stored in MongoDB. Without an alias, the backend falls through to the
Gemini provider and fails with an aiohttp AssertionError.
Adds MODEL_ALIASES mapping and _resolve_model() helper so gpt-5 is
transparently resolved to gpt-5.2. Also updates all llm_model checks
to accept both values.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Swap model ID from gpt-5 to gpt-5.2 across all backend services,
frontend components, and documentation. Change default reasoning
effort from medium to low for faster responses.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Stage 2 (detailed persona generation) was ignoring the audience brief and
research objective, causing the LLM to guess research context from demographics
alone. Now passes both values through to generate_persona() in all three
endpoints (generate-personas-full, complete-and-save-persona, complete-persona)
and auto-generates prompt customization via customize_persona_prompt() when
they are provided.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Version 1.52.0 has a known bug where aiohttp connector is None.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
logger is not defined at module level where get_gemini_client() lives.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This will help identify where exactly the AssertionError is occurring
in the google-genai SDK and what version is installed on the server.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Log full exception details: type, module, str, repr, args, and __dict__
to diagnose why Gemini errors are producing empty messages.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Catch genai_errors.APIError specifically and extract e.code and e.message
attributes for proper error logging. The generic str(e) was returning empty
strings for Google API errors, making debugging impossible.
- Import google.genai.errors for specific exception handling
- Add APIError catch before generic Exception in generate_content()
- Add APIError catch before generic Exception in generate_contextual_response()
- Properly categorize errors by HTTP code for retry logic (429/500+ retryable)
- Fix time.sleep to await asyncio.sleep in contextual response handler
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Skip WebSocket connection attempt when no auth token is available.
Previously, the WebSocketProvider would try to connect immediately
on mount (even on login page) with an empty token, causing
"Invalid token format" errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The previous event loop tracking approach still caused issues - when replacing
a cached client, its garbage collection triggers aclose() which tries to close
the aiohttp session on the wrong event loop.
Simplest fix: create a fresh client for each call. The overhead is minimal
compared to the actual LLM API call, and this completely avoids all event
loop mismatch issues in ASGI environments.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The previous lazy initialization fix wasn't sufficient - the genai.Client
internally caches async structures bound to the event loop at creation time.
With ASGI servers like Hypercorn, subsequent requests may come on different
event loop contexts, causing "Future attached to a different loop" errors.
Now tracks which event loop the client was created on and recreates it if
the loop has changed.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
These files are already in .gitignore but were committed previously.
Removing them from tracking to prevent future conflicts.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The genai.Client and AsyncOpenAI clients were being created at module
import time, before the Quart/Hypercorn event loop existed. This caused
"Future attached to a different loop" errors when async calls were made,
resulting in autonomous focus group conversations stopping with
"excessive_silence".
Changed to lazy initialization - clients are now created on first use
within the running event loop context via get_gemini_client() and
get_openai_client() helper functions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Legacy code from Flask-SocketIO migration that's no longer used.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes ModuleNotFoundError on server by using the custom
Quart-compatible JWT implementation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Creates uploads/ and temp/ directories with correct ownership
before restarting the service, fixing systemd namespace errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add VITE_ENABLE_LOCAL_LOGIN env variable to conditionally show/hide
local username/password login on the login screen. When set to 'false'
(production), only Microsoft login is shown. When 'true' (development),
both options are available.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add prominent "Edit Discussion Guide" button to header and enhance accordion
styling with amber color scheme, "Click to Edit" badge, and visual feedback
to help users discover the inline editing capability.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Users can now edit individual questions and prompts directly without
entering section edit mode. Edit buttons appear on hover for each item,
allowing inline editing of content, time limits, and probe questions.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements a traffic light indicator beneath paragraph fields to guide users
on content adequacy. Shows red (<33%), yellow (33-99%), or green (≥100%) based
on word count progress toward minimum targets.
Fields updated:
- Research Brief: 150 words minimum
- Discussion Topics: 15 words minimum
- Audience Brief: 150 words minimum
- Research Objective: 150 words minimum
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Make entire draft card clickable to enter setup mode
- Rename "Edit" button to "Continue Setup" for better clarity
- Add "Run Session" button for complete drafts (with discussion guide and participants)
- Prevent checkbox clicks from triggering card navigation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Extract business logic and UI into reusable pieces:
Custom Hooks:
- useFocusGroupAutoSave: debounced auto-save with retry logic
- useFolderManagement: folder CRUD operations
- usePersonaFiltering: filter state and persona filtering
- useDiscussionGuideGeneration: guide generation and progress
UI Components:
- SaveStatusIndicator: auto-save status display
- FolderSidebar: folder list and management
- PersonaFilterDialog: persona filter modal
- CopyGuideDialog: copy guide from other focus groups
Tab Components:
- SetupTab: form and asset uploader
- ReviewTab: discussion guide viewer
- ParticipantsTab: persona selection grid
Reduces FocusGroupModerator from 2,396 to ~600 lines (75% reduction).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The useEffect that reverts to Setup tab on cancellation was incorrectly
firing after successful generation. Added check for discussionGuide to
only revert when generation was actually cancelled (no guide exists).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create focus_group_summary_service.py to generate concise summaries
- Add prompt template for summary generation
- Integrate summary generation after discussion guide creation
- Display summary under focus group title in list view with fallback to description
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The upload section had more prominence than Audience Brief and Research
Objective, causing users to focus there first. Now collapsed by default
with "(Optional)" label to de-emphasize relative to primary inputs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add tooltip explaining what data improves persona accuracy
- Add "What data should I upload?" section with bullet list
- Update "What's included in the personas?" section with revised copy
- Add PowerPoint support to allowed file types
- Make FieldTooltip example prop optional for simpler tooltips
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed the Select Participants grid from 3 columns to 2 columns on large screens to match the visual pattern used elsewhere in the platform.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated the asset upload section in the Focus Group flow to use more
intuitive terminology and provide better guidance about its purpose.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
The term "Cooper Profile" confused non-UX users. Renamed to "Attitudinal
Profile" to align with user language and documentation terminology.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Users can now see helpful context next to each model option:
- Gemini 3 Pro (Slow, best for most tasks)
- GPT-4.1 (Fast, best for speed)
- GPT-5 (Slow, best for complex tasks)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Clarifies the distinction between these form fields by adding (?) tooltip
icons with explanatory text and expandable examples. Updates placeholder
text and removes redundant FormDescription elements.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace suggestions panel with auto-apply: enhanced text now populates form fields automatically
- Add modal showing assumptions made during enhancement (3-5 bullet points)
- Reduce prompt scope by 50% for more focused, impactful enhancements
- Update backend to return enhanced text + assumptions instead of suggestions array
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Wrap temperature slider in accordion labeled "Advanced Controls"
- Rename "AI Creativity Level (Temperature)" to "Creativity Level"
- Replace numeric labels with descriptive terms (More Focused & Consistent / More Diverse & Creative)
- Remove "Current" value display
- Change default from 1.0 to 0.75 (centered position)
- Update description with user-friendly language about variance and hallucination risk
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Created new reusable ProgressModal component with animated progress bar
- Converted all inline GenerationProgressBar usages to modal dialogs:
- AIRecruiter.tsx: Persona generation
- FocusGroupModerator.tsx: Discussion guide generation
- FocusGroupSession.tsx: Key themes extraction
- SyntheticUsers.tsx: Persona summary generation
- PersonaModificationModal.tsx: Persona modification
- Modal features: auto-dismiss after completion, non-dismissible during operation,
cancel support, progress animation from 0-90% over 54 seconds
- Fixed broken theme generation state calls in FocusGroupSession.tsx
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>