Spaces:
Sleeping
Sleeping
Commit History
-
Drop reflective_question from dimension-event cards
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
-
Trim leading/trailing silence from session duration; free-tier lifetime cap + upgrade-interest capture
- session_duration_s now spans first-speech to last-speech instead of recording-start (t=0) to last-speech, so pre/post-meeting dead air no longer inflates silence_ratio, crosstalk_ratio, or the duration reported to the insight-generation prompt. Verified with a real SignalExtractor test (leading + trailing silence, confirmed both trimmed correctly). - Free session cap changed from 15/month (resetting) to 7 lifetime — a one-time trial pool, not an ongoing allowance. /api/usage and /api/prepare/start now share one _get_lifetime_session_count() helper instead of duplicating the count query. - New POST /api/upgrade-interest — a fake-door demand signal (no real payment/Stripe): records the click in a new upgrade_interest table and emails a notification, so real pricing/volume decisions can be made from actual interest instead of a guess. Verified end-to-end with a real Supabase insert/read-back and a real Resend email send, using disposable test data cleaned up afte…44885c8 -
Backend hardening: ffmpeg/multi-party fixes, 20-min recording cap, remove dead dimension_scorer
- ffmpeg: check subprocess returncode + wrap wave.open in try/except on both main and mic audio; fail clean (400) on the main stream, fail soft (mic_audio_path=None) on the supplementary mic stream instead of an uncaught crash on corrupted uploads. - Multi-party dyadic partner selection: pick the non-user speaker with the most total speaking time instead of an arbitrary Python set-ordering pick, for the handful of genuinely dyadic signals (pauses, turn_dynamics, legacy questions, engagement_proxy, crosstalk). - Drift direction: compute real up/down for continuous-signal drift events (was hardcoded None) so Home feed's "Shifted" cards can show a real arrow. - Recording cap 25->20 min: _JOB_TIMEOUT_S and the server-side hard-reject (1320s, a small buffer above the 20-min client cap) updated to match. - Removed dimension_scorer.py entirely (724 lines) — the old 0-100 numeric trait-scoring engine, superseded by the evidence-based system. Confirmed zero usage anywhere (b…556fba2
-
Add real range/agreement-count to dimension-event card copy
Continuous signals (pace, vocabulary richness, etc.) now show their actual mean+-std band alongside the point value ("170 words per minute (typically between 155 and 185)"); categorical ones (energy arc, pacing arc) show how many of the recent sessions actually agreed ("decreasing, showing up in 3 of your last 5 sessions"). Both numbers were already computed to decide steadiness in the first place, just never surfaced in the card copy before now. Existing dimension_events rows were backfilled directly (one-time script, not committed) using each row's own previous_value/label as prior and freshly recomputed current evidence, since card_copy_json freezes permanently at fire time and wouldn't have picked up this change otherwise.5351d38 -
Fix 500 on Session Spectrum: guard against pre-migration session data
Real session history spans this whole project's evolution — sessions recorded before hedging/directness/curiosity/drive_vs_follow/etc existed are missing those signal groups entirely, not just holding a null value inside them. compute_composite_position's extract calls had no protection against that, so a KeyError from one old session anywhere in a user's history took down the whole /api/sessions/{id}/spectrum request with an unhandled 500 (the recharts stack trace in the browser's error panel was just where the resulting bad response surfaced client-side, not the actual cause). Fixed at the source (_safe_extract in evidence_gate.py, so both the spectrum endpoint and the HistoryView highlight benefit) plus a defensive per-composite try/except in the endpoint itself. Verified against a synthetic mixed old/new-format history — composites that lack enough real samples now correctly report "not steady" instead of crashing.669970c -
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
-
Switch feedback email sender to verified mirrorai.live domain
Resend domain verification is done, so drop the temporary sandbox sender in favor of the real feedback@mirrorai.live address.f448001 -
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
-
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
-
Add temporary turn-timeline debug log (structure only, no transcript text)
Logs speaker/start/end/duration and gap-vs-same-or-different-speaker for every merged turn, to visually verify turn/gap structure during testing. Never logs transcript content, only timing — consistent with the privacy rule against persisting/exposing room content. Remove once no longer needed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>5876422 -
Use the mic transcript as the source of truth for the user's own speech
Tab audio (chromeMediaSource: 'tab') captures what the tab plays back — Meet never echoes your own voice through your own output, so it structurally can't reliably contain the user's speech, only the other participant's. The whole signal pipeline was built from a tab-audio transcript regardless, attributing segments to the user via WebRTC-VAD-timeline matching against a transcript that mostly didn't contain them in the first place. The mic transcript was already computed but explicitly discarded as "proof-of-capture only" — a real scripted test recording confirmed it was consistently far more complete than the tab-derived alternative. Now builds the merged transcript from two sources instead of one: other- speaker segments still come from the tab transcript (already reliable there), but the user's own segments come directly from the mic transcript, no VAD- matching needed since that recording is isolated to the user by construction. Falls back to the old tab-VAD-attributed behavior if…163ac47
-
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
-
Migrate phrasing layer from Groq to Anthropic Claude (CLAUDE.md rule #9)
Swaps all 4 LLM call sites (insight_generator, context_detector, portrait_synthesizer, main.py's session-summary consolidation) from Groq/llama to Claude Sonnet 5. Deletes personality_synthesizer.py — confirmed dead code, superseded by portrait_synthesizer during the You-page rebuild; only its .client was still being reused. Three real API differences found via live testing, not assumed: claude-sonnet-5 rejects an explicit temperature param entirely; response text isn't reliably content[0] since a thinking block can precede it on longer prompts (new pipeline/llm_utils.py extracts by block type instead of position); and thinking was silently consuming ~93% of the token budget on the richer prompts, truncating output before max_tokens was reached — fixed by disabling thinking for these structured-output calls, which don't need multi-step reasoning. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>dbbf495
-
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 B2 remainder: hedging, directness, question-impact, drive-vs-follow, building-on-others
Completes CLAUDE.md's 9-signal priority list as rule-based v1s — the Groq→Claude phrasing migration is explicitly deferred for now, so no new LLM dependency is introduced here, including for the two signals (building-on-others, drive-vs-follow) that conceptually most want semantic reasoning. Both ship with an honest interpretation_note-style caveat (matching the existing engagement_proxy pattern) rather than overclaiming precision, with a clear upgrade path once an LLM reasoning pass exists. - signal_extractor.py: extracted _build_all_turns (the chronological turn-sequence pattern already inline in _compute_interruptions) into a reusable helper — verified byte-identical output on synthetic fixtures before relying on it elsewhere. Added 5 new _compute_* methods: - hedging / directness: phrase-list rate signals mirroring the existing filler pattern exactly, independent of each other (not 1-hedging — a neutral statement is neither) - question_impact: reuses the room-wid…d2b8330 -
Phase B2 first slice: per-signal evidence gating, replace population norms
Implements CLAUDE.md rule #3 (gate on accumulated evidence per signal, never session count — session 1 = raw observations only) and retires rule #4's population-norm violation (self-relative comparisons only). - New pipeline/evidence_gate.py: pure, testable module computing per-signal steadiness (min 5 samples + coefficient-of-variation under a per-signal threshold, over a rolling 10-session window). Wired up for the 4 signals with solid extraction infra already in place: talk-share, curiosity (question rate), pace, pauses. Extension point left for hedging, directness, building-on-others, question-impact, drive-vs-follow once their extraction exists (likely needs a new Claude reasoning pass over the transcript — not built yet, deferred to follow-up work). - main.py: deleted CONTEXT_POPULATION_NORMS entirely (no population comparisons, ever) and the dead _get_user_baseline. Replaced _get_context_baseline with _get_context_evidence, which always returns a per-signal…eba06d8 -
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 -
Log mic audio duration vs last transcribed timestamp; fix stale Whisper message
Diagnostic for a user report that a recording ran longer than its mic transcript — this makes it possible to tell whether the gap is a capture/ upload truncation or Deepgram not transcribing the tail, instead of guessing. Also fixes two leftover "Transcribing audio with Whisper…" progress messages that weren't updated when the ASR provider switched to Deepgram. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>bc05591 -
Switch ASR from Groq Whisper to Deepgram Nova-3
Groq Whisper mis-transliterated Hindi/Hinglish speech into Urdu script during the mic-capture keystone verification — a documented Whisper failure mode on code-switched audio, not a one-off glitch. Deepgram Nova-3 with language=multi handles Hindi-English code-switching correctly (verified locally: Devanagari script preserved, "mirror" correctly kept in Latin script mid-sentence) and mip_opt_out=true gives an explicit guarantee audio is never used for model training, matching the transient/discard privacy design. Sends the already-produced 16kHz mono WAV directly to Deepgram's REST API instead of Groq's SDK + mp3 downsample step. Output shape (segments/words) is unchanged so no downstream callers needed changes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>706b280 -
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
-
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 -
Add feedback endpoint with Resend email notifications
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>a440db2
-
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 -
Fix and update privacy policy
- Correct inaccurate statement: audio IS written to temporary disk storage during processing (was incorrectly saying "server memory only") - Voiceprint section: clarified it is optional and can be skipped - Add paragraph about in-app consent prompt for Meet recording - Add explicit bullet: recording never happens automatically - Update effective date and last updated to 16 June 2026 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>cb971f9 -
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 -
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 -
Fix missing trend signal in mirror feed — synthesizer was blind to numeric improvement
Root cause: mirror_feed_synth.synthesize() only received qualitative fingerprint text. The computed trends list (filler_rate, wpm, talk_ratio — early vs recent sessions) was calculated in get_profile but never passed to the synthesizer. The LLM had no numerical evidence of change, so it could never generate trend_up / trend_down items. Fix: - Add signal_trends + signal_patterns params to MirrorFeedSynthesizer.synthesize() - Add _format_signal_trends() helper that formats hard data with explicit type hints: "↑ IMPROVED filler_rate: 8.2/100w → 3.1/100w → generate a trend_up item for this" - Inject the trends block into both _build_prompt and _build_consolidated_prompt - Pass trends and patterns from get_profile to the synthesizer call - Bump _MF_VERSION 5 → 6 to force feed regeneration with the new data Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>ed78629 -
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 -
Unlock behavioral vocabulary — break repetition loop across sessions
InsightGenerator: - Expand WHAT TO LOOK FOR from 5 narrow points to 25 across 7 behavioral clusters: perspective/thinking style, clarity/expression, conversation navigation, handling challenge, listening quality, self-awareness, warmth/relational - Add ANTI-REPETITION DIRECTIVE: known patterns from session history get at most one brief reference — primary job is finding what is NEW or nuanced - Add DIVERSITY RULE: each observation must cover a different cluster - Add STRENGTH RULE: at least one observation must be about a quality or strength - Update fingerprint instruction to require 4+ different behavioral dimensions and explicitly deprioritise already-established patterns (talk ratio, dominance) MirrorFeedSynthesizer: - Replace generic dimensions list with 10 explicit THEME CLUSTERS (A–J) - Add THEME CLUSTER RULE: no two feed items may come from the same cluster - Fix _parse cap: was silently truncating feed at 4 items, now allows 8 - Both prompt builders (consolidated + se…19b7615 -
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 -
Major feature update: Google Meet recording, cumulative mirror feed, UX overhaul
Backend: - Fix talk ratio inflation for multi-speaker Google Meet calls (use all_other_segs) - Add user_perspective field to InsightGenerator — user now feels personally seen - Mirror feed is now cumulative: items persist, evolve, and grow across sessions (v4) - Expose per-speaker WPM timeline in /api/sessions for history chart - Bump _MF_VERSION to 4 to force feed regeneration with new cumulative logic Frontend: - Google Meet WebRTC recording: content-meet.js + meet-webrtc-injector.js + offscreen audio pipeline - Speaker timeline chart in History tab (who spoke when, WPM per participant) - ProfileView: Portrait section moved above Mirror Feed (it's the centrepiece) - ProfileView: Recurring Themes section added (coaching areas flagged across sessions) - ResultsView: Summary tab removed, summary_sentence block removed - ResultsView: "Your Perspective" section added (user_perspective from InsightGenerator) - ResultsView: Visual 3-segment talk split bar (You / Others / Silence) - Results…5748a9d
-
Fix multi-speaker OOM + talk ratio inflation + add backend logging
372e8bd
-
Fix get_sessions 500 crash + extension panel stability
- backend/main.py: wrap each session in try/except in get_sessions so one malformed JSON field no longer crashes the entire endpoint with 500 - HistoryView: add loadError state and Retry button instead of silently showing "No sessions yet" when the API fails - MeetStatusBanner: sync a fresh Supabase token to the SW right before recording starts, preventing stale-JWT 401s on chunk upload - background.js: skip getMediaStreamId prefetch when already recording - manifest.json: add "tabs" permission for reliable Meet URL detection - vite.config.js: base "./" for correct extension asset paths - background.js: call sidePanel.open() before any await so it fires within Chrome's user-gesture window Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>8f4ee21
-
Use isinstance(Annotation) to robustly unwrap pyannote output
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>3534520 -
Revert pyannote pin, keep robust DiarizeOutput unwrapping
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>9039939 -
Robust pyannote output unwrapping + pin to 3.3.2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>c5d12d5 -
Fix pyannote >= 3.3 DiarizeOutput compatibility in diarizer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>feeca32
-
Add privacy policy page at /privacy
a161737 -
Add public /health endpoint for uptime monitoring
b1e449c -
Add omegaconf dependency for pyannote voiceprint embedding
32553aa -
pyannote token/use_auth_token compatibility fix
f8b6c58 -
Fix app_port to 8000 for HuggingFace Spaces
40501f4 -
Add HuggingFace Spaces README config
ff66b1c
-
Fix pyannote v3 use_auth_token → token
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>10270c8 -
Rename to mirror., scroll reveal animations, waveform logo, deployment config
- Renamed app from Behavioral Mirror to mirror. throughout - Added waveform SVG logo (option 2A) to all pages replacing emoji placeholders - Added scroll reveal animations (Reveal/RevealItem) to all pages - Cleaned requirements.txt: removed unused anthropic, openai-whisper, whisperx, sqlalchemy - Added Dockerfile with CPU-only torch and ffmpeg for Railway deployment - Updated CORS to allow chrome-extension:// origins via regex + FRONTEND_URL env var - Added .env.example template Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>d1cde70