Spaces:
Running
Running
Commit History
-
Drop reflective_question from dimension-event cardsβ Running
Not wanted on this card type after seeing it rendered. Removed end to end rather than just hiding it in the UI β the prompt no longer asks Claude to generate it, so there's no wasted output tokens on text that was never going to be shown. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>99aec30 -
Route dimension-event phrasing through Claude, batched (Option B)β
Home feed's maturity cards (Vocabulary Richness, Pace, etc.) were pure Python string templates β the same one-of-five sentence shapes forever, which is why they read as flat next to Session Recap's Claude-written cards, and why the same dimension crossing into "steady" in two scopes at once produced two near-duplicate cards back to back. The trigger decision itself (trigger_detector.py's if/elif logic β which of the 5 rules applies) is untouched and stays fully deterministic; that decision is a numeric threshold comparison and must stay reliable, not a place for LLM judgment. Only the phrasing step changes: every event that fires in one finalize run is now batched into a single Claude call (new pipeline/event_phraser.py) with the decided facts, the same dimension's state in its sibling scope, a few neighboring signals from the session, and the dimension's last-fired note for anti-repetition. Events for the same dimension firing in multiple scopes in one run are grouped into ONE card iβ¦70d37d2
-
Reflected Back cards: match left-border color to the signal's own dotβ
Border pulled from framing type (Observation/Strength/Growth area β 3 colors) while the bullet dot pulled from the signal's own fixed color (14 colors, same ones used for that signal on the Home feed and spectrum chart) β same card, two unrelated color systems, looked broken. Border now follows the dot's color; the framing badge pill keeps its own color since it conveys separate information. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>3a2b5d9 -
Clicking the header logo/wordmark returns to Homeβ
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>743fe31 -
Remove raw filename from session header, un-cap spectrum intro widthβ
The session detail header showed the internal upload filename (meet_segment_2.webm) β not meaningful to a user, dropped it along with the now-unused filename/detected_speaker destructures. Session Spectrum's intro paragraph had maxWidth: 62ch, appropriate for reading text but making it sit cramped on the left above cards that span the full width. Removed the cap. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>3efe926 -
Distinct colors per conversation type on Historyβ
Every session card and filter chip used the same blue regardless of context, so the list read as visually flat. Each context now gets its own fixed color (grouped by display label, since several raw context keys collapse to the same label β e.g. social/casual both render as "Casual & Low-Stakes" and must share a color). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>186c898 -
Bump extension version to 1.4.2 for CWS resubmissionβ
1.4.1 already live before the session-detail banner/carousel fixes landed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>5a521eb -
Session detail: auto-dismiss saved banner, one-card-at-a-time observationsβ
"Session saved" banner sat there permanently instead of reading as a confirmation toast β now fades out ~4s after mount. Behavioral observation cards fit ~3 per screen in the horizontal scroller, so it read as a normal grid rather than a scrollable stack. Cards are now sized to the container (88%) so one is dominant and the next peeks in at the edge as a scroll affordance. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>974780e
-
Bump extension version to 1.4.1 for CWS resubmissionβ
1.4.0 was already submitted and approved before the Home/You empty- state changes landed β those need their own version to go out. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>c0d6859 -
Richer empty states for new users on Home and Youβ
Bare "your mirror is waiting" text gave no sense of what's coming and no next action. Home now shows a real example card (faded "Example" badge) so a new user sees the feed instead of just reading about it; You lists what the standing portrait will contain. Both add an "Open Google Meet" CTA since recording can only start from an actual call. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>0338292 -
Bump extension version to 1.4.0 for CWS resubmissionβ
Ships the 4-step onboarding rebuild, Google OAuth button fix, 40-minute recording cap, and upgrade card that landed in earlier commits but were never packaged for the store. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>391f68a -
Recording segment cap, 4-step onboarding, Google OAuth fix, upgrade card, Home feed polishβ
- offscreen.js/background.js: recording now hard-caps at MAX_CHUNKS=2 (40 min total) instead of continuing indefinitely. The final segment routes through background.js's normal handleStop() (WebRTC-timeline flush before stopping) instead of a plain boundary cut, so the last chunk's speaker timeline is complete. The 30s pre-boundary warning now distinguishes "continuing automatically" from "recording will end." - AuthView.jsx: fixed the Google sign-in button being hidden specifically inside the extension (display:none leftover from before the chrome.identity.launchWebAuthFlow path existed) β handleGoogle() already supported both contexts, only the button visibility was wrong. Added diagnostic logging for the OAuth callback failure path. - OnboardingView.jsx: rebuilt to 4 steps (Concept/How/Preview/Trust) β Preview is new, showing an example portrait card (real quote+tags format, not numeric scores) plus a compact "Already reflected back" hint and an honest "what β¦401c4a8
-
Scope onboarding-done state per account, not per browserβ
bm_onboarding_v1 was a single flat localStorage key with no user scoping β once any account finished onboarding on a browser, every other account signing in on that same browser (e.g. a friend testing on your machine, or you testing a second account) silently skipped it too. Now keyed as bm_onboarding_v1_<user.id> and re-checked whenever the signed-in user actually changes, not just once at mount.9d84a97 -
Bump extension version to 1.3.0 for CWS resubmissionβ
The approved CWS listing (v1.2.0, submitted 2026-06-23) predates essentially everything built this session: the web_accessible_resources fix that made password reset work, the entire History/Session Spectrum rebuild, and the onboarding/privacy/How It Works content update. This version needs its own CWS review before any of that is actually live for users installing from the store.6e34b24
-
Bring onboarding, How It Works, and privacy policy up to dateβ
These hadn't been touched since the CLAUDE.md engine rebuild and were describing a product that no longer exists: voice enrollment, the disabled Upload path, a 5-trait Confidence/Assertiveness/Composure radar, Groq Whisper transcription, pyannote diarization. All fully removed in favor of what's actually true today: Deepgram Nova-3, Claude for phrasing, no diarization (the mic identifies you by construction), and real self-relative signals with no numeric grades. Onboarding goes from 2 steps to 3 β dropping the dead "Upload" path freed up room for a dedicated trust/privacy step ("What happens to your recording"), rather than the one small gray footnote it was buried in before. That same "only your patterns are kept, whoever else is on the call is never profiled" point now appears consistently in onboarding, How It Works, the privacy policy, and the recording consent modal β a real, distinctive design decision that wasn't stated anywhere in the product until now.88c192b
-
Fix HistoryView Retry button sending page=[object Object]β
onClick={loadSessions} passed React's click SyntheticEvent as the first argument (pageNum), which then got template-interpolated straight into the request URL β confirmed in production logs as repeated 422s on GET /api/sessions?page=[object%20Object].c93687d -
Home recap: drop resonance vote, add colored signal labelβ
The vote already lives on the session detail page (voting twice on the same observation was redundant); Home's card now just shows the observation and its reflective question. Also replaces the hardcoded signal->color lookup (which only covered old signal-key names and silently fell back to gray for the free-form names the LLM actually generates, e.g. "topic_transition") with a deterministic hash-based color picker shared between Home and the session detail page, so every signal gets a real color and the same signal reads the same color on both surfaces.b6afdb8 -
Rebuild History/session-detail into 3 CLAUDE.md-compliant tabsβ
Replaces the old Dimensions tab (numeric 1-5 trait scores) and the per-participant speaker-timeline chart (rule #8: persisted behavioral signals for every other room participant, indefinitely) with: - Session Spectrum: 7 composites (Speech Style, Vocal Arousal, Rapport, Power Balance, Turn-taking Courtesy, Fluency, Responsive Engagement), each a self-relative "more/less than your usual" read computed by z-scoring components against their own history at read-time, never a stored raw score. New evidence_gate.py layer, verified with 18 synthetic checks. - Overview: metrics-first ordering, Notable Pattern removed (redundant + violated rule #3), Behavioral Observations horizontal-scroll with the resonance-vote layout fixed (vote now sits against the observation, not the adjacent reflective question) and tips attached via existing coaching_suggestions[].dimension_key matching. - HistoryView: dropped the numeric score dots and the speaker-timeline chart, added one self-reβ¦31abd7f
-
Complete the password reset flow; fix feedback email senderβ
AuthView gains an "update-password" mode (new password + confirm, calls supabase.auth.updateUser) and App.jsx now catches Supabase's PASSWORD_RECOVERY auth event to route there before the normal app/onboarding. The reset email's redirectTo now points at the extension's own fullpage URL (built dynamically via chrome.runtime.getURL, not hardcoded), since there's no hosted copy of the app to redirect to otherwise. manifest.json declares index.html as a web_accessible_resource β without it, Chrome silently blocks external navigation into the extension with ERR_BLOCKED_BY_CLIENT, which is what an actual end-to-end test surfaced. Also switches the feedback-notification email's sender to Resend's shared sandbox address (onboarding@resend.dev) so it works with any API key immediately, rather than requiring mirrorai.live's domain to be verified in Resend first. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>454186b -
Revert to the bar-graph logoβ
The Dome/Clarity mark didn't land well in practice β reverting App.jsx, AuthView, OnboardingView, HowItWorksView, ProfileView's empty state, favicon.svg, generate-icons.html, and the extension icon PNGs to their pre-dome-mark state, and removing the now-unused Logo.jsx. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>7dd0d81 -
Replace the bar-graph logo with the Dome/Clarity markβ
Introduces a single shared Logo.jsx component (DomeMark + LogoLockup) and retires 5 independently hand-duplicated copies of the old equalizer-bar SVG across App.jsx, AuthView, OnboardingView, HowItWorksView, and ProfileView's empty state. The new mark matches docs/Mirror_Canonical_Vision.md's "Clarity" mark: a faint dashed dome above the mirror line, a solid dome below rendered with a radial gradient (bright center, deepening toward the edges). Also rewrites favicon.svg and generate-icons.html to match, and regenerates the extension's icon16/48/128.png against a dark background rather than the old near-black canvas default. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>f9393f8
-
Rebuild the You page: fix stale 9-signal bug, add paragraph/tags/indicators/coachingβ
Rewrites Shape/Reflected Back/How You Shift By Context's shared signal-key maps against the current 15-dimension set (they were still keyed on the old 9-signal names, silently clamping ~10 dimensions to the chart's max), adds categorical axis support, and adds a per-signal color palette. Adds three new You-page sections built on the existing evidence-gated portrait system: a self-referential narrative paragraph + behavior-phrase tags, a plain-fact indicators strip (session count, time recorded, avg talk-share/pace, contexts covered), and coaching synthesis ("Where You Might Grow") that distills recurring coaching_suggestions grouped by a new dimension_key field. Recadences the existing signals/context-shift synthesis call from every-session to every-3- sessions, adds Shape's established-vs-recent overlay, curates Signal History down to 7 signals, and renames "What We've Noticed" to "Reflected Back". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>22395e0
-
Home feed v2: 15-dimension evidence engine + trigger-detection + interleaved feedβ
Replaces the static 9-signal/5-card-type Home feed with a real evidence-gated system: 15 tracked dimensions (was 9, plus 3 fold-in sub-signals), a new categorical evidence path for signals whose mean sits near zero (pacing/energy arc), and a trigger-detection engine that diffs each session's evidence against persisted state to fire one of 5 event types (first-time-steady, drift, recurring, context-shift, single-session anomaly) with a shared 2-session cooldown. Home now interleaves an unconditional per-session recap card with these frozen, dated dimension events instead of recomputing static cards from live evidence on every read. Also reformulates 5 signal computations (curiosity as a rate, room-wide interruptions, a 4-input reweighted drive score, a building-on-others denominator fix, and fixed-window vocabulary richness to remove a session-length confound), and adds two new Supabase tables (signal_evidence_state, dimension_events) to support the trigger engine. Co-Authored-By: Claβ¦9ceaaad
-
Fix crash + noise in audio diagnostic loggingβ
playbackCtx.onstatechange threw "Cannot read properties of null" once stopRecording() nulled the outer playbackCtx variable before the AudioContext's own final 'closed' event fired β closure was reading the reassigned variable instead of a stable reference to the context object itself. Also downgraded routine WebRTC connection-state transitions (checking/connecting/connected) from warn to log, since console.warn was flooding chrome://extensions' Errors page with normal lifecycle noise and burying anything actually worth seeing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>3b255ec -
Fix still-forming cards mislabeling stable-but-noisy signals; add audio diagnosticsβ
still_forming (Home + You page) was including signals that already had enough samples but were still too variable (high CV) to call steady β these showed as "6 of 5 sessions" and would never resolve since more sessions alone don't fix variance. Now omitted entirely once the sample floor is met but steadiness still isn't reached (say nothing rather than mislabel), confirmed against the exact real-account scenario that surfaced this. Also clamps both progress-bar widths defensively. Adds non-invasive diagnostic logging (track mute/unmute, AudioContext state, RTCPeerConnection connection state) to the WebRTC injector and offscreen recorder, investigating intermittent audio dropout reports during live testing β pure logging, no behavior change. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>c1392fe
-
Phase B3 second slice: replace Mirror Feed with evidence-gated Home feedβ
Retires the LLM free-form mirror_feed/recurring_coaching system (no dismissal awareness, session-count-gated patterns) in favor of five card types built from already-computed evidence and portrait data: strength, observation, how-it-may-land, progress, and still-forming. Cards are self-relative, carry their evidence, and are dismissable via a new dismissed_cards table β dismissing a growth_area/observation framing of a signal shares one key so it holds even if the portrait LLM later reclassifies it. Home is now the app's default landing tab. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>7d68132
-
Phase B3, You page: evidence-based standing portrait replaces trait scoringβ
Retires the numeric dimension-scoring "personality" system from the You page (pentagon chart, 0-100 dimension scores, personality-trait badges β the clearest CLAUDE.md rule #2 violation in the app) and replaces it with a standing portrait built entirely on the 9 relational signals' evidence-gating system from Phase B2. Scoped to the You page only, per earlier decision: dimension_scorer.py keeps running unchanged, still feeding HistoryView and ResultsView's dimension displays β untouched this slice. - New backend/pipeline/portrait_synthesizer.py: replaces PersonalitySynthesizer's role. Only phrases signals that are already evidence-steady, classifies each qualitatively (strength / growth_area / observation, never a number), and phrases cross-context comparisons for signals steady in 2+ of the user's own contexts. Reuses the existing Groq call pattern (Claude migration stays deferred per earlier decision). - main.py: new _compute_profile_evidence() computes evidence for all 9β¦ed3866e
-
Phase B1: quarantine pyannote/voiceprint off the live path, remove Upload UIβ
Per CLAUDE.md rule #1 (no diarization/voiceprint guessing on the live path), now that the mic-capture keystone means the user is identified by construction. Changes: - backend/main.py: removed the pyannote diarize() + voiceprint-matching fallback branch from _run_prepare_job entirely. When no WebRTC speaker timeline is available, the job now fails cleanly with a clear error instead of silently guessing the speaker. Also removed _update_voiceprint() (was unconditionally running pyannote embeddings on every session, including WebRTC-mode ones β a live-path violation this audit surfaced). diarizer.merge_transcript_with_speakers() stays; it's a transcript/timeline merge utility, not diarization itself, and the WebRTC path depends on it. pipeline/diarizer.py and pipeline/voiceprint.py are left in place (quarantined, not deleted) for a possible future upload-a-file feature. - Frontend: removed the Upload nav tab + UploadView, and the "Train your voice" account-menu entrβ¦0507574 -
Self-heal a 401 mid-chunk by refreshing the auth token on demandβ
prepare and finalize can now be several minutes apart (2 transcriptions, diarization, signal extraction, scoring, an LLM call) β long enough for the Supabase token cached at recording-start to go stale before finalize runs, which surfaced as "Finalize failed (HTTP 401): Invalid or expired token" during mic-capture verification. background.js now retries once on a 401 by asking any open extension page to force-refresh its session via getSession() (which refreshes on demand if expired) and reports the fresh token back over runtime messaging. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>ae18cb8 -
Route mic permission through a dedicated extension tab; parallelize mic+tab transcriptionβ
getUserMedia's permission prompt cannot render inside a side panel or popup (confirmed Chromium limitation) β it silently rejected with no UI. Adds request-mic.html/js, a minimal extension tab that can show the real prompt; the side panel now opens it only when permission isn't already granted, and waits for the result via a message + tab-close listener. Also runs the new mic transcription concurrently with the existing tab transcribe/diarize pipeline (background ThreadPoolExecutor) instead of sequentially before it, to cut the added backend latency roughly in half. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>5c375d9 -
Capture the user's own mic as a second stream in Meet recordingβ
Previously only tab audio (other participants) was recorded and transcribed; the user's own mic was used for VAD timing only, so their speech content never appeared anywhere. Adds a second, synchronized MediaRecorder on getUserMedia({audio:true}) in the offscreen document, uploads it alongside the existing tab stream, and transcribes it independently on the backend into a new mic_transcript field β never merged into the existing tab-based transcript/diarization/scoring pipeline. Bootstraps mic permission from the visible side panel since the offscreen document can't show its own prompt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>9cf6c37
-
Bump extension version to 1.2.0 for CWS resubmission
5b45db1 -
Add job timeout watchdog, session pagination, feedback modal, and store assetsβ
- Backend: 15-min per-job timeout using threading.Timer + _cancelled set; fires at every existing cancellation checkpoint in both prepare and finalize jobs - Backend: GET /api/sessions now paginated (page/page_size params, returns total + has_more) - Frontend: HistoryView loads 10 sessions at a time with a "Load more" button that appends - Frontend: FeedbackModal component wired into Account menu β Send feedback - Landing: CNAME for mirrorai.live custom domain - Store assets: listing copy, screenshots template, promo tile for CWS submission Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>0580b30
-
Replace password toggle emoji with SVG eye iconsβ
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>dd61d52 -
Hide Google OAuth button in extension contextβ
Continue with Google is hidden in the Chrome extension side panel since it requires a separate Chrome Extension OAuth client setup. Email/password auth works for all users in extension context. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>fb84c92 -
Revert implicit flowType β use PKCE so Supabase exchanges code server-sideβ
With flowType implicit, Supabase set our extension URL as Google's redirect_uri directly, meaning we received a raw Google auth code that can't be exchanged client-side. With PKCE (default), Supabase handles the exchange via its own callback and redirects to our extension URL with a Supabase-issued code that exchangeCodeForSession can handle. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>28baf74 -
Fix Google OAuth callback: check query params and hash, show real errorβ
Supabase can return tokens in query params or hash depending on version. Also surface the actual OAuth error string instead of generic message. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>15fae7a -
Fix Google OAuth in Chrome extension: implicit flow + PKCE fallbackβ
- Set flowType:'implicit' in Supabase client so tokens come in the URL hash, which is what launchWebAuthFlow captures (PKCE sends a code that requires a server-side exchange, not usable in an extension callback) - Handle both implicit (hash access_token) and PKCE (query code) in callback so it works regardless of Supabase project settings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>254e7f6 -
Fix tab capture: always get fresh stream ID on-demand + propagate offscreen errorsβ
Pre-fetched stream IDs expire in ~10 seconds, so using them when the user finally clicks Start Recording caused silent "Error starting tab capture". - handleStart: try on-demand getMediaStreamId first (always fresh); pre-fetched is now a last-resort fallback only - handleStart: check offscreen sendMessage response and return the error instead of blindly setting recordingActive = true even when capture failed - Bump consent key to v3 so the one-time modal re-appears after this fix Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>0be84d5 -
Fix backend round(dict) crash + tab capture permission + consent/results UXβ
- Fix TypeError in backend: logger was calling round() on dimension group dicts (dimensions values are nested dicts, not scalars) - Fix tab capture "Extension has not been invoked": moved getMediaStreamId to background SW action.onClicked (where activeTab grant lives); removed it from panel page which can never hold that grant - Switch openPanelOnActionClick to false + manual sidePanel.open() so activeTab grant reaches the SW correctly - Bump consent key to mirror_consent_v2 so existing users see the modal again - Remove 5-second auto-dismiss on analysis results; add persistent "View in History" button instead - Wire onViewHistory prop through App β MeetStatusBanner β history nav Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>886eaea -
Update recording consent message to be friendlierβ
Reframes from "you must get consent" to "this is for your personal growth, here's what we do with it, and please give others a heads up." Compliant with Chrome Web Store requirements while being less heavy-handed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>1e8e010 -
Add open-as-full-page featureβ
- Small expand icon button in the header (side panel only) opens the extension as a full browser tab at index.html?fullpage=1 - Full page mode: wider layout (900px, 40px side padding vs 600px/24px), no MeetStatusBanner (recording belongs in the side panel) - Expand button hidden when already in full page or not in extension context - isExtension and isFullPage are module-level constants so they don't recompute on every render Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>1417226 -
Redesign onboarding to 2 steps + add recording consent promptβ
Onboarding: - Cut from 3 steps to 2: concept screen (what Mirror is) + how-to screen (two paths: Google Meet live recording vs file upload) - Step 2 now accurately describes the current product β removed the old "upload only" framing, added Meet recording path with clear description - CTA changed to "Open the mirror β" on final step - Removed StepPreview (mock profile) β reduces time to first real use Recording consent: - First-time "Start Recording" click now shows a modal: "You are responsible for ensuring all participants consent to being recorded" - User must confirm before recording starts; choice stored in localStorage (mirror_consent_v1) so prompt never appears again Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>aff2ced -
Remove enrollment gate, add 15-session monthly capβ
- App.jsx: enrollment no longer blocks access β removed the voiceprint status check and the blocking EnrollView screen. Voice training stays available in Account menu as an optional setting. - main.py: /api/prepare/start checks monthly session count before processing; returns 429 when >= 15 sessions used this month. New /api/usage endpoint returns used/limit/remaining/resets_on. - UploadView: shows a subtle session usage bar (turns orange at β€3 remaining, red at 0) and disables the upload button when limit is hit. Refreshes usage count after each successful analysis. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>edee3c4
-
LLM-generated portrait tags (max 4, behavior-specific)β
PersonalitySynthesizer now outputs 3-4 keyword tags grounded in fingerprint observations (e.g. "Reframes Questions", "Topic Driver") rather than fixed score-bucket labels. ProfileView uses personality.tags from the API instead of the old deriveKeywords() mapping. Bump _SYNTHESIS_VERSION to 7 to invalidate cached portraits. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>2e7ca87 -
Restore dot-grid backgroundβ
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>a65851a -
Portrait layout, clean background, richer Recurring Themesβ
- Portrait: text justified full-width, keyword tags in a row below (not side-by-side) - index.css: remove dot-grid overlay so panel background is clean dark (not grey) - main.py: normalize coaching area synonyms (Active Listening β Listening, etc.) and capture the latest suggestion text per area - ProfileView: Recurring Themes shows "{N} of {total} sessions" count + tip text so each card explains what to work on, not just a label with a flagged count Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>dbd59f3 -
Mirror feed: gradient fade on 3rd item with Show more overlayβ
Replace the separate button with a gradient that fades the bottom of the 3rd card from transparent to the page background (#0f1117), with a "Show more" pill overlaid on it. Clicking anywhere on the gradient expands the feed. "Show less" appears as a plain text link below when expanded. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>a88c856 -
Richer portrait + collapsible mirror feedβ
PersonalitySynthesizer: - Paragraph rules now direct the LLM across 7 behavioral vocabulary dimensions: thinking style, argument framing, conversation navigation, handling challenge, clarity/precision, listening quality, warmth/relational style - Session log now passes fingerprint[:350] (was [:200]) as the PRIMARY source rather than raw dimension scores β the qualitative text matters more - Explicit rule: do NOT make dominance/talk ratio the portrait centrepiece if fingerprints reveal more interesting things - Bump _SYNTHESIS_VERSION 5 β 6 to force portrait regeneration ProfileView: - MirrorFeed is now collapsible β shows 3 items by default - "Show N more" button expands to full list - "Show less" collapses back to 3 - Extracted MirrorFeedItem component for cleaner rendering Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>6744cd1 -
Remove reflect tab β saves one full LLM call per sessionβ
Each session was making a separate 800-token reflection-questions call on top of the main 3000-token insight call. The content overlapped with resonance_prompts already embedded in observations and the coaching tab. Removing the tab, the backend call, and the three generator methods. Finalize job is now 3 steps instead of 4. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>b665409