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

30 KiB

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

# 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

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

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

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

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

make fmt              # Format all code (Biome + rustfmt)
make fmt-check        # Check all formatting

E2E Tests

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.

# 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:

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:

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:

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:

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:

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 coming from?"