# AGENTS.md — SessionScribe

_Last updated: 2026-02-16_

This file is for coding agents working inside `SessionScribe/`.

## 1) Snapshot
- macOS SwiftUI app (deployment target 15.2)
- Records **system audio + mic** into chunked WAV files
- Produces live/eager transcript + finalized transcript
- Generates AI summaries, supports per-meeting chat
- Includes onboarding, licensing/trial, meeting detection, Sparkle updates

## 2) Core Runtime Flow
`RecordingView` → `RecordingViewModel` → `RecordingManager` → `RecordingService` → (`ProcessTapRecorder` + mic tap) → `CombinedTranscriptionService`

Persistence:
`RecordingViewModel` / `MeetingsViewModel` → `DatabaseNotifier` → `DatabaseManager` → `SQLiteManager`

## 3) Audio Pipeline
### System audio
- `ProcessTap` creates process tap + aggregate device
- `ProcessTapRecorder` accumulates mono Int16 PCM
- `flushAsWavData()` on chunk boundary writes `system_audio_<N>.wav`

### Mic audio
- `AVAudioEngine` input tap writes per-chunk `mic_audio_<N>.wav`
- Pause/resume currently mutes/unmutes mic and controls timer state

### Chunking
- User-selectable chunk durations (5/10/20/30/60s; minimum enforced at 5s)
- Eager snapshots every 3s (system-only) for near-real-time UI
- Recorder retains ~2s audio overlap between chunks for continuity

### Important invariants
- Do not trust only tap description channels; use runtime `mNumberChannels`
- Multichannel downmix prefers L/R channels for stereo-content clarity
- PCM is normalized before WAV creation to improve transcription reliability

## 4) Transcription
`CombinedTranscriptionService` supports:
1. OpenAI Whisper API (`whisper-1`)
2. WhisperKit local models
3. FluidAudio/Parakeet local model

Behavior:
- Eager chunks: system-only interim text (`isEager = true`)
- Final chunks replace eager entries for matching `chunkIndex + source`
- Local system/mic inference is serialized to avoid model corruption
- Overlap dedup at boundaries via word-level suffix/prefix matching

Notes:
- `StreamingTranscriptionService` exists, but manager currently uses batch mode (`useStreamingMode = false`)
- Audio deletion after transcription is intentionally disabled (debug preservation)

## 5) AI Summary + Chat
- Summary generation lives in `RecordingViewModel`
- Prompt source order:
  1) per-meeting override
  2) saved default prompt
  3) built-in default (`PromptTemplate`)
- Chat lives in `ChatViewModel`; conversation persists in `Note.aiConversation`
- Chat can include none/partial/full transcript context

## 6) Data & Paths
- Recording output: app container Documents
  - `~/Library/Containers/arnavgosain.SessionScribe/Data/Documents/Recording_<timestamp>/`
  - contains WAV chunks + `recording_metadata.json`
- WhisperKit models:
  - `.../Documents/huggingface/models/argmaxinc/whisperkit-coreml/<model>/`
- SQLite database:
  - preferred: `~/Documents/SessionScribe/notes.sqlite`
  - fallback: app container Documents `SessionScribe/notes.sqlite`
- SQLite schema version: 6 (includes FTS table for search)

## 7) High-Signal Files
- `SessionScribeApp.swift` — app shell, navigation, onboarding/license checks
- `RecordingService.swift` — chunk timers, eager snapshots, file writes
- `ProcessTap.swift` / `ProcessTapRecorder.swift` — system audio capture pipeline
- `TranscriptionService.swift` — `CombinedTranscriptionService`
- `StreamingTranscriptionService.swift` — streaming path (currently disabled)
- `RecordingManager.swift` — lifecycle + model loading/download
- `ViewModels/RecordingViewModel.swift` — transcript formatting, summary generation, save/resume
- `ViewModels/MeetingsViewModel.swift` — reactive notes/search
- `Database/SQLiteManager.swift` — migrations/CRUD/FTS
- `MeetingDetection/MeetingDetectionService.swift` — meeting detection notifications
- `SettingsView.swift` — transcription/provider/model/prompt/update settings

## 8) Build
```bash
xcodebuild -scheme SessionScribe -configuration Debug build
```
Team ID: `Q49ZKW8324`

### Internal Testing License Key
- Bypass/lifetime test key: `SESS-TEST-FREE-FOREVER`
- Accepted from onboarding and license management flows.
- Key matching is normalized (trim + uppercase).

## 9) Known Footguns
- Localized recording folder timestamps can contain `U+202F` before AM/PM.
- `determineAudioProcessToTap()` currently returns system-wide source (selected process metadata is saved but not used for tap source selection yet).
- Streaming transcription code is present but disabled by default manager flag.
- Historical DB repair helpers include legacy hardcoded paths.
- Terms text may not match runtime trial duration (runtime trial logic is 7 days).

## 10) Post-change Sanity Checks
1. Build passes.
2. Record and verify both system/mic WAV chunk files.
3. Eager transcript appears while recording.
4. Final transcript replaces eager text correctly.
5. Stop/save persists note and metadata.
6. Resume flow updates existing note instead of duplicating.
7. No main-thread publishing violations in stop/finalize path.
