BrainCue

Folder Structure

AI_Inter/
├─ docs/                        # this design set + the GitHub Pages site
│                               #   (index.html landing, _config.yml, media/, images/)
├─ electron.vite.config.ts      # main + preload + renderer build config
├─ electron-builder.yml         # packaging (win/mac/linux, icons)
├─ drizzle.config.ts            # drizzle-kit (schema -> migrations)
├─ drizzle/                     # generated SQL migrations + meta (bundled into the app)
├─ package.json
├─ tsconfig.json / tsconfig.node.json / tsconfig.web.json
├─ tailwind.config.js / postcss.config.js
├─ vitest.config.ts
├─ .gitignore
├─ index.html                   # single renderer entry (dashboard/overlay/selection roots chosen at runtime)
│
├─ CONTRIBUTING.md              # setup, gate, IPC contract, invariants
├─ SECURITY.md / CODE_OF_CONDUCT.md
├─ .github/workflows/           # ci.yml · release.yml · pages.yml · auto-merge.yml
├─ .github/                     # CODEOWNERS · PR template · ISSUE_TEMPLATE/
│
├─ scripts/
│  ├─ run-electron-vite.mjs     # dev/preview launcher
│  ├─ clean-release.mjs         # kill running app + wipe release/ (pre-package)
│  ├─ generate-icon.mjs         # icon.svg -> icon.png + icon.ico
│  ├─ build-media.mjs           # capture frames -> docs/media gif+mp4 (ffmpeg)
│  └─ privacy-affinity/         # the privacy hard test (hardtest.js)
│
├─ e2e/                         # Playwright vs the BUILT app over CDP (see e2e/README.md)
│  ├─ fixtures.ts               # spawn + connect harness, disablePrivacyMode
│  ├─ *.spec.ts                 # smoke / data-integrity / live tiers
│  └─ *.capture.spec.ts         # opt-in (E2E_CAPTURE=1) marketing stills + clips
│
├─ resources/                   # build resources (not packed into app)
│  ├─ icon.svg                  # icon source
│  ├─ icon.png                  # 1024² master (mac/linux)
│  └─ icon.ico                  # multi-resolution Windows icon
│
├─ src/
│  ├─ shared/                   # imported by BOTH main and renderer (types/constants only)
│  │  ├─ ipc.ts                 # IPC + EVENTS channel name constants
│  │  ├─ types.ts               # domain types (Profile, Job, Session, ...)
│  │  └─ result.ts              # Result<T> envelope
│  │
│  ├─ main/                     # MAIN PROCESS (Node, trusted)
│  │  ├─ index.ts               # entry: lifecycle, init order
│  │  ├─ env.ts                 # isDev, paths, env var access
│  │  ├─ shortcuts.ts           # global shortcut registration
│  │  ├─ windows/
│  │  │  ├─ mainWindow.ts  overlayWindow.ts  selectionWindow.ts
│  │  │  └─ loadRenderer.ts     # dev-URL vs file load + diagnostics
│  │  ├─ ipc/
│  │  │  ├─ index.ts            # registerIpc(): wires all handlers
│  │  │  ├─ helpers.ts          # handle() wrapper + zod validation
│  │  │  ├─ broadcast.ts        # push events to dashboard/overlay
│  │  │  ├─ settings.ipc.ts  profiles.ipc.ts  documents.ipc.ts
│  │  │  ├─ jobs.ipc.ts  notes.ipc.ts  session.ipc.ts  mock.ipc.ts
│  │  │  ├─ capture.ipc.ts  overlay.ipc.ts  dialog.ipc.ts
│  │  ├─ db/
│  │  │  ├─ index.ts            # better-sqlite3 + drizzle init + migrate
│  │  │  ├─ schema.ts           # drizzle table definitions
│  │  │  └─ repositories/       # typed data access per entity
│  │  │     ├─ profiles.repo.ts  jobs.repo.ts
│  │  │     ├─ sessions.repo.ts  settings.repo.ts
│  │  ├─ providers/             # capability seam (v2): types.ts registry.ts errors.ts + openai/ impls
│  │  ├─ services/
│  │  │  ├─ engine/             # v2 conversation engine (see 12-ENGINE-PLAN.md)
│  │  │  │  ├─ engine.ts  engineSession.ts  modeDefinition.ts  grounding.ts
│  │  │  │  ├─ meetingReport.ts  contextEvent.ts  sourceAdapter.ts
│  │  │  │  ├─ persona.ts       # the ONE companion-personality prompt source
│  │  │  │  ├─ modes/           # interview.mode.ts  meeting.mode.ts  companion.mode.ts
│  │  │  │  ├─ trigger/         # reactiveQuestion  summoned  meetingHeuristics  salience  ambientPolicy  presence
│  │  │  │  │                   # + companion: interjectionPolicy  companionSalience  companionPresence
│  │  │  │  ├─ companion/       # costMeter.ts (visible estimate + budget gates)
│  │  │  │  └─ persistence/enginePersistence.ts
│  │  │  ├─ memory/             # local memory: extractor  memoryService  recall  sensitiveFilter
│  │  │  ├─ voice/              # voice/summon layer
│  │  │  │  ├─ dialogueController.ts  # explicit FSM: idle/listening/thinking/speaking/interrupted/paused/error
│  │  │  │  ├─ voiceService.ts        # orchestrator: PTT buffer, STT, routing, sentence-chunked TTS
│  │  │  │  ├─ quickAnswer.ts         # no-session quick ask (spoken-style persona)
│  │  │  │  └─ sentenceStream.ts  wav.ts
│  │  │  ├─ openai/             # see 06-OPENAI-SERVICE.md
│  │  │  │  ├─ client.ts  models.ts  parsing.ts  embeddings.ts
│  │  │  │  ├─ questions.ts  answer.ts  transcription.ts
│  │  │  │  ├─ coding.ts  codingPrompt.ts  vision.ts
│  │  │  │  ├─ interviewer.ts   # mock-interview question/feedback gen
│  │  │  │  ├─ tts.ts           # text-to-speech (mock voice)
│  │  │  │  └─ realtime.ts  realtimeEvents.ts   # Realtime STT
│  │  │  ├─ rag/
│  │  │  │  ├─ vectorStore.ts   # interface + SQLite blob store
│  │  │  │  ├─ vectorMath.ts    # cosine / decode helpers
│  │  │  │  ├─ chunker.ts       # text -> chunks
│  │  │  │  ├─ indexProfile.ts  # reindexProfile() + indexJob()
│  │  │  │  └─ retriever.ts     # embed query -> top-k
│  │  │  ├─ documents/
│  │  │  │  ├─ extract.ts       # pdf/docx/txt/md -> text
│  │  │  │  ├─ fetchUrl.ts      # download a posting URL -> readable text
│  │  │  │  └─ companyResearch.ts # scrape company site (home + about/careers…) -> text
│  │  │  ├─ capture/
│  │  │  │  ├─ screenshot.ts    # desktopCapturer + region crop
│  │  │  │  └─ codingMode.ts    # coding-question solve flow
│  │  │  ├─ mock/
│  │  │  │  └─ mockManager.ts   # mock-interview session orchestration
│  │  │  ├─ session/
│  │  │  │  ├─ sessionManager.ts# live session orchestration
│  │  │  │  ├─ report.ts        # post-session report generation
│  │  │  │  └─ privacy.ts       # screen-capture privacy affinity
│  │  │  ├─ stt/                # speech-to-text engine choice + local engine (see 22-LOCAL-STT.md)
│  │  │  │  ├─ index.ts         # seam: readSttPrefs / sttReady / applySttSelection
│  │  │  │  ├─ prefs.ts         # persisted SttPrefs
│  │  │  │  ├─ modelStore.ts    # <userData>/models/stt/<id>: installed(), bytesOnDisk(), active downloads
│  │  │  │  ├─ downloader.ts    # resumable, size-verified download (Range + .part)
│  │  │  │  ├─ worker.ts        # sherpa-onnx recognizer — a utilityProcess (out/main/stt-worker.js)
│  │  │  │  ├─ localRealtimeStt.ts  # the `local` RealtimeSttProvider driving the worker
│  │  │  │  └─ protocol.ts  pcm.ts   # worker messages; PCM16→Float32 + 24k→16k helpers
│  │  │  └─ security/
│  │  │     ├─ apiKey.ts        # safeStorage-backed ApiKeyStore
│  │  │     └─ logger.ts        # redacting logger
│  │  │
│  ├─ preload/
│  │  ├─ index.ts               # contextBridge -> window.api (typed facade)
│  │  └─ index.d.ts             # ambient types for window.api
│  │
│  └─ renderer/                 # RENDERER (React)
│     ├─ main.tsx               # entry: mounts dashboard / overlay / selection
│     ├─ index.css              # tailwind entry
│     ├─ components/            # Markdown.tsx  Waveform.tsx  ui.tsx (shared kit)
│     ├─ lib/
│     │  ├─ api.ts              # thin wrapper over window.api
│     │  ├─ useMicCapture.ts  useAnswerRecorder.ts  pcm.ts
│     │  └─ usePagedSearch.ts
│     ├─ store/                 # zustand: useProfileStore.ts  useSettingsStore.ts  useTourStore.ts
│     ├─ dashboard/
│     │  ├─ App.tsx             # router + shell (5-section sidebar, hosts the guided tour)
│     │  ├─ Tour.tsx            # first-run guided tour (spotlight + steps)
│     │  ├─ StartSessionModal.tsx  startFlow.ts   # the shared universal start flow
│     │  ├─ library/            # Library tabs: ProfilesTab  SpacesTab  DocumentsTab
│     │  └─ pages/  (Home, Library, ProfileEditor, Interview, Mock, Sparring, Tailor, Sessions, Reports=Insights, Settings)
│     ├─ overlay/               # always-on-top Cue Card (contribution feed)
│     │  ├─ Overlay.tsx          # shell: window state, IPC subscriptions, composition
│     │  ├─ store/useOverlayStore.ts   # zustand card feed (reducers in cards/model.ts)
│     │  ├─ cards/               # ContributionCard frame + registry.ts + per-kind views + UnknownCardView
│     │  ├─ controls/            # HeaderBar  SessionBar  AnswerControls  AskBar  VoiceBar  Btn  EqualizerBars
│     │  ├─ panels/              # ClientNotes  Captures  ErrorBanner  AudioMeter  Transcript  DataSent  SettingsModal
│     │  ├─ voice/               # useVoice.ts (state mirror + VAD)  voiceCapture.ts  voicePlayer.ts (setSinkId queue)
│     │  └─ lib/                 # streamBuffer.ts (rAF token coalescer)  style.ts
│     └─ selection/RegionSelector.tsx  # region-capture window
│
└─ (userData at runtime: app.db, documents/, vectors/ — see 04-DATABASE.md)

Module boundaries

Path aliases (configured in electron.vite.config.ts + tsconfigs): @shared, @main, @renderer.