- Added assertions to verify that the exported content from the ExportService is of type string for Markdown format in multiple test cases.
- Ensured consistency in testing the output of the export functionality across different formats.
- Introduced `PdfExporter` class for exporting meeting transcripts to PDF format.
- Updated `ExportService` to support PDF as a new export format.
- Enhanced `proto_to_export_format` to handle PDF format.
- Added WeasyPrint as a dependency in `pyproject.toml` and `uv.lock`.
- Updated documentation to reflect the new PDF export capabilities and resolved issues from Sprint 3.
- Implemented tests for PDF export functionality, ensuring valid PDF output and proper handling of meeting data.
- Updated `pyproject.toml` to include additional mypy exclusions and plugins for improved type checking.
- Added mypy overrides for specific modules to handle complex type parameters and untyped calls.
- Revised roadmap documentation to reflect changes in the Diarization Application Service, renaming it to "Diarization Enhancements" and updating feature descriptions for clarity.
- Adjusted architectural decisions to clarify the application service layer requirements for upcoming sprints.
Sprint 0 consolidates all proto schema changes and database migrations
for Sprints 1-6 into a coordinated release.
Infrastructure:
- Add named_entities table migration with updated_at trigger
- Add webhook_configs and webhook_deliveries migrations
- Add httpx dependency for webhooks
- Multi-stage Docker build with NER support (with-ner target)
- Enable depends_on for db service in compose.yaml
Proto schema:
- Add SummarizationOptions message (Sprint 1)
- Add EXPORT_FORMAT_PDF enum value (Sprint 3)
- Add ExtractEntities RPC and messages (Sprint 4)
- Add Calendar RPCs and messages (Sprint 5)
- Proto regeneration script at scripts/regenerate_proto.sh
Tests:
- Add proto compilation tests verifying Sprint 0 messages
- Add feature flag tests with env var parsing
- Add migration structure and trigger tests
Documentation:
- Fix PROTO_CHANGELOG.md CalendarProvider field names
- Update COMPLETION_PLAN.md status to 100%
Client submodule updated with Sprint 0 TypeScript types.
- Updated the Summary entity to include provider and model names, along with tokens used and latency metrics for better tracking of summarization performance.
- Modified the ORM converters and repository methods to accommodate new attributes, ensuring backward compatibility.
- Introduced word timing position indexing to maintain order within summaries.
- Added a new SQLAlchemy model structure for improved organization of persistence layers, including core, identity, and integration models.
- Removed deprecated models and files to streamline the codebase.
- Updated client submodule to the latest commit af9dfce.
- Added a new frontend service in `compose.yaml` for development with Node.js, including necessary configurations for ports, volumes, and environment variables.
- Updated `example.env` to include default values for audio test parameters, improving clarity for device integration testing.
Backend:
- Extract gRPC client into modular mixins (_client_mixins/)
- Add StreamingSession class for audio streaming lifecycle
- Add gRPC config and type modules
- Fix test smells across test suite
Frontend (submodule update):
- Fix code quality issues and eliminate lint warnings
- Centralize CSS class constants
- Extract Settings.tsx sections into components
- Add code quality test suite
Quality:
- Add tests/quality/ suite for code smell detection
- Add QA report and correction plan documentation
- Added a comprehensive MCP Tools Reference section in `CLAUDE.md`, detailing various tools and their use cases for web scraping, reasoning, library documentation, semantic code tools, and more.
- Updated `example.env` to reflect new configuration options for retention, diarization, encryption, and desktop client settings, improving clarity and usability.
- Introduced a new `roadmap.md` file outlining the feature gap analysis and development roadmap for NoteFlow, focusing on core pipeline completion and future enhancements.
- Updated submodule reference in the `client` directory to the latest commit.
- Introduced a new submodule for the client located at `client`, pointing to the GitHub repository `https://github.com/vasceannie/noteflow-ai.git`.
- Updated `.gitmodules` to include the new submodule configuration.
- Introduced a new API specification file `noteflow-api-spec.json` detailing the real-time audio-to-text functionality.
- Removed obsolete client configuration files, including `.prettierrc.json`, `biome.json`, `index.html`, and various TypeScript configuration files.
- Deleted unused components and tests from the client directory to streamline the project structure.
- Expanded `.gitignore` to include temporary files and scratch documents.
- Enhanced `AGENTS.md` with guidelines on using Conventional Commits and PR descriptions.
- Added configuration notes to `README.md` for environment variable usage.
- Updated `pyproject.toml` to reflect changes in dependencies and comments.
- Introduced new files for client configuration and testing, including Prettier settings and Playwright tests.
- Removed deprecated client components and adjusted related documentation accordingly.
- Added new tests for various components and functionalities to improve coverage.
- Refresh last_access time via touch() for existing non-expired keys
- Track hits/misses in exists() for accurate cache statistics
- Use get_mut() to enable in-place modification of entries
- Fix mutable/immutable borrow conflict in exists() by separating check from removal
- Reset recording state on gRPC stop_meeting failure to prevent stuck UI
- Clean up orphaned meetings on start_streaming failure (best-effort)
- Return consistent state snapshots from seek/get_playback_state
- Replace expect() with proper error handling in CryptoBox::new()
- Use CommonJS format for PostCSS config for build tool compatibility
- Use deleteByPrefix for cache invalidation in stop() and delete()
- Move blocking file dialog to spawn_blocking to avoid UI freezes
- Prevent connection race conditions with attempt ID tracking
- Guard against missing root element with explicit check
- Delete corrupt cached values on JSON parse failure (cache.ts)
- Preserve trigger_pending state on streaming failure for retry
- Construct IPC payload dynamically to omit undefined device_id
- Return PlaybackInfo from seek command for immediate UI updates
- Replace unwrap() with format! in hex_encode to avoid panic paths
- Prevent stuck recording state if no meeting exists on stop_recording
- Cache non-serializable values in memory fallback (RedisCache)
- Remove expired entries on exists() check in Rust MemoryCache
- Validate snooze duration inputs with bounds checking
- Clear stale server_address on gRPC disconnect
- Handle invalid (non-finite/negative) duration values in format_duration
Cache improvements (cache.ts):
- Handle JSON.parse errors in RedisCache.get as cache miss, not backend failure
- Pre-serialize in RedisCache.set to catch errors before triggering fallback
- Collect keys before deleting in deleteByPrefix to avoid mutation during iteration
- Skip caching null/undefined results in withCache and cached helpers
Event listener safety (useTauriEvents.ts):
- Use Promise.allSettled to handle individual listener failures gracefully
- Log failures but continue with successfully registered listeners
Config validation (config.ts):
- Route setSection through mergeConfig for consistent validation
Command safety (Rust):
- accept_trigger: Add guards for disconnected/already-recording states
- stop_recording: Update local state only after server acknowledges
- seek: Validate position is finite, clamp to valid range, clear highlight if no match
- Add proper parameter names to NoOpCache method signatures for
better code clarity and IDE support
- Use overflow-safe midpoint calculation in binary search:
`left + (right - left) / 2` instead of `(left + right) / 2`
Bug fixes:
- Prevent infinite loop in MemoryCache.set when maxItems <= 0
- Fix keyring error handling to only generate new key on NoEntry error,
propagating other errors to prevent accidental data loss
- Fix annotation list_annotations default end_time (0.0 -> f64::MAX)
to correctly handle unbounded time ranges
- Move cache invalidation after successful delete to ensure atomicity
React improvements:
- Add mounted flag to App.tsx useEffect to prevent state updates on
unmounted component
Cache fixes:
- Add deleteByPrefix to Cache interface for targeted invalidation
- Fix MeetingService.delete to properly invalidate parameterized list caches
- Fix invalidateCache to not clear unrelated entries (was using cache.clear())
- DRY up RedisCache with withFallback helper method
- Extract eviction logic into *_locked helpers in memory.rs
Event handling fix:
- Fix race condition in useTauriEvents where listeners registered after
unmount would never be cleaned up. Now uses Promise.all with cancelled
flag to handle cleanup atomically.
- Migrate all components to use api.* facade instead of individual function imports
- Remove 77 lines of backwards-compatibility function aliases from tauri.ts
- Components now use: api.connection, api.recording, api.meetings, api.playback,
api.summary, api.export, api.triggers
Rust fixes:
- memory.rs: Fix TOCTOU race condition in get() - use single write lock
- memory.rs: Fix race in set() - single lock for evict+insert+cleanup
- config.rs: Add validation for auto_start_threshold (clamp 0.0-1.0)
- config.rs: Add minimum bounds for poll_interval and snooze_duration
- helpers.rs: Fix division by zero in normalize_db_level when range is 0
- helpers.rs: Add test for zero-range edge case
TypeScript fixes:
- cache.ts: Fix race condition in RedisCache fallback switching
- cache.ts: Use atomic switchToFallback() with promise serialization
Rust backend:
- Add config.rs with env-based configuration (server, audio, storage, triggers, cache)
- Add cache/ module with trait-based abstraction
- Implement MemoryCache with LRU eviction and TTL support
- Add CacheKey builder for consistent key formatting
- Add comprehensive tests for all modules
TypeScript frontend:
- Add config.ts with localStorage persistence and change subscriptions
- Add cache.ts with in-memory, Redis, and no-op backends
- Redis backend auto-fallbacks to memory if unavailable
- Add withCache() helper for transparent function caching
- Integrate caching into API services (meetings, connection)
- Automatic cache invalidation on mutations
- Add constants.rs for event names, gRPC settings, audio/crypto constants
- Add helpers.rs with now_timestamp(), new_id(), format_duration(), etc.
- Add constants.ts for frontend event names and type-safe constants
- Update all files to use centralized constants instead of hardcoded values
- Add comprehensive tests for helpers and constants
- Remove duplicate timestamp/UUID generation patterns
Thread Safety & Race Conditions:
- GrpcClient: Group related state into ConnectionState and StreamingState
structs with single RwLock each for atomic updates
- Connect/disconnect now update all connection fields in single lock
- Streaming state (meeting_id, active) updated atomically
State Duplication Eliminated:
- Remove connected and server_address from AppState (were duplicated)
- GrpcClient is now single source of truth for connection state
- AppState.get_status() reads from grpc_client.is_connected()
- Commands use grpc_client.is_connected() for connection checks
Lock Contention Optimization:
- Reduced from 5 individual locks in GrpcClient to 2 grouped locks
- ConnectionState: channel + server_address + connected
- StreamingState: meeting_id + active
Bug fixes:
- crypto/mod.rs: Rename base64_encode/decode to hex_encode/decode
(they were actually hex encoding, not base64). Add validation for
odd-length hex strings.
- app_state.rs: Fix tilde expansion in fallback meetings_dir path.
Now properly uses BaseDirs::home_dir() or falls back to /tmp.
- recording.rs: Add atomic state checks and proper cleanup on error.
If start_streaming fails after create_meeting, state is now cleaned up.
- useTauriEvents.ts: Fix event listener cleanup race condition.
Use ref pattern to avoid re-subscribing, await all listeners before
pushing to array, add mounted flag to prevent updates after unmount.
- Removed the `support/` and `tests/` directories from the Repomix configuration to streamline included files.
- Updated `repomix-output.md` to reflect the new file structure and clarify included patterns.
- Deleted the outdated `triage.md` document to reduce clutter and improve project organization.
- Introduced a new `ui.md` document detailing the migration plan for transitioning to a Rust/Tauri application, including architecture overview and feature parity checklist.
- Commented out environment variables and dependencies in `compose.yaml` for clarity.
- Updated `ensure_schema_ready` function to check for existing database schema before running migrations.
- Added new integration tests for various components, including summarization, streaming, and error handling.
- Improved error handling and logging in the `RecoveryService` and `DiarizationJob` workflows.
- Enhanced the `SqlAlchemyUnitOfWork` to support advanced scenarios and edge cases in database operations.
- Improved the `_stop_recording` method to stop the timer immediately for better visual feedback.
- Consolidated button state updates to ensure recording status is accurately reflected after stopping.
- Removed redundant timer stop logic from the end of the recording process, streamlining the code.
- Added guard against multiple stop attempts in the `_stop_recording` method to prevent erroneous state changes.
- Updated state management to immediately reflect recording status and disable the stop button accordingly.
- Removed redundant state reset logic after recording ends, streamlining the process.
- Added environment file support and a command for the server in `compose.yaml`.
- Updated the database image in `compose.yaml` to use `pgvector/pgvector:pg15`.
- Modified `pyproject.toml` to include additional dependencies for enhanced functionality.
- Updated `uv.lock` to reflect new package versions and added new packages for improved features.
- Enhanced migration scripts to ensure the `noteflow` schema exists before running migrations.
- Improved error handling in the `OllamaSummarizer` to include a new exception type.
- Refactored the `calendar` trigger to streamline imports and improve code clarity.
- Added module-level mocks in test configurations to handle missing dependencies gracefully.
- Updated .dockerignore to include additional cache and environment files, improving build efficiency.
- Changed the Dockerfile reference in compose.yaml to point to the new server-specific Dockerfile.
- Added `diart` as a dependency in pyproject.toml and uv.lock to support enhanced diarization features.
- Created a new server.Dockerfile for a streamlined development environment setup with necessary dependencies.
- Added `repomix-output.md` to `.gitignore` to exclude output files from version control.
- Updated `repomix.config.json` to include the `support/` directory in the include paths.
- Enhanced `TranscriptComponent` to improve search functionality with a debounce mechanism for input.
- Refactored search logic to filter visible segments based on the search query, ensuring better user experience.
- Updated `Meeting` and `Annotation` entities to use `utc_now()` for consistent UTC-aware timestamps.
- Introduced new repository protocols for `DiarizationJob` and `Preferences` to support additional functionalities.
- Implemented in-memory persistence for repositories to facilitate testing and development without a database.
- Added error handling and utility functions to streamline gRPC service responses and improve code maintainability.
- Added `asset_path` to the `Meeting` entity for audio asset storage.
- Implemented `AudioValidationResult` for audio integrity checks during recovery.
- Updated `RecoveryService` to validate audio file integrity for crashed meetings.
- Enhanced `SummarizationService` to include consent persistence callbacks.
- Introduced new database migrations for `diarization_jobs` and `user_preferences` tables.
- Refactored various components to support the new asset path and audio validation features.
- Improved documentation in `CLAUDE.md` to reflect changes in recovery and summarization functionalities.
- Created .dockerignore to exclude unnecessary files from Docker builds.
- Added .repomixignore for managing ignored patterns in Repomix.
- Introduced Dockerfile.dev for development environment setup with Python 3.12.
- Configured docker-compose.yaml to define services, including a PostgreSQL database.
- Established a devcontainer.json for Visual Studio Code integration.
- Implemented postCreate.sh for automatic dependency installation in the dev container.
- Added constants.py to centralize configuration constants for the project.
- Updated pyproject.toml to include new development dependencies.
- Created initial documentation files for project overview and style conventions.
- Added tests for new functionalities to ensure reliability and correctness.
- Introduced speaker diarization functionality using pyannote.audio and diart for both streaming and offline processing.
- Updated `pyproject.toml` to include new dependencies for diarization.
- Enhanced `TranscriptComponent` to handle speaker identification and color coding for speakers.
- Added new settings in `Settings` class for enabling and configuring diarization features.
- Updated `Segment` and gRPC models to include speaker ID and confidence metrics.
- Implemented a `DiarizationEngine` for managing diarization processes and speaker assignments.
- Created necessary database migrations to accommodate new speaker fields in segments.
- Added tests for audio reading and diarization functionalities to ensure reliability and correctness.
- Updated documentation to reflect new features and usage instructions for diarization.