Files
noteflow/AGENTS.md
2026-01-23 07:45:20 +00:00

801 lines
30 KiB
Markdown

# AGENTS.md
This file provides guidance to AI coding assistants (Cursor, Copilot, Codex, etc.) when working with code in this repository.
## Project Overview
NoteFlow is an intelligent meeting notetaker: local-first audio capture + navigable recall + evidence-linked summaries. It is a client-server system built around a gRPC API for bidirectional audio streaming and transcription. The repository includes:
- **Python backend** (`src/noteflow/`) — gRPC server, domain logic, infrastructure adapters
- **Tauri + React desktop client** (`client/`) — Rust for IPC, React UI (Vite)
The gRPC schema is the shared contract between backend and client; keep proto changes in sync across Python, Rust, and TypeScript.
---
## Quick Orientation
| Entry Point | Description |
|-------------|-------------|
| `python -m noteflow.grpc.server` | Backend server (`src/noteflow/grpc/server/__main__.py`) |
| `cd client && npm run dev` | Web UI (Vite) |
| `cd client && npm run tauri dev` | Desktop Tauri dev (requires Rust toolchain) |
| `src/noteflow/grpc/proto/noteflow.proto` | Protobuf schema |
| `client/src/api/tauri-adapter.ts` | TypeScript → Rust IPC bridge |
| `client/src-tauri/src/commands/` | Rust Tauri command handlers |
---
## Build and Development Commands
```bash
# Install (editable with dev dependencies)
python -m pip install -e ".[dev]"
# Run gRPC server
python -m noteflow.grpc.server --help
# Run Tauri + React client UI
cd client && npm install && npm run dev
cd client && npm run tauri dev # Desktop (requires Rust)
# Tests
pytest # Full suite
pytest -m "not integration" # Skip external-service tests
pytest tests/domain/ # Run specific test directory
pytest -k "test_segment" # Run by pattern
# Docker (hot-reload enabled)
docker compose up -d postgres # PostgreSQL with pgvector
python scripts/dev_watch_server.py # Auto-reload server
```
### Forbidden Docker Operations (without explicit permission)
- `docker compose build` / `up` / `down` / `restart`
- `docker stop` / `docker kill`
- Any command that would interrupt the hot-reload server
---
## Quality Commands (Makefile)
**Always use Makefile targets instead of running tools directly.**
### Primary Quality Commands
```bash
make quality # Run ALL quality checks (TS + Rust + Python)
make quality-py # Python: lint + type-check + test-quality
make quality-ts # TypeScript: type-check + lint + test-quality
make quality-rs # Rust: clippy + lint
```
### Python Quality
```bash
make lint-py # Basedpyright lint → .hygeine/basedpyright.lint.json
make type-check-py # Basedpyright strict mode
make test-quality-py # pytest tests/quality/
make lint-fix-py # Auto-fix Ruff + Sourcery issues
```
### TypeScript Quality
```bash
make type-check # tsc --noEmit
make lint # Biome linter → .hygeine/biome.json
make lint-fix # Auto-fix Biome issues
make test-quality # Vitest quality tests
```
### Rust Quality
```bash
make clippy # Clippy linter → .hygeine/clippy.json
make lint-rs # Code quality script → .hygeine/rust_code_quality.txt
make fmt-rs # Format with rustfmt
make fmt-check-rs # Check rustfmt formatting
```
### Formatting
```bash
make fmt # Format all code (Biome + rustfmt)
make fmt-check # Check all formatting
```
### E2E Tests
```bash
make e2e # Playwright tests (requires frontend on :5173)
make e2e-ui # Playwright tests with UI mode
make e2e-grpc # Rust gRPC integration tests
```
---
## Architecture
```
src/noteflow/
├── domain/ # Entities, ports, value objects
│ ├── entities/ # Meeting, Segment, Summary, Annotation, NamedEntity, Integration, Project, Processing, SummarizationTemplate
│ ├── identity/ # User, Workspace, WorkspaceMembership, roles, context
│ ├── auth/ # OIDC discovery, claims, constants
│ ├── ports/ # Repository protocols
│ │ ├── repositories/
│ │ │ ├── transcript.py # MeetingRepository, SegmentRepository, SummaryRepository
│ │ │ ├── asset.py # AssetRepository
│ │ │ ├── background.py # DiarizationJobRepository
│ │ │ ├── external/ # WebhookRepository, IntegrationRepository, EntityRepository, UsageRepository
│ │ │ └── identity/ # UserRepository, WorkspaceRepository, ProjectRepository, MembershipRepository, SummarizationTemplateRepository
│ │ ├── unit_of_work.py # UnitOfWork protocol (supports_* capability checks)
│ │ ├── async_context.py # Async context utilities
│ │ ├── diarization.py # DiarizationEngine protocol
│ │ ├── ner.py # NEREngine protocol
│ │ └── calendar.py # CalendarProvider protocol
│ ├── webhooks/ # WebhookEventType, WebhookConfig, WebhookDelivery, payloads
│ ├── triggers/ # Trigger, TriggerAction, TriggerSignal, TriggerProvider
│ ├── summarization/# SummarizationProvider protocol
│ ├── rules/ # Business rules registry, models, builtin rules
│ ├── settings/ # Domain settings base
│ ├── constants/ # Field definitions, placeholders
│ ├── utils/ # time.py (utc_now), validation.py
│ ├── errors.py # Domain-specific exceptions
│ └── value_objects.py
├── application/ # Use-cases/services
│ ├── services/
│ │ ├── meeting/ # MeetingService (CRUD, segments, annotations, summaries, state)
│ │ ├── identity/ # IdentityService (context, workspace, defaults)
│ │ ├── calendar/ # CalendarService (connection, events, oauth, sync)
│ │ ├── summarization/ # SummarizationService, TemplateService, ConsentManager
│ │ ├── project_service/ # CRUD, members, roles, rules, active project
│ │ ├── recovery/ # RecoveryService (meeting, job, audio recovery)
│ │ ├── webhook_service.py
│ │ ├── ner_service.py
│ │ ├── export_service.py
│ │ ├── trigger_service.py
│ │ ├── retention_service.py
│ │ ├── auth_service.py
│ │ ├── auth_workflows.py
│ │ ├── auth_integration_manager.py
│ │ ├── auth_token_exchanger.py
│ │ ├── auth_types.py
│ │ ├── auth_constants.py
│ │ └── protocols.py
│ └── observability/ # Observability ports
├── infrastructure/ # Implementations
│ ├── audio/ # sounddevice capture, ring buffer, VU levels, playback, writer, reader
│ ├── asr/ # faster-whisper engine, VAD segmenter, streaming, DTOs
│ ├── auth/ # OIDC discovery, registry, presets
│ ├── diarization/ # Session, assigner, engine (streaming: diart, offline: pyannote)
│ ├── summarization/# CloudProvider, OllamaProvider, MockProvider, parsing, citation verifier, template renderer
│ ├── triggers/ # Calendar, audio_activity, foreground_app providers
│ ├── persistence/ # SQLAlchemy + asyncpg + pgvector
│ │ ├── database.py # create_async_engine, create_async_session_factory
│ │ ├── models/ # ORM models (core/, identity/, integrations/, entities/, observability/, organization/)
│ │ ├── repositories/ # Repository implementations
│ │ │ ├── meeting_repo.py
│ │ │ ├── segment_repo.py
│ │ │ ├── summary_repo.py
│ │ │ ├── annotation_repo.py
│ │ │ ├── entity_repo.py
│ │ │ ├── webhook_repo.py
│ │ │ ├── preferences_repo.py
│ │ │ ├── asset_repo.py
│ │ │ ├── summarization_template_repo.py
│ │ │ ├── diarization_job/
│ │ │ ├── integration/
│ │ │ ├── identity/
│ │ │ ├── usage_event/
│ │ │ └── _base/ # BaseRepository with _execute_scalar, _execute_scalars, _add_and_flush
│ │ ├── unit_of_work/
│ │ ├── memory/ # In-memory implementations
│ │ └── migrations/ # Alembic migrations
│ ├── security/ # Keystore (keyring + AES-GCM), protocols, crypto/
│ ├── crypto/ # Cryptographic utilities
│ ├── export/ # Markdown, HTML, PDF (WeasyPrint), formatting helpers
│ ├── webhooks/ # WebhookExecutor (delivery, signing, metrics)
│ ├── converters/ # ORM ↔ domain (orm, webhook, ner, calendar, integration, asr)
│ ├── calendar/ # Google/Outlook adapters, OAuth flow
│ ├── ner/ # spaCy engine
│ ├── observability/# OpenTelemetry tracing, usage tracking
│ ├── metrics/ # Metric collection
│ ├── logging/ # Log buffer utilities
│ └── platform/ # Platform-specific code
├── grpc/ # gRPC server and client
│ ├── server/ # Server entry point (__main__.py, __init__.py)
│ ├── service.py # NoteFlowServicer (composes mixins)
│ ├── client.py # Python gRPC client wrapper
│ ├── _mixins/ # Modular RPC implementations
│ │ ├── streaming/ # ASR streaming (package)
│ │ │ ├── _mixin.py # Main StreamingMixin class
│ │ │ ├── _session.py # Session management
│ │ │ ├── _asr.py # ASR processing
│ │ │ ├── _processing/ # Audio processing pipeline
│ │ │ │ ├── _audio_ops.py
│ │ │ │ ├── _chunk_tracking.py
│ │ │ │ ├── _congestion.py
│ │ │ │ ├── _constants.py
│ │ │ │ ├── _types.py
│ │ │ │ └── _vad_processing.py
│ │ │ ├── _partials.py # Partial transcript handling
│ │ │ ├── _cleanup.py # Resource cleanup
│ │ │ └── _types.py # Type definitions
│ │ ├── diarization/ # Speaker diarization (package)
│ │ │ ├── _mixin.py # Main DiarizationMixin class
│ │ │ ├── _jobs.py # Background job management
│ │ │ ├── _refinement.py# Offline refinement
│ │ │ ├── _streaming.py # Real-time diarization
│ │ │ ├── _speaker.py # Speaker assignment
│ │ │ ├── _status.py # Job status tracking
│ │ │ └── _types.py # Type definitions
│ │ ├── meeting/ # Meeting lifecycle (package)
│ │ │ ├── meeting_mixin.py
│ │ │ ├── _project_scope.py
│ │ │ └── _stop_ops.py
│ │ ├── summarization.py # Summary generation
│ │ ├── annotation.py # Segment annotations CRUD
│ │ ├── export.py # Document export
│ │ ├── entities.py # Named entity extraction
│ │ ├── calendar.py # Calendar sync
│ │ ├── webhooks.py # Webhook management
│ │ ├── preferences.py # User preferences
│ │ ├── observability.py # Usage tracking, metrics
│ │ ├── sync.py # State synchronization
│ │ ├── identity.py # Identity operations
│ │ ├── projects.py # Project operations
│ │ ├── oidc.py # OIDC operations
│ │ ├── converters.py # Protobuf ↔ domain converters
│ │ ├── errors.py # gRPC error helpers
│ │ ├── protocols.py # ServicerHost protocol
│ │ └── _audio_helpers.py # Audio utilities
│ ├── _client_mixins/ # Python client mixins
│ │ ├── streaming.py
│ │ ├── meeting.py
│ │ ├── diarization.py
│ │ ├── export.py
│ │ ├── annotation.py
│ │ ├── converters.py
│ │ └── protocols.py
│ ├── interceptors/ # gRPC server interceptors
│ │ └── identity.py # Identity context propagation
│ └── proto/ # Protobuf definitions and generated stubs
├── cli/ # CLI tools
│ ├── __main__.py # CLI entry point
│ ├── retention.py # Retention management
│ ├── constants.py # CLI constants
│ └── models/ # Model commands (package)
│ ├── _download.py
│ ├── _parser.py
│ ├── _registry.py
│ ├── _status.py
│ └── _types.py
└── config/ # Configuration
├── settings/ # Pydantic settings (_base, _features, _server, _security, etc.)
├── constants.py # Application constants
└── feature_flags.py
```
### Client Architecture (`client/src/`)
```
client/src/
├── api/ # API layer with adapters
│ ├── tauri-adapter.ts # Main Tauri IPC adapter
│ ├── mock-adapter.ts # Mock adapter for testing
│ ├── cached-adapter.ts # Caching layer
│ ├── connection-state.ts # Connection state machine
│ ├── reconnection.ts # Auto-reconnection logic
│ ├── interface.ts # Adapter interface definition
│ └── types/ # API type definitions
│ ├── core.ts
│ ├── meetings.ts
│ ├── segments.ts
│ ├── diarization.ts
│ ├── annotations.ts
│ ├── templates.ts
│ ├── webhooks.ts
│ ├── calendar.ts
│ ├── entities.ts
│ ├── preferences.ts
│ ├── observability.ts
│ ├── triggers.ts
│ ├── audio.ts
│ ├── playback.ts
│ ├── apps.ts
│ └── readonly.ts
├── hooks/ # Custom React hooks
│ ├── use-diarization.ts
│ ├── use-cloud-consent.ts
│ ├── use-webhooks.ts
│ ├── use-oauth-flow.ts
│ ├── use-calendar-sync.ts
│ ├── use-entity-extraction.ts
│ ├── use-audio-devices.ts
│ ├── use-project.ts
│ ├── use-project-members.ts
│ ├── use-oidc-providers.ts
│ ├── use-auth-flow.ts
│ ├── use-integration-sync.ts
│ ├── use-integration-validation.ts
│ ├── use-secure-integration-secrets.ts
│ ├── use-guarded-mutation.ts
│ ├── use-panel-preferences.ts
│ ├── use-preferences-sync.ts
│ ├── use-meeting-reminders.ts
│ ├── use-recording-app-policy.ts
│ ├── use-post-processing.ts
│ ├── use-toast.ts
│ ├── use-mobile.tsx
│ └── post-processing/
├── contexts/ # React contexts
│ ├── connection-context.tsx # gRPC connection context
│ ├── connection-state.ts
│ ├── workspace-context.tsx # Workspace context
│ ├── workspace-state.ts
│ ├── project-context.tsx # Project context
│ └── project-state.ts
├── components/ # React components
│ ├── ui/ # Reusable UI components (shadcn/ui)
│ ├── recording/ # Recording-specific components
│ ├── settings/ # Settings panel components
│ ├── analytics/ # Analytics visualizations
│ ├── projects/ # Project components
│ ├── icons/ # Icon components
│ └── ... # Top-level components
├── pages/ # Route pages
│ ├── Home.tsx
│ ├── Meetings.tsx
│ ├── MeetingDetail.tsx
│ ├── Recording.tsx
│ ├── Projects.tsx
│ ├── ProjectSettings.tsx
│ ├── Settings.tsx
│ ├── settings/ # Settings sub-pages
│ ├── People.tsx
│ ├── Tasks.tsx
│ ├── Analytics.tsx
│ ├── Index.tsx
│ └── NotFound.tsx
├── lib/ # Utilities
│ ├── config/ # Configuration (server, defaults, app-config, provider-endpoints)
│ ├── cache/ # Client-side caching (meeting-cache)
│ ├── format.ts
│ ├── utils.ts
│ ├── time.ts
│ ├── crypto.ts
│ ├── cva.ts
│ ├── styles.ts
│ ├── tauri-events.ts
│ ├── preferences.ts
│ ├── preferences-sync.ts
│ ├── entity-store.ts
│ ├── speaker-utils.ts
│ ├── ai-providers.ts
│ ├── ai-models.ts
│ ├── integration-utils.ts
│ ├── default-integrations.ts
│ ├── status-constants.ts
│ ├── timing-constants.ts
│ ├── object-utils.ts
│ ├── error-reporting.ts
│ ├── client-logs.ts
│ ├── client-log-events.ts
│ ├── log-groups.ts
│ ├── log-converters.ts
│ ├── log-messages.ts
│ ├── log-summarizer.ts
│ └── log-group-summarizer.ts
├── types/ # Shared TypeScript types
└── test/ # Test utilities
```
### Rust/Tauri Backend (`client/src-tauri/src/`)
```
src-tauri/src/
├── commands/ # Tauri IPC command handlers
│ ├── recording/ # capture.rs, device.rs, audio.rs, app_policy.rs
│ ├── playback/ # audio.rs, events.rs, tick.rs
│ ├── triggers/ # audio.rs, polling.rs
│ ├── meeting.rs
│ ├── diarization.rs
│ ├── annotation.rs
│ ├── export.rs
│ ├── summary.rs
│ ├── entities.rs
│ ├── calendar.rs
│ ├── webhooks.rs
│ ├── preferences.rs
│ ├── observability.rs
│ ├── sync.rs
│ ├── projects.rs
│ ├── identity.rs
│ ├── oidc.rs
│ ├── connection.rs
│ ├── audio.rs
│ ├── audio_testing.rs
│ ├── apps.rs
│ ├── apps_platform.rs
│ ├── diagnostics.rs
│ ├── shell.rs
│ └── testing.rs
├── grpc/ # gRPC client
│ ├── client/ # Client implementations by domain
│ │ ├── core.rs
│ │ ├── meetings.rs
│ │ ├── annotations.rs
│ │ ├── diarization.rs
│ │ ├── identity.rs
│ │ ├── projects.rs
│ │ ├── preferences.rs
│ │ ├── calendar.rs
│ │ ├── webhooks.rs
│ │ ├── observability.rs
│ │ ├── oidc.rs
│ │ ├── sync.rs
│ │ └── converters.rs
│ ├── types/ # Rust type definitions
│ │ ├── core.rs
│ │ ├── enums.rs
│ │ ├── identity.rs
│ │ ├── projects.rs
│ │ ├── preferences.rs
│ │ ├── calendar.rs
│ │ ├── webhooks.rs
│ │ ├── observability.rs
│ │ ├── oidc.rs
│ │ ├── sync.rs
│ │ └── results.rs
│ ├── streaming/ # Streaming converters
│ └── noteflow.rs # Generated protobuf types
├── state/ # Runtime state management
│ ├── app_state.rs
│ ├── preferences.rs
│ ├── playback.rs
│ └── types.rs
├── audio/ # Audio capture and playback
├── cache/ # Memory caching
├── crypto/ # Cryptographic operations
├── events/ # Tauri event emission
├── triggers/ # Trigger detection
├── error/ # Error types
├── identity/ # Identity management
├── config.rs # Configuration
├── constants.rs # Constants
├── helpers.rs # Helper functions
├── oauth_loopback.rs # OAuth callback server
├── main.rs # Application entry point
└── lib.rs # Library exports
```
---
## Database
PostgreSQL with pgvector extension. Async SQLAlchemy with asyncpg driver.
```bash
# Alembic migrations
alembic upgrade head
alembic revision --autogenerate -m "description"
```
Connection via `NOTEFLOW_DATABASE_URL` env var or settings.
### ORM Models (`persistence/models/`)
| Directory | Models |
|-----------|--------|
| `core/` | MeetingModel, SegmentModel, SummaryModel, AnnotationModel, DiarizationJobModel |
| `identity/` | UserModel, WorkspaceModel, WorkspaceMembershipModel, ProjectModel, ProjectMembershipModel, SettingsModel |
| `integrations/` | IntegrationModel, IntegrationSecretModel, CalendarEventModel, MeetingCalendarLinkModel, WebhookConfigModel, WebhookDeliveryModel |
| `entities/` | NamedEntityModel, SpeakerModel |
| `observability/` | UsageEventModel |
| `organization/` | SummarizationTemplateModel, TaskModel, TagModel |
---
## Testing Conventions
- Test files: `test_*.py`, functions: `test_*`
- Markers: `@pytest.mark.slow` (model loading), `@pytest.mark.integration` (external services)
- Integration tests use testcontainers for PostgreSQL
- Asyncio auto-mode enabled
- React unit tests use Vitest; e2e tests use Playwright in `client/e2e/`
### Test Quality Gates (`tests/quality/`)
**After any non-trivial changes**, run:
```bash
pytest tests/quality/
```
This suite enforces:
| Check | Description |
|-------|-------------|
| `test_test_smells.py` | No assertion roulette, no conditional test logic, no loops in tests |
| `test_magic_values.py` | No magic numbers in assignments |
| `test_code_smells.py` | Code quality checks |
| `test_duplicate_code.py` | No duplicate code patterns |
| `test_stale_code.py` | No stale/dead code |
| `test_decentralized_helpers.py` | Helpers consolidated properly |
| `test_unnecessary_wrappers.py` | No unnecessary wrapper functions |
| `test_baseline_self.py` | Baseline validation self-checks |
### Global Fixtures (`tests/conftest.py`)
**Do not redefine these fixtures:**
| Fixture | Description |
|---------|-------------|
| `reset_context_vars` | Reset logging context variables |
| `mock_uow` | Mock Unit of Work |
| `crypto` | Crypto utilities |
| `meetings_dir` | Temporary meetings directory |
| `webhook_config` | Single-event webhook config |
| `webhook_config_all_events` | All-events webhook config |
| `sample_datetime` | Sample datetime |
| `calendar_settings` | Calendar settings |
| `meeting_id` | Sample meeting ID |
| `sample_meeting` | Sample Meeting entity |
| `recording_meeting` | Recording-state Meeting |
| `sample_rate` | Audio sample rate |
| `mock_grpc_context` | Mock gRPC context |
| `mockasr_engine` | Mock ASR engine |
| `mock_optional_extras` | Mock optional extras |
| `mock_oauth_manager` | Mock OAuth manager |
| `memory_servicer` | In-memory servicer |
| `approx_float` | Approximate float comparison |
| `approx_sequence` | Approximate sequence comparison |
---
## Code Style
### Python
- Python 3.12+, 100-char line length
- 4-space indentation
- Naming: `snake_case` modules/functions, `PascalCase` classes, `UPPER_SNAKE_CASE` constants
- Strict basedpyright (0 errors, 0 warnings, 0 notes required)
- Ruff for linting (E, W, F, I, B, C4, UP, SIM, RUF)
- Module soft limit 500 LoC, hard limit 750 LoC
- Generated `*_pb2.py`, `*_pb2_grpc.py` excluded from lint
### TypeScript
- Biome for linting and formatting
- Single quotes, 100 char width
- Strict TypeScript (noEmit checks)
### Rust
- `rustfmt` for formatting
- `clippy` for linting (warnings treated as errors)
---
## Type Safety (Zero Tolerance)
### Forbidden Patterns (Python)
| Pattern | Why Blocked | Alternative |
|---------|-------------|-------------|
| `# type: ignore` | Bypasses type safety | Fix the actual type error |
| `# pyright: ignore` | Bypasses type safety | Fix the actual type error |
| `Any` type annotations | Creates type safety holes | Use `Protocol`, `TypeVar`, `TypedDict`, or specific types |
| Magic numbers | Hidden intent | Define `typing.Final` constants |
| Loops in tests | Non-deterministic | Use `@pytest.mark.parametrize` |
| Conditionals in tests | Non-deterministic | Use `@pytest.mark.parametrize` |
| Multiple assertions without messages | Hard to debug | Add assertion messages |
### Type Resolution Hierarchy
When facing dynamic types:
1. **`Protocol`** — For duck typing (structural subtyping)
2. **`TypeVar`** — For generics
3. **`TypedDict`** — For structured dictionaries
4. **`cast()`** — Last resort (with comment explaining why)
### Validation Requirements
After any code changes:
```bash
source .venv/bin/activate && basedpyright src/noteflow/
```
**Expected output:** `0 errors, 0 warnings, 0 notes`
---
## Protected Files (Require Explicit Permission)
| File/Directory | What's Blocked |
|----------------|----------------|
| `Makefile` | All modifications |
| `tests/quality/` (except `baselines.json`) | All modifications |
| `pyproject.toml`, `ruff.toml`, `pyrightconfig.json` | All edits |
| `biome.json`, `tsconfig.json`, `.eslintrc*` | All edits |
| `.rustfmt.toml`, `.clippy.toml` | All edits |
### Quality Gate Requirement
Before completing any code changes:
```bash
make quality
```
All quality checks must pass.
### Policy: No Ignoring Pre-existing Issues
If you encounter lint errors, type errors, or test failures—**even if they existed before your changes**—you must either:
1. Fix immediately (for simple issues)
2. Add to todo list (for complex issues)
3. Launch a subagent to fix (for parallelizable work)
---
## Proto/gRPC
Proto definitions: `src/noteflow/grpc/proto/noteflow.proto`
Regenerate after proto changes:
```bash
python -m grpc_tools.protoc -I src/noteflow/grpc/proto \
--python_out=src/noteflow/grpc/proto \
--grpc_python_out=src/noteflow/grpc/proto \
src/noteflow/grpc/proto/noteflow.proto
```
Then run stub patching:
```bash
python scripts/patch_grpc_stubs.py
```
### Sync Points (High Risk of Breakage)
When changing proto:
1. **Python stubs** — Regenerate `*_pb2.py`, `*_pb2_grpc.py`
2. **Server mixins** — Update `src/noteflow/grpc/_mixins/`
3. **Python client** — Update `src/noteflow/grpc/client.py`
4. **Rust types** — Generated by `client/src-tauri/build.rs`
5. **Rust commands** — Update `client/src-tauri/src/commands/`
6. **TypeScript types** — Update `client/src/api/types/`
7. **TypeScript adapter** — Update `client/src/api/tauri-adapter.ts`
---
## Key Subsystems
### Speaker Diarization
- **Streaming**: diart for real-time speaker detection
- **Offline**: pyannote.audio for post-meeting refinement
- **gRPC**: `RefineSpeakerDiarization`, `GetDiarizationJobStatus`, `RenameSpeaker`
### Summarization
- **Providers**: CloudProvider (Anthropic/OpenAI), OllamaProvider (local), MockProvider (testing)
- **Templates**: Configurable tone, format, verbosity
- **Citation verification**: Links summary claims to transcript evidence
- **Consent**: Cloud providers require explicit user consent
### Export
- **Formats**: Markdown, HTML, PDF (via WeasyPrint)
- **Content**: Transcript with timestamps, speaker labels, summary
### Named Entity Recognition (NER)
- **Engine**: spaCy with transformer models
- **Categories**: person, company, product, technical, acronym, location, date, other
- **Segment tracking**: Entities link to source `segment_ids`
### Trigger Detection
- **Signals**: Calendar proximity, audio activity, foreground app
- **Actions**: IGNORE, NOTIFY, AUTO_START
### Webhooks
- **Events**: `meeting.completed`, `summary.generated`, `recording.started`, `recording.stopped`
- **Delivery**: Exponential backoff retries
- **Security**: HMAC-SHA256 signing
### Authentication
- **OIDC**: OpenID Connect with discovery
- **Providers**: Configurable via OIDC registry
---
## Feature Flags
| Flag | Default | Controls |
|------|---------|----------|
| `NOTEFLOW_FEATURE_TEMPLATES_ENABLED` | `true` | AI summarization templates |
| `NOTEFLOW_FEATURE_PDF_EXPORT_ENABLED` | `true` | PDF export format |
| `NOTEFLOW_FEATURE_NER_ENABLED` | `false` | Named entity extraction |
| `NOTEFLOW_FEATURE_CALENDAR_ENABLED` | `false` | Calendar sync |
| `NOTEFLOW_FEATURE_WEBHOOKS_ENABLED` | `true` | Webhook notifications |
Access via `get_feature_flags().<flag_name>` or `get_settings().feature_flags.<flag_name>`.
---
## Common Pitfalls Checklist
### When Adding New Features
- [ ] Update proto schema first (if gRPC involved)
- [ ] Regenerate Python stubs
- [ ] Run `scripts/patch_grpc_stubs.py`
- [ ] Implement server mixin
- [ ] Update Python client wrapper
- [ ] Update Rust commands
- [ ] Update TypeScript adapter
- [ ] Update TypeScript types
- [ ] Add tests (both backend and client)
- [ ] Run `make quality`
### When Changing Database Schema
- [ ] Update ORM models in `persistence/models/`
- [ ] Create Alembic migration
- [ ] Update repository implementation
- [ ] Update UnitOfWork if needed
- [ ] Update converters in `infrastructure/converters/`
### When Modifying Existing Code
- [ ] Search for all usages first
- [ ] Update all call sites
- [ ] Run `make quality`
- [ ] Run relevant tests
---
## Known Issues & Technical Debt
See `docs/triage.md` for tracked technical debt.
See `docs/sprints/` for feature implementation plans.
---
## Configuration & Security
- Runtime settings from `.env` or `NOTEFLOW_` environment variables
- Settings module: `src/noteflow/config/settings/`
- Keep secrets and credentials out of the repo
- Use `.env` for local development configuration
---
## Commit & Pull Request Guidelines
- Use Conventional Commits: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`, `test:`
- Include concise scope when helpful: `feat(grpc): add streaming backpressure`
- PRs should:
- Describe the change clearly
- Link related issues/specs
- Note any DB or proto changes
- Include UI screenshots for client changes
- Pass all quality checks (`make quality`)
Fast Apply: IMPORTANT: Use `edit_file` over `str_replace` or full file writes. It works with partial code snippets—no need for full file content.
Warp Grep: warp-grep is a subagent that takes in a search string and tries to find relevant context. Best practice is to use it at the beginning of codebase explorations to fast track finding relevant files/lines. Do not use it to pin point keywords, but use it for broader semantic queries. "Find the XYZ flow", "How does XYZ work", "Where is XYZ handled?", "Where is <error message> coming from?"