Feature dump...#2
Conversation
|
Important Review skippedToo many files! This PR contains 283 files, which is 133 over the limit of 150. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (17)
📒 Files selected for processing (283)
You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
This PR is a broad feature drop that adds AI voice-memo related data models + persistence, a shared chrono-based extraction/parsing package (with tests), and a standalone Flutter “AI testbench” app, plus platform integrations for creating calendar/reminder actions and improving on-device LLM runtime behavior.
Changes:
- Added Drift tables + domain models for voice memos, AI-extracted actions, and crash reporting; refactored several models to
freezed. - Added
chrono_ai_flowshared package for prompt templates + LLM JSON parsing + deterministic time resolution, and introduced anai_testbenchFlutter app for benchmarking. - Updated mobile platform setup: iOS 14 minimum + EventKit method channel; Android foreground service + build-time patching for
whisper_ggml_plus.
Reviewed changes
Copilot reviewed 138 out of 279 changed files in this pull request and generated 18 comments.
Show a summary per file
| File | Description |
|---|---|
| zswatch_app/lib/data/models/extracted_action.dart | New Freezed model + enum + DB string conversions for AI-extracted actions |
| zswatch_app/lib/data/models/dfu_state.dart | Refactor DFU state from Equatable to Freezed; add speed history field |
| zswatch_app/lib/data/models/crash_summary.dart | New lightweight crash summary model |
| zswatch_app/lib/data/models/coredump_analysis.dart | New backend coredump analysis DTO with JSON factory |
| zswatch_app/lib/data/models/connection_phase.dart | New Freezed sealed connection lifecycle state machine |
| zswatch_app/lib/data/models/connection_event.dart | Refactor ConnectionEvent to Freezed |
| zswatch_app/lib/data/models/connection.dart | Refactor Connection to Freezed |
| zswatch_app/lib/data/models/comm_log_entry.dart | Refactor CommLogEntry/CommLogStats to Freezed |
| zswatch_app/lib/data/database/tables/voice_memos_table.dart | New Drift table for voice memo metadata + AI processing fields |
| zswatch_app/lib/data/database/tables/extracted_actions_table.dart | New Drift table for AI-extracted action suggestions |
| zswatch_app/lib/data/database/tables/crash_reports_table.dart | New Drift table for crash report persistence |
| zswatch_app/lib/core/constants/app_constants.dart | New centralized app constants to replace magic numbers |
| zswatch_app/lib/app.dart | Initialize voice memo sync, analytics, and crash persistence providers at startup |
| zswatch_app/ios/Runner/Info.plist | Raise iOS minimum version + add microphone/calendar/reminder permission strings |
| zswatch_app/ios/Runner/AppDelegate.swift | Add EventKit MethodChannel to create calendar events/reminders; add memory queries |
| zswatch_app/ios/Podfile | Set iOS 14 deployment target; enable permission_handler macros |
| zswatch_app/android/build.gradle.kts | Add Gradle-time patching for whisper_ggml_plus CMake/main source issues |
| zswatch_app/android/app/src/main/kotlin/dev/zswatch/app/LlmComputeService.kt | New Android foreground service + wakelock for LLM inference |
| zswatch_app/android/app/src/main/kotlin/dev/zswatch/app/BleConnectionForegroundService.kt | Improve UX when app task is removed by updating service notification state |
| zswatch_app/android/app/src/main/AndroidManifest.xml | Add permissions + declare LLM foreground service |
| zswatch_app/android/app/build.gradle.kts | Pin NDK version required by whisper_ggml_plus |
| third_party/fllama | Add fllama submodule pointer |
| specs/ci-cd.md | New CI/CD documentation for PR + nightly workflows |
| specs/ai-tasks/voice-memo-time-extraction.md | New design doc for deterministic time extraction pipeline using chrono_dart |
| packages/chrono_ai_flow/test/parser_test.dart | New unit tests for ChronoLlmParser parsing/normalization behaviors |
| packages/chrono_ai_flow/scripts/time_resolver_debug_manual.dart | Manual debug script for time resolution |
| packages/chrono_ai_flow/pubspec.yaml | New package pubspec for chrono_ai_flow |
| packages/chrono_ai_flow/lib/src/time_expression_resolver.dart | New deterministic time resolver combining chrono_dart + regex fallbacks |
| packages/chrono_ai_flow/lib/src/parser.dart | New parser utilities for extracting JSON objects/arrays from LLM output |
| packages/chrono_ai_flow/lib/src/models.dart | New models for parser output + resolved time |
| packages/chrono_ai_flow/lib/src/correction_prompt_template.dart | New shared STT correction prompt template + token estimation |
| packages/chrono_ai_flow/lib/chrono_ai_flow.dart | Package barrel exports |
| ai_testbench/windows/runner/win32_window.h | Windows runner scaffold for ai_testbench |
| ai_testbench/windows/runner/win32_window.cpp | Windows runner implementation for ai_testbench |
| ai_testbench/windows/runner/utils.h | Windows runner utilities header |
| ai_testbench/windows/runner/utils.cpp | Windows runner utilities implementation |
| ai_testbench/windows/runner/runner.exe.manifest | Windows runner manifest (DPI awareness, OS compatibility) |
| ai_testbench/windows/runner/resource.h | Windows runner resources header |
| ai_testbench/windows/runner/main.cpp | Windows runner main entrypoint |
| ai_testbench/windows/runner/flutter_window.h | Windows FlutterWindow host header |
| ai_testbench/windows/runner/flutter_window.cpp | Windows FlutterWindow host implementation |
| ai_testbench/windows/runner/Runner.rc | Windows runner resources |
| ai_testbench/windows/runner/CMakeLists.txt | Windows runner CMake target |
| ai_testbench/windows/flutter/generated_plugins.cmake | Generated Windows plugin list (FFI fllama) |
| ai_testbench/windows/flutter/generated_plugin_registrant.h | Generated Windows plugin registrant header |
| ai_testbench/windows/flutter/generated_plugin_registrant.cc | Generated Windows plugin registrant source |
| ai_testbench/windows/flutter/CMakeLists.txt | Generated Windows Flutter build glue |
| ai_testbench/windows/CMakeLists.txt | Windows top-level CMake for ai_testbench |
| ai_testbench/windows/.gitignore | Windows build ignores |
| ai_testbench/test_single_prompt.py | Utility script to run a single transcript through headless benchmark |
| ai_testbench/test/widget_test.dart | Basic Flutter widget smoke test for ai_testbench |
| ai_testbench/show_failures.py | Utility script to print failed benchmark cases from results |
| ai_testbench/run_benchmark.py | Utility wrapper to run headless benchmark and summarize results |
| ai_testbench/pubspec.yaml | ai_testbench app dependencies incl. fllama + chrono_ai_flow + chrono_dart |
| ai_testbench/parse_results.py | Utility script to parse and print benchmark results |
| ai_testbench/parse_iter4.py | Utility script to parse results with alternate formatting |
| ai_testbench/macos/RunnerTests/RunnerTests.swift | macOS RunnerTests skeleton |
| ai_testbench/macos/Runner/Release.entitlements | macOS release entitlements |
| ai_testbench/macos/Runner/MainFlutterWindow.swift | macOS main window host |
| ai_testbench/macos/Runner/Info.plist | macOS runner Info.plist |
| ai_testbench/macos/Runner/DebugProfile.entitlements | macOS debug entitlements |
| ai_testbench/macos/Runner/Configs/Warnings.xcconfig | macOS build warning settings |
| ai_testbench/macos/Runner/Configs/Release.xcconfig | macOS release config includes warnings |
| ai_testbench/macos/Runner/Configs/Debug.xcconfig | macOS debug config includes warnings |
| ai_testbench/macos/Runner/Configs/AppInfo.xcconfig | macOS app identity settings |
| ai_testbench/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json | macOS app icon set manifest |
| ai_testbench/macos/Runner/AppDelegate.swift | macOS AppDelegate setup |
| ai_testbench/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist | Xcode workspace checks (generated) |
| ai_testbench/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme | Xcode scheme for Runner |
| ai_testbench/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist | Xcode project workspace checks |
| ai_testbench/macos/Podfile | macOS CocoaPods setup for ai_testbench |
| ai_testbench/macos/Flutter/GeneratedPluginRegistrant.swift | macOS generated plugin registrant |
| ai_testbench/macos/Flutter/Flutter-Release.xcconfig | macOS Flutter release xcconfig |
| ai_testbench/macos/Flutter/Flutter-Debug.xcconfig | macOS Flutter debug xcconfig |
| ai_testbench/macos/.gitignore | macOS build ignores |
| ai_testbench/linux/runner/my_application.h | Linux runner scaffold header |
| ai_testbench/linux/runner/my_application.cc | Linux runner GTK application host |
| ai_testbench/linux/runner/main.cc | Linux runner main |
| ai_testbench/linux/runner/CMakeLists.txt | Linux runner CMake target |
| ai_testbench/linux/flutter/generated_plugins.cmake | Generated Linux plugin list (FFI fllama) |
| ai_testbench/linux/flutter/generated_plugin_registrant.h | Generated Linux plugin registrant header |
| ai_testbench/linux/flutter/generated_plugin_registrant.cc | Generated Linux plugin registrant source |
| ai_testbench/linux/flutter/CMakeLists.txt | Generated Linux Flutter build glue |
| ai_testbench/linux/CMakeLists.txt | Linux top-level CMake for ai_testbench |
| ai_testbench/linux/.gitignore | Linux build ignores |
| ai_testbench/lib/widgets/memo_card.dart | UI card for visualizing chrono_ai_flow JSON extraction |
| ai_testbench/lib/time_extraction_main.dart | Headless runner for time extraction benchmark |
| ai_testbench/lib/services/time_expression_resolver.dart | Re-export chrono_ai_flow resolver for testbench use |
| ai_testbench/lib/services/llm_service.dart | fllama wrapper service for inference (testbench) |
| ai_testbench/lib/screens/time_extraction_screen.dart | UI screen to run/visualize time extraction benchmarks |
| ai_testbench/lib/prompts/time_extraction_prompts.dart | Prompt selection + rendering for time extraction benchmarks |
| ai_testbench/lib/prompts/prompt_templates.dart | Keep summarize prompt + supported language list |
| ai_testbench/lib/main.dart | Dispatch between UI and headless benchmark modes |
| ai_testbench/lib/correction_main.dart | Headless correction benchmark runner |
| ai_testbench/lib/benchmark_main.dart | Headless/UI benchmark runner with model/case selection and JSON output |
| ai_testbench/benchmark_results/headless_benchmark_2026-03-08_summary.md | Saved benchmark summary artifact |
| ai_testbench/android/settings.gradle.kts | Android build setup for testbench app |
| ai_testbench/android/gradle/wrapper/gradle-wrapper.properties | Gradle wrapper for testbench Android build |
| ai_testbench/android/gradle.properties | Gradle properties for testbench Android build |
| ai_testbench/android/build.gradle.kts | Android root build for testbench |
| ai_testbench/android/app/src/profile/AndroidManifest.xml | Android profile manifest for testbench |
| ai_testbench/android/app/src/main/res/values/styles.xml | Android styles for testbench |
| ai_testbench/android/app/src/main/res/values-night/styles.xml | Android night styles for testbench |
| ai_testbench/android/app/src/main/res/drawable/launch_background.xml | Android launch background |
| ai_testbench/android/app/src/main/res/drawable-v21/launch_background.xml | Android v21 launch background |
| ai_testbench/android/app/src/main/kotlin/com/example/ai_testbench/MainActivity.kt | Android MainActivity for testbench |
| ai_testbench/android/app/src/main/AndroidManifest.xml | Android main manifest for testbench |
| ai_testbench/android/app/src/debug/AndroidManifest.xml | Android debug manifest for testbench |
| ai_testbench/android/app/build.gradle.kts | Android app build config for testbench |
| ai_testbench/android/.gitignore | Android ignores for testbench |
| ai_testbench/analysis_options.yaml | Dart analyzer configuration for testbench |
| ai_testbench/README.md | Documentation for testbench usage and benchmarks |
| ai_testbench/.metadata | Flutter metadata for testbench project |
| ai_testbench/.gitignore | Git ignore rules for testbench project |
| Flutter-nRF-Connect-Device-Manager | Bump DFU submodule commit |
| CHANGELOG.md | New changelog file |
| .gitmodules | Add fllama submodule definition |
| .github/workflows/pr.yml | New PR CI workflow for formatting/analyze/test + Android/iOS builds |
| .github/copilot-instructions.md | Update repository Copilot instructions with AI testbench section |
Files not reviewed (1)
- ai_testbench/macos/Runner.xcworkspace/contents.xcworkspacedata: Language not supported
| case 'reminder': | ||
| return ExtractedActionType.reminder; | ||
| default: | ||
| return ExtractedActionType.task; |
There was a problem hiding this comment.
Silently mapping unknown DB values to ExtractedActionType.task can corrupt behavior (e.g., an unknown/typoed type becomes a task). Prefer failing fast (throw/FormatException), returning nullable, or introducing an explicit unknown enum value so the app can surface the issue and avoid creating the wrong OS-side action.
| return ExtractedActionType.task; | |
| throw FormatException('Unknown ExtractedActionType: $value'); |
| /// Foreign key to the parent voice memo | ||
| IntColumn get memoId => integer().named('memo_id')(); |
There was a problem hiding this comment.
This column is documented as a foreign key, but it isn't declared as a Drift reference. Without a FK, the DB can accumulate orphaned extracted actions when a voice memo is deleted, and you lose integrity guarantees. Consider declaring it as a reference (and importing the parent table), e.g. using references(VoiceMemos, #id) (or the appropriate table name in this codebase).
| /// Total number of images to upload | ||
| final int totalImages; | ||
| /// Speed history for chart (bytes per second samples) | ||
| @Default([]) List<int> speedHistory, |
There was a problem hiding this comment.
@Default([]) is an untyped empty list literal, which can become List<dynamic> under strict analysis and fail assignment to List<int>. Use a typed literal for the default (e.g. <int>[]) to ensure the generated code compiles cleanly and retains type safety.
| @Default([]) List<int> speedHistory, | |
| @Default(<int>[]) List<int> speedHistory, |
| val openAppIntent = packageManager.getLaunchIntentForPackage(packageName)?.apply { | ||
| flags = Intent.FLAG_ACTIVITY_SINGLE_TOP | ||
| } | ||
| val pendingIntent = PendingIntent.getActivity( | ||
| this, 0, openAppIntent, | ||
| PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE | ||
| ) |
There was a problem hiding this comment.
getLaunchIntentForPackage() can return null. Passing a null intent into PendingIntent.getActivity(...) will crash when starting the foreground service on some devices/ROMs. Provide a non-null fallback intent (e.g., an explicit intent to your launcher activity) before building the PendingIntent.
| <!-- Sync settings permissions for triggering Google Calendar sync after event creation --> | ||
| <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> | ||
| <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" /> | ||
| <uses-permission android:name="android.permission.READ_SYNC_STATS" /> | ||
|
|
There was a problem hiding this comment.
These SyncAdapter permissions are signature/privileged on modern Android and are not grantable to normal apps; keeping them in the manifest can cause policy/review issues and creates confusion about required capabilities. If you need to refresh calendars after insertion, prefer supported public APIs (e.g., insert via Calendar Provider and rely on system sync, or request sync via ContentResolver without privileged permissions) and remove these permissions.
| <!-- Sync settings permissions for triggering Google Calendar sync after event creation --> | |
| <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" /> | |
| <uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" /> | |
| <uses-permission android:name="android.permission.READ_SYNC_STATS" /> |
| try { | ||
| final results = Chrono.parse( | ||
| normalized, | ||
| ref: ref, | ||
| option: ParsingOption(forwardDate: true), | ||
| ); |
There was a problem hiding this comment.
This resolver contains non-trivial adjustment logic (weekday correction, 'next' semantics, and regex fallbacks), but there are currently only parser tests in this package. Add unit tests for TimeExpressionResolver.resolve() covering key branches (e.g., 'next Tuesday' when today is before/after Tuesday, 'on Wednesday' spoken on Wednesday, 'in X minutes/hours/days', 'tonight', 'day after tomorrow') to prevent regressions when tuning behavior.
| var resolved = results.first.date(); | ||
| if (resolved.isUtc) resolved = resolved.toLocal(); | ||
|
|
||
| final weekdayMatch = _weekdayNames.firstMatch(normalized); |
There was a problem hiding this comment.
This resolver contains non-trivial adjustment logic (weekday correction, 'next' semantics, and regex fallbacks), but there are currently only parser tests in this package. Add unit tests for TimeExpressionResolver.resolve() covering key branches (e.g., 'next Tuesday' when today is before/after Tuesday, 'on Wednesday' spoken on Wednesday, 'in X minutes/hours/days', 'tonight', 'day after tomorrow') to prevent regressions when tuning behavior.
| if (normalized.contains('next')) { | ||
| final daysFromRef = resolved.difference(ref).inDays; |
There was a problem hiding this comment.
This resolver contains non-trivial adjustment logic (weekday correction, 'next' semantics, and regex fallbacks), but there are currently only parser tests in this package. Add unit tests for TimeExpressionResolver.resolve() covering key branches (e.g., 'next Tuesday' when today is before/after Tuesday, 'on Wednesday' spoken on Wednesday, 'in X minutes/hours/days', 'tonight', 'day after tomorrow') to prevent regressions when tuning behavior.
| // Ignore and continue to regex fallbacks. | ||
| } | ||
|
|
||
| final regexResult = _generalRegex(normalized, ref); |
There was a problem hiding this comment.
This resolver contains non-trivial adjustment logic (weekday correction, 'next' semantics, and regex fallbacks), but there are currently only parser tests in this package. Add unit tests for TimeExpressionResolver.resolve() covering key branches (e.g., 'next Tuesday' when today is before/after Tuesday, 'on Wednesday' spoken on Wednesday, 'in X minutes/hours/days', 'tonight', 'day after tomorrow') to prevent regressions when tuning behavior.
|
|
||
| with open('/Users/jakkra/Documents/ZSWatch-App/ai_testbench/benchmark_results/results.json') as f: |
There was a problem hiding this comment.
This script hardcodes an absolute, user-specific path, making it unusable for other contributors and CI. Prefer resolving the results path relative to the script directory (or accept a CLI argument) so the script runs from any checkout location.
| with open('/Users/jakkra/Documents/ZSWatch-App/ai_testbench/benchmark_results/results.json') as f: | |
| import sys | |
| from pathlib import Path | |
| script_dir = Path(__file__).resolve().parent | |
| default_results_path = script_dir / 'benchmark_results' / 'results.json' | |
| if len(sys.argv) > 1: | |
| results_path = Path(sys.argv[1]).expanduser() | |
| else: | |
| results_path = default_results_path | |
| with open(results_path, 'r', encoding='utf-8') as f: |
- LLM-based transcription correction using fllama (llama.cpp FFI) - AI classification & summarization with structured action extraction (schedule, reminder, todo) from voice memo transcriptions - Live debug view with real-time token streaming during AI processing - Word-level diff highlighting between original and corrected transcription - Per-file debug info scoping in debug sheet - GGUF model import/management in Settings (file picker, delete, select) - AI startup self-test (4 test cases) on first launch - Extracted actions DB table + repository for structured data - 500ms delay between fllama inference calls to prevent NativeCallable use-after-free crash (SIGABRT workaround) - Tappable 'Processing with AI...' spinner opens debug bottom sheet - Handles loading/correcting/classifying phases with live UI updates
Voice memo AI processing:
- Add time expression resolver for converting relative times ("tomorrow at 3pm")
to absolute datetimes using current watch time context
- Add model benchmark service for comparing AI model performance
- Improve voice note AI pipeline with better action extraction and
time resolution
- Improve transcription engine with noise handling and better segmentation
- Add voice memo sync service improvements
- Remove ai_startup_test.dart (debug scaffold)
Calendar integration (Android):
- Add ExtractedActionCreationService: Flutter service wrapping the
productivity MethodChannel (createAction, listWritableCalendars,
openCalendarEntry, checkCalendarSyncHealth, openCalendarSyncSettings)
- Fix calendar sync on OnePlus/ColorOS: use CALLER_IS_SYNCADAPTER=true
URI when inserting events to cloud accounts, bypassing broken OEM
SyncAdapter framework
- Streamline requestCalendarSync(), trim verbose diagnostic logging,
remove debug test handlers from MethodChannel routing
- Add calendar permission and calendar picker to iOS (Info.plist, AppDelegate)
AI settings screen:
- Add ai_models_settings_screen.dart: dedicated screen for transcription
model selection, AI processing model selection, calendar integration
(Android-only, with proactive permission grant button), and model benchmark
- Calendar Integration section uses WidgetsBindingObserver to re-check
permission on app resume; warns on non-cloud (local-only) calendars
- Wire new screen into app router and settings screen navigation
Settings cleanup:
- Remove debug calendar tiles (_TestCalendarEventTile,
_TestCalendarEventIntentTile, _CalendarSyncStatusTile,
_ProductivityCalendarTile) from settings_screen.dart
- Move calendar and AI settings into ai_models_settings_screen.dart
- Remove unused imports from settings_screen.dart
Other:
- Add ai_debug_widgets.dart for AI processing debug overlays
- Update providers (ai_providers, settings_providers, voice_memo_providers)
with new state and service wiring
- Update voice_memos_screen with improved UI and AI processing triggers
- Add permission_handler and other deps to pubspec.yaml
Vendor fllama as a git submodule pointing to git@github.com:ZSWatch/fllama.git to fix iOS ggml header conflicts via CocoaPods configuration. The fork contains iOS header-map fixes: - podspec: USE_HEADERMAP=NO to prevent ggml header cross-resolution - podspec: iOS minimum bumped to 14.0 - Explicit relative includes in clip.cpp, llava.h, llama.h, log.h Changes: - third_party/fllama: git submodule (ZSWatch/fllama fork) - zswatch_app/pubspec.yaml: path dependency ../third_party/fllama - zswatch_app/ios/Podfile: set deployment target - zswatch_app/ios/Runner.xcodeproj/project.pbxproj: update deployment target - zswatch_app/lib/data/database/app_database.dart: guard schema v5 migration - zswatch_app/lib/providers/ai_providers.dart: use ref.listen to avoid recreating LlmService on model-id change
…l fit UI - iOS: Calendar Integration section shown on all platforms; add _RemindersPermissionTile - Podfile: PERMISSION_EVENTS, PERMISSION_EVENTS_FULL_ACCESS, PERMISSION_REMINDERS macros - AppDelegate: getDeviceMemoryMB via ProcessInfo.physicalMemory, switch-based routing - MainActivity: getDeviceMemoryMB via ActivityManager.MemoryInfo.totalMem - LlmService: ModelMemoryFit enum, ModelFitResult, _computeInferenceParams() RAM heuristic, CPU fallback <100 MB headroom, checkModelFit() public API - ai_providers: llmModelFitProvider (FutureProvider<ModelFitResult>) - Settings screen: _ModelMemoryFitBanner with green/amber/red fit indicator
…oggle - Update fllama submodule to fix cpp-httplib unconditional linkage that broke Android builds after the qwen 3.5 llama.cpp drop - Hide calendar/reminders permission tiles and calendar picker until AI processing is enabled in settings - listWritableCalendars() no longer auto-requests permission; it checks status only, returning empty list if not granted
- Add dedicated Voice Memo AI section header in settings - Rename AI & Transcription to Voice Memo AI throughout - Show model ranking badges (#1-#4) in model dropdown - Remove 3 worst-performing models from catalog - Remove Experimental label from Qwen3.5 - Move Import .gguf to standalone tile - Shrink Re-transcribe button to secondary TextButton - Add descriptive subtitle to Calendar Integration section - Fix Voice Memo AI grouped under Firmware Update section
…shes - Raise GPU threshold to >=1200MB available (was >=600MB) to avoid Metal KV cache allocation failures on memory-constrained devices - Prefer CPU + full nCtx=2048 over GPU when 600-1200MB available, ensuring the ~1136-token classify prompt fits without truncation - Add real-time available memory queries (os_proc_available_memory on iOS, ActivityManager.availMem on Android) instead of cached total RAM - Add 500ms delay between whisper and fllama inference for memory settling - Add memory diagnostics to AI debug view (available RAM, headroom, nCtx, GPU layers, max tokens cap) with low-memory warning indicator - Fix double-counting bug where model size was subtracted from available memory even though it was already loaded when queried - Never skip LLM inference on low memory; reduce maxTokens to 256 instead
Standalone Flutter desktop app for evaluating on-device GGUF models used by the companion app's voice memo pipeline. Benchmarks: - Structured extraction (intent/title/datetime JSON) - Time expression resolution (transcript → chrono_dart → DateTime) - STT correction (homophone/filler/punctuation fixes) Supports both interactive GUI and headless CLI modes. Also updated copilot-instructions.md with ai_testbench docs.
- Add 'auto_create_actions' setting (AutoCreateActionsNotifier provider) - Enhance sendResultToWatch() with confirmation timeout + onConfirmed callback - Sends AI result to watch as toast (3s undo window) - If no undo received within 5s, fires onConfirmed callback - If watch disconnected, creates immediately without round-trip - Cancels pending timer on undo_last from watch - Add _autoCreateActionsForMemo() helper: looks up pending actions, creates each via ExtractedActionOperations using selected calendar ID - Wire autoCreateActionsProvider → sendResultToWatch onConfirmed in providers - Add 'Auto-create calendar events' toggle in AI settings screen (enabled only when local AI + auto-process are both on) - Restore _ActionItem with Create/Dismiss/Open buttons and _ActionStatusBadge - Restore chrono extraction/resolution debug block in _AiDebugSheet - Fix audio player slider overlap (Expanded instead of fixed-width SizedBox)
- chrono_ai_flow: support array output (multiple events/tasks per transcript)
- parser: extract JSON array with single-object fallback
- models: add extractions list to ChronoLlmParseResult
- prompt: array output format, deadline recognition, direct weekday
translation (no forced 'next'), multi-item date context carry-forward,
preserve 'next' when explicitly in original transcript
- time_resolver: weekday-aware 'next' logic, same-day push-to-next-week fix
- ai_testbench: restructure benchmark for multi-item support
- BenchmarkCase/ExpectedItem/BenchmarkCaseResult support multiple items
- Expand test suite from 22 to 48 cases (Swedish events/reminders/notes,
short and long voice notes, multi-item Swedish, EN/DE singles)
- Headless serialization and UI updated for per-item failure details
- Python wrapper scripts for running and parsing results
- Disable macOS sandbox in Release.entitlements for h
- chrono_ai_flow: support array output (multiple events/tasks per transcript)
-y=2 - parser: extract JSON array with single-object fallback
- models: add era - models: add extractions list to ChronoLlmParseResult
de ug utility
…ge ranking - Reorganize catalog: English → Swedish → German → Multilingual - Add German models: Whisper Base and Small (multilingual forced to de) - Rank models within each language (best→worst): English #1-3, Swedish #1-3, German #1-2, Multilingual #1 - Display gold/silver/bronze badges in dropdown matching LLM model UI
…tion - Reorganize prompt with IMPORTANT sections for item splitting and intent - Remove Swedish-specific rules (weekday table, halv X, klockan) - Make prompt language-agnostic with examples teaching patterns implicitly - Add 8 new examples (Swedish, multi-item, negative title-translation) - Add CLI filtering (--case, --case-limit, --model) to benchmark runner - Add Swenglish and conversational test cases (51 total) - Increase nCtx to 4096 for larger prompt - Add benchmark helper scripts (show_failures.py, test_single_prompt.py) - Benchmark result: 46/51 (90%) with zero dropped items
- Extract shared AiDebugInfo class into ai_debug_info.dart - Add ActionChronoDebug for per-action chrono extraction details - Forward actionChronoDetails through processTranscript/BrainDump paths - Shared ai_debug_widgets.dart: aiFormatJson, aiMemoryInfoBlock, multi-action aiFormatChronoDetails with Action N headers - Both debug sheets (benchmark + voice memos) use unified widgets
- Apply selective improvements from external AI review: - Add JSON constraint (start with '[', end with ']') - Add comma-list rule to prevent over-splitting - Move schema before examples for better model comprehension - Strengthen title extraction rule (copy words from memo) - Clarify date propagation for multi-item memos - Restore Swedish/German connectors (och, och sen, sen, und) - Add AI transcript correction toggle (default OFF): - New setting in SharedPreferences (ai_correction_enabled) - Provider + notifier following existing toggle pattern - UI toggle in AI settings, gated by Local AI enabled - Wired through VoiceNoteAiPipeline to LlmService Benchmark: 47-48/51 (92-94%) across multiple runs
- raise default nCtx to 4096 for production and testbench - add compact chrono prompt for reduced-context devices - choose full vs compact prompt based on effective context size - surface prompt mode in debug UI strategy output - retune memory tiers for safer mobile inference
Points third_party/fllama to 39d7702, which adds numThreads to OpenAiRequest and forwards it through fllamaChat for the AI testbench.
Update fllama submodule: never install Dart NativeCallable as the global llama_log_set callback. This fixes the cleanup-thread crash and eliminates the event-loop flooding from hundreds of llama.cpp internal log messages. Add wall-clock timestamps to timing diagnostics for further verification.
…lity - Start ConnectionAnalyticsService and BatteryStorageService from app boot (app.dart) so connection events are recorded even when the analytics screen has never been opened - DB migration v1→v2: create new tables instead of drop-recreate to preserve existing data - Change disconnected color from red to orange for better visual contrast vs connected (green) in analytics timeline and event list - BLE fixes: guard against concurrent setup calls, force-close stale autoConnect GATT handles before reconnect, stop RSSI polling on disconnect, clear notify value on cleanup - GPS: stop updates when watch disconnects - Android: show "app killed" notification when task is swiped away - Voice memos: skip auto-creating tasks/reminders without a scheduled time - Various debug log cleanup Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Parse ver message SHA/debug fields and coredump BLE message - Add CrashSummary model and crash summary providers - Show crash indicator card on dashboard with dismiss/view actions - Add crash report screen with summary, copy-to-clipboard, and erase-on-watch functionality - Add crash report route to app router Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The DFU flow now sends the GadgetBridge smp_enable command automatically before starting any firmware or filesystem upload. No manual step on the watch is needed when using the companion app. - Add _ensureSmpEnabled() to DfuNotifier (enable, wait, rediscover) - Call it in startUpdate(), startFilesystemUpload(), startBothUpdates() - Replace manual SMP warning card with info card - Remove hasSmpService gate on update buttons - Update firmware_updates.md docs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Download coredump from watch via SMP/MCUmgr and send to backend for GDB analysis - Persist crash reports to local database (v3 schema migration) - Crash report screen: current crash tab + history tab with stored reports - Coredump analysis state tracked via Riverpod providers - Server URL configured to local dev server (192.168.1.77:8000) - ELF upload removed from app; handled by CI or upload_elf.py script - Added shell screen for developer diagnostics - Auto-enable SMP on watch connect to allow coredump download Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace swipe D-pad with circular touchpad that streams touch events to the watch via touchdown/touchmove/touchup shell commands - Position hardware buttons (Next/Prev/Select/Back) at 45° corners around the touchpad, matching physical watch layout - Use Listener + EagerGestureRecognizer to prevent parent ListView/TabBarView from intercepting touch during drag - Rate-limit touch move events to 50ms to avoid overwhelming BLE - Refactor LiveMonitorState to track structured power/cpu/thread data with per-thread history and poll count - Update coredump API URL to production endpoint Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ance - Add speed history line chart (fl_chart) to firmware update status card - Fix image counter staying at 0/3 by initializing to 1 and detecting image switches when bytesSent resets - Smooth speed/remaining time with 5-sample moving average instead of raw 1-second snapshots (both DFU and filesystem uploads) - Show actionable error when SMP enable fails on older firmware: guide user to Apps > Update > Enable FW Update on the watch - Update SMP info card on firmware screen with older FW hint
The watch reports a 12-char truncated SHA via BLE, but the ELF cache stores files under the full 40-char SHA from manifest.json. Add prefix matching to getCachedElf() and getCachedElfHash() so truncated SHAs match cached files.
- Add _polling guard to prevent overlapping poll calls - Reduce poll interval from 5s to 1s for more responsive updates - Add cancelPolling() method safe to call during widget lifecycle - Auto-stop after 5 consecutive errors with user-facing message - Track thread removal: mark threads no longer reported as removed - Add firstSeenPoll to ThreadHistory for display ordering - Debug logging for thread parse errors and empty results - Update .gitignore
- Add TimeRangeOption enum (1h/6h/12h/24h/7d) to analytics_providers.dart - Add connectionTimelineRangeProvider (StateProvider per watchId, defaults to 7d) - Update connectionTimelineProvider to use selected range instead of oldest event - Add _TimeRangeDropdown widget to _ConnectionTimelineCard - Remove _windowTitle helper (replaced by fixed title + dropdown)
4543384 to
778a8ef
Compare
- Add .github/workflows/pr.yml (analyze, test, build-android on PRs) - Add REFACTOR_PLAN.md - Add specs/ci-cd.md - Add packages/chrono_ai_flow/scripts/time_resolver_debug_manual.dart
No description provided.