Chore10:26 PM Β· ZRosserMcIntosh
update investor branding and add investors@ mailbox
- Change investor page contact from Rosser to Zachary Rosser
- Update CTA to investors@katura1999.com instead of personal email
- Restore footer label to 'Investors' (plural) across en/pt/es
- Add investors@katura1999.com as shared mailbox in email system
10:22 PM Β· ZRosserMcIntosh
write 33 approved foundational memories to MemoryNode
Feature9:53 PM Β· ZRosserMcIntosh
marketing nav group + under development page + memory review doc
- Add Marketing group (marketing, stella marketing, stella media, stella videos, sales goals, wholesale)
- Move Support from Sales group to Sales (Sales now: CRM, Invoices, Support)
- Add 'Under Development' link in System group β /admin/under-development
- Remove stella/goals/wholesale from commandPaletteOnlyItems (now in sidebar)
- Add EN + PT translations for groupMarketing, underDevelopment
- Directory of all 30+ pages removed from sidebar
- Organized by section with descriptions
- Direct links, no search required
- docs/YEN-FOUNDATIONAL-MEMORIES-REVIEW.md β plain-English review of all 15 seed memories for approval before running seed script
Update9:27 PM Β· ZRosserMcIntosh
duplicate Activity import + sidebar consolidation + memory instrumentation
- Merge duplicate lucide-react imports into single block (Turbopack)
- Core: Dashboard, Orders, Products, Projects, Customers, Collections, Inventory, Analytics
- Business Tools: Yen AI, Messages, Meetings, Email, Calendar, Tasks
- Sales: CRM, Invoices, Marketing, Support
- Team + Finance + Content + System (streamlined)
- All removed items still searchable via βK command palette
- Updated EN + PT i18n translations
- P0: Added structured logging to meeting-end memory extraction
- P1: Created /api/cron/yen-memory-maintenance daily cron (3 AM UTC) Calls runMemoryMaintenance() + logs getMemoryHealth() snapshot Added to vercel.json cron schedule
- P2: Created scripts/seed-yen-memories.ts β 15 foundational MemoryNode records (business identity, key people, policies, constraints) Uses graph system, not legacy YenMemory table
Feature8:47 PM Β· ZRosserMcIntosh
translation grouping + /admin/usage dashboard + memory hardening
- SubtitlePanel: groupConsecutiveLines() merges same-speaker lines within 8s
- Per-line translation awareness skips translation for same-language speakers
- sourceLanguage tracking in admin + guest meeting rooms
- GET /api/admin/usage β token/cost breakdowns by source, user, model, day
- DeepL, Deepgram, LiveKit cost estimation
- Budget status + token rate limit display
- /admin/usage page with KPI cards, sparkline, tables
- pruneExpiredMemories() β archives nodes past expiresAt
- decayUnreinforcedMemories() β archives stale low-importance nodes (60d)
- deduplicateMemories() β content-similarity dedup within scope+type
- runMemoryMaintenance() β single call for all cleanup tasks
- getMemoryHealth() β monitoring metrics for admin
- On-access pruning in buildMemoryContext()
Feature6:53 AM Β· ZRosserMcIntosh
no-hallucination hard rule + per-user & org-wide token rate limits
- Added top-level hard rule: Yen is FORBIDDEN from inventing or guessing any contact information (email, phone, address, name). If a tool did not return a confirmed value, Yen must honestly say so and ask. No exceptions.
- Added TOKEN_LIMITS constants (all env-var-overrideable): Individual: 40k/day Β· 200k/week Β· 600k/month Company: 200k/day Β· 800k/week Β· 3M/month
- Added checkUserTokenLimits(userId, tenantId): single parallel query checks all 6 windows and returns ok:false + limitKind + reason + usage
- Added getUserTokenStats(tenantId): per-user breakdown of token usage (day/week/month + cost) for the admin dashboard
- Added checkUserTokenLimits call after checkMonthlyBudget
- Returns HTTP 429 with rateLimited:true, limitKind, used/limit counts, and full usage snapshot β applies to ALL users including Katura employees
Update6:44 AM Β· ZRosserMcIntosh
clean meeting summary output, bypass sendEmail gate for Katura employees, update Yen signature
- handleGetMeetingSummary: replace JSON.stringify with fmtList() helper that renders action items / decisions / open questions / follow-ups as bullet points instead of raw JSON arrays
- evaluateGuard: made async; adds early ALLOW for sendEmail when recipient is *@katura1999.com or a known WorkerProfile.personalEmail (falls through to SOFT_GATE for all other external addresses)
- chat/route.ts + agent-runner.ts: await evaluateGuard() at both call sites
- compose-email/route.ts: replaced plain-text signature table with branded logo signature matching Rosser's format (Katura logo, navy divider, gold accent links)
Featureyen6:39 AM Β· ZRosserMcIntosh
structured feedback system β FeedbackEvent + PlaybookRule + GoldenExample
- yen-feedback.prisma: 3 new schema models
- SQL migration + runner
- API: /feedback, /feedback/[id], /playbook, /playbook/[id], /golden-examples
- YenFeedbackWidget: 4-button component (Good/Bad/Edited/Problem) + tag selector
- Audit pages: /audit/feedback + /audit/playbook with activate/retire controls
- chat/route.ts: injects active PlaybookRules into system prompt via raw SQL
- email/page.tsx: replaced memory-hack thumbs with proper YenFeedbackWidget
Updateyen6:21 AM Β· ZRosserMcIntosh
fetch work/personal emails from DB, never hardcode addresses
Updateyen6:17 AM Β· ZRosserMcIntosh
malformed Anthropic request after soft-gate + add listRecentMeetings/getMeetingSummary tools
Featureyen/email6:12 AM Β· ZRosserMcIntosh
fix personal CC email (Gmail), add post-send thumbs feedback β memory
Docsyen6:08 AM Β· ZRosserMcIntosh
comprehensive architecture doc β three products, full technical inventory
Featureyen5:59 AM Β· ZRosserMcIntosh
audit restructure β token spend dashboard + tools/guardrails/emails sub-pages
Featureyen5:49 AM Β· ZRosserMcIntosh
sendEmail tool β Confirm/Decline flow instead of refusal
- Register sendEmail tool definition (to, toName, cc, ccName, subject, bodyHtml, bodyText, note)
- Add handleSendEmail handler β calls /api/admin/yen/send-email (Brevo) after user approves
- Add dispatch case 'sendEmail'
- Tool description instructs model to always draft + call, never refuse
- Remove 'send emails without confirmation' from hard NEVER list
- Add dedicated '# Sending emails' section: draft from context, call sendEmail, let soft gate handle confirm/decline
- Explicit: 'The soft gate is the safety mechanism. You do not need to be the safety mechanism.'
- Math.floor(liveFirmCost) before formatPrice β ticks in whole dollars only (was 0.01 increments)
Featureyen5:39 AM Β· ZRosserMcIntosh
memory schema hardening β Virgil's 9-point review
- MemoryNode: add workspaceId, userId, archivedAt
- MemoryNode: comment on @@unique([tenantId,id]) enforced in SQL
- MemorySummary: label now non-null default 'overview' (required for compound unique)
- MemorySummary: @@unique now (tenantId, scope, scopeId, label) β Option B multi-summary
- MemorySummary: add refreshReason field
- Add @@index([tenantId, scope, scopeId]) to MemorySummary for queries without label
- All memorySummary upsert/findUnique use new key tenantId_scope_scopeId_label
- label defaults to 'overview' everywhere (was null/scopeId)
- ALTER TYPE ADD VALUE IF NOT EXISTS for all enum members (safe on existing DBs)
- ALTER TABLE ADD COLUMN IF NOT EXISTS for all new columns
- CHECK constraints: confidence [0,1], importance [1,10]
- UNIQUE(tenantId, id) on MemoryNode for composite FK safety
- Composite FKs: MemorySource and MemoryEdge reference (tenantId, nodeId) not just nodeId
- Partial indexes: active scope + active subject, ranked by importance DESC
- MemorySummary unique constraint migrated from (tenant,scope,scopeId) β (tenant,scope,scopeId,label)
- NULL label rows backfilled to 'overview' before constraint applied
- RLS enabled on all 4 tables with service_role bypass policy
Featureyen5:20 AM Β· ZRosserMcIntosh
Virgil's memory architecture β MemoryNode graph layer
- prisma/schema/yen-memory-graph.prisma: MemoryNode, MemorySource, MemoryEdge, MemorySummary
- MemoryNode: typed (13 types), durable, status-tracked, source-linked
- MemorySource: evidence backing every node β why Yen believes it
- MemoryEdge: supersedes/contradicts/supports/belongs_to_project graph
- MemorySummary: precomputed scope-level summaries (cheap retrieval)
- src/lib/yen/memory-graph.ts: full pipeline
- extractMemoriesFromTranscript() β Haiku extraction from transcripts
- classifyMemoryCandidate() β permanent/long_term/short_term/sensitive/discard
- upsertMemoryNode() β dedup, supersede old, attach source
- refreshMemorySummary() β Haiku summary regen per client/project
- buildMemoryContext() β narrow retrieval (1 summary + 10 nodes + 5 graph)
- processTranscriptIntoMemory() β full pipeline: extract β upsert β summarize
- tools.ts: storeMemoryNode, getMemoryContext, correctMemoryNode tools
- human correction always outranks model extraction (confidence=0.95)
- never_model access level never injected into prompts
- never_model nodes silently omitted from all retrieval
- sensitive type auto-set to never_model
- retrieval budgets: chat(10 nodes), email(8), proposal(20) β no firehose
- cost guard checked before every extraction call
Featureyen5:06 AM Β· ZRosserMcIntosh
email mailbox, client memory, follow-up rules, audit log
- Add /admin/yen/email compose UI with Anthropic Haiku/Sonnet routing
- Add /admin/yen/audit filterable log (tool calls, guardrails, emails)
- Add compose-email API with cost guard, abort/Stop, client memory enrichment
- Add send-email API via Brevo from yen@katura1999.com with audit logging
- Add audit API aggregating YenToolCall + YenGuardrailEvent + YenEmailSent
- Add client-memory CRUD API (/api/admin/yen/client-memory)
- Add follow-up-rules CRUD API (/api/admin/yen/follow-up-rules)
- Add prisma schemas: ClientMemoryCard, ClientMemoryEvent, YenFollowUpRule, YenPermission, YenEmailSent
- Add tool definitions + dispatch + handlers for getClientMemory, updateClientMemory, createFollowUpRule, listFollowUpRules
- Regenerate Prisma client
Docs3:47 AM Β· ZRosserMcIntosh
client preview & CAD renders β comprehensive feature documentation
Update3:37 AM Β· ZRosserMcIntosh
subtitle fragmentation, duplication, and translation consistency
- Three issues surfaced during the May 12 Pedro test meeting:
- 1. FRAGMENTATION β Deepgram fires is_final at every endpoint boundary,
- producing many short lines for what's actually one sentence. Fix:
- accumulate consecutive finals in finalMergeBufferRef for 600ms and
- push a single merged line to the display. Broadcast + DB persist
- still happen immediately on each fragment (remote viewers unaffected).
- 2. DUPLICATION β After a final the live caption stayed visible while the
- same text was added to the transcript history, showing the line twice.
- Fix: the merge-timer callback clears latestSourceRef/Translated and
- calls setLiveCaption(null) on the next frame (only if no new interim
- has started), handing the display off cleanly to the history lines.
- 3. TRANSLATION INCONSISTENCY β In-flight interim translate requests were
- completing AFTER the final's translate response and overwriting it
- with stale data. Also, translateInterimForViewer was calling
- pushSubtitle(undefined, res.text) on finals which raced with the
- live-caption clear. Fix: bump interimTranslateTokenRef at start of
- every final block to cancel in-flight interims; final translate only
- updates setTranscript (history column) and never touches live caption.
- Cleanup: finalMergeTimerRef is cancelled in both stopStt() and
- ws.onclose so no stale callbacks fire after the session ends.
Docs3:28 AM Β· ZRosserMcIntosh
Deepgram Nova-3 STT full implementation log β May 12 2026
Update2:46 AM Β· ZRosserMcIntosh
stale closure β translation never fired after startStt()
- ws.onmessage interim branch (translateInterimForViewer call)
- ws.onmessage final branch (translate fetch + sourceLanguage field)
- translateInterimForViewer useCallback (reads ref not stale state)
Update2:38 AM Β· ZRosserMcIntosh
Deepgram fragmentation + translation diagnostics
- translate route: warn in server logs when DEEPL_API_KEY is not set
- room client: show one-time toast 'check DEEPL_API_KEY' when translate returns the original text unchanged with cached=false (the soft-fail path in translateSegment when the key is missing)
- translate catch: log warning instead of swallowing silently
Update2:25 AM Β· ZRosserMcIntosh
add wss://api.deepgram.com to CSP connect-src
- The Deepgram WebSocket was being blocked by Content-Security-Policy.
- Add both wss:// and https:// for api.deepgram.com to allow the live
- STT connection from the browser.
Update2:14 AM Β· ZRosserMcIntosh
AudioWorklet not processing β silent sink + early port listener
- Root cause: Chrome optimizes away AudioWorklet nodes not connected to
- AudioDestinationNode. source β worklet with no worklet β destination
- means process() is never called β zero bytes sent to Deepgram.
- Fix 1 (both admin + guest rooms):
- Add worklet β silentSink(gain=0) β destination so the node stays in
- the active audio graph. Zero gain means no mic bleed to speakers.
- Fix 2 (both rooms):
- Move worklet.port.onmessage assignment to BEFORE the WebSocket is
- created, not inside ws.onopen. Audio buffers queued during the WS
- handshake (~200ms) were being silently dropped. Now they buffer on
- the port and flush when the WS opens.
- Fix 3 (guest room):
- Add audioCtx.resume() guard that was missing from the guest client
- (was only in admin client after last commit).
Update2:01 AM Β· ZRosserMcIntosh
meeting room STT β AudioContext suspension + WS error recovery
- toggleAiNotes: remove dead isSttSupported branch (always true; Deepgram works everywhere β just call startStt() directly in the else branch)
Update1:46 AM Β· ZRosserMcIntosh
deepgram-token routes β return master key directly
- The rotated Deepgram API key does not have admin/member scope required
- to create ephemeral sub-keys via POST /v1/projects/{id}/keys. Both
- admin and guest token routes were 500-ing on the getProjectId() call.
- Fix: return DEEPGRAM_API_KEY directly from both routes. Both endpoints
- are already protected by auth (admin session / valid invite token), so
- returning the master key is safe β only authenticated users ever see it.
- Removes the unnecessary round-trip to Deepgram key-creation API.
1:35 AM Β· ZRosserMcIntosh
fix + feat: share-link 500, schedule timezone + attendee search
- Add preferredName String? to prisma/schema/jewelry-projects.prisma
- Run prisma generate β fixes 500 on POST /api/admin/jewelry-projects/[id]/share-links
- Root cause: column existed in DB (migration was run) but Prisma 6 runtime rejects unknown fields in create.data even with 'as any' cast
- Show local timezone below date/time pickers (e.g. 'America/New_York (EST)')
- Derived from Intl.DateTimeFormat().resolvedOptions().timeZone on mount
- Replace plain text input with search-as-you-type dropdown
- Debounced 250ms fetch to /api/admin/customers/search (existing endpoint)
- Finds users by name OR any email (stella@katura1999.com + contatoluiseagency@gmail.com both surface)
- Click to add β email chip; manual type + Enter still works as fallback
- Suggestions auto-hide already-added emails
Feature1:16 AM Β· ZRosserMcIntosh
Deepgram Nova-3 STT replaces browser SpeechRecognition
- public/deepgram-processor.js β AudioWorklet: Float32βInt16 PCM for Deepgram WS
- api/admin/meetings/[id]/deepgram-token β creates 90-min scoped temp key
- api/guest/deepgram-token β same, auth via inviteToken (raw SQL, same pattern as translate)
- meeting-room-client: async startStt() opens Deepgram WS via AudioWorklet
- Prefers LiveKit mic track (no second getUserMedia, fixes iOS)
- Falls back to getUserMedia if LK track not ready
- onmessage: is_finalβfinalLogic, elseβinterimLogic (Hey Yen, broadcast, persist, translate all unchanged)
- stopStt: sends CloseStream, closes WS + AudioContext + stream
- isSttSupported always true (works in all browsers incl Firefox, Safari, iOS)
- guest-room-client: same async Deepgram pattern
- Removed isIOS guard (iOS now works via LK mic track reuse)
- Same interim/final broadcast logic to host
Updatemeetings12:47 AM Β· ZRosserMcIntosh
Hey Yen phonetic regex, STT lang BCP-47 fix (pt-BR not pt), spoken lang settings panel, Sparkles=always public Yen, remove FAB
Featureshare12:25 AM Β· ZRosserMcIntosh
customer autocomplete + preferredName headline, i18n (PT/ES/FR), DESIGNED FOR, mobile zoom 170%; feat(meetings): guest Yen passive display
Updatemeetings12:07 AM Β· ZRosserMcIntosh
panel layout respects subtitle bar, Yen FAB bottom-left, Hey Yen public mode, guest captions broadcast + subtitles default on, instant meeting end when host leaves alone