# 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().` or `get_settings().feature_flags.`. --- ## 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 coming from?"