Two fixes for the notification-parsing pipeline:
- CompanionDeviceManager pairing (DEVICE_PROFILE_WATCH -> COMPANION_DEVICE_WATCH
role -> RECEIVE_SENSITIVE_NOTIFICATIONS) via a new platform channel in
MainActivity.kt, companion_device_channel.dart and companion_access_controller,
surfaced as a card in parsing settings. Lifts the system "Confidential"
redaction that hid VTB/T-Bank notification text from the listener.
- raw_messages.ai_response: the model's raw completion content is now persisted
(schema v4 + migration) and shown in the parsing log detail panel. Unlike
draftJson it survives inbox sweeps and is filled even for partial/ignored
outcomes.
flutter analyze: no issues.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Drop ParseRuleKind from parse_rules (enum survives only in rule_candidates):
a rule is now a condition (pattern + matchMode + optional txTypeGuard) plus
any set of actions (merchantCanonical/categoryId/accountId) or isIgnore
- Field-wise resolution: findClassificationRule fills merchant/category,
findAccountRule feeds the account resolver - one message may use both
- Per-rule autoApply toggle + ruleAutoApplyEnabled gate check; off -> Inbox
with full prefill
- Dedup guard in ParseRulesRepositoryImpl.create: same condition updates or
reactivates the existing row instead of inserting a duplicate
- ParsingPipeline.reapplyRulesToInbox: sweep app inbox cards on cached AI
drafts after createRule/ignoreWithRule (zero tokens)
- Schema v2 -> v3 migration (drop kind, add auto_apply) + migration_v3_test
- Rework rule_editor_screen into a single unified form; update rules list,
rule cards, source app detail, l10n strings, and tests
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Notification parsing:
- Drop the account_bindings table/DAO/repo/entity/controller/screen; account
resolution now goes senderToAccount rule -> source_apps.defaultAccountId
(trusted) -> global default (untrusted -> Inbox), via v1->v2 migration.
- Add defaultAccountId to source_apps; per-app settings consolidated into
source_app_detail_screen (/settings/parsing/apps/:pkg).
- Inbox auto-learns an app default on first Confirm/CreateRule; account picker
on the card instead of a disabled button; parse_error_labels extracted.
Analytics:
- Replace placeholder screen with fl_chart cards (chart_card, chart_theme,
month_stepper, month_math domain helper); slim down habit_analysis_screen.
Android: add launcher icon (adaptive foreground + colors.xml) and app_name.
Tests: migration_v2, analytics (screen/month_math), AI retry, inbox
visibility; update resolver/gate/inbox suites for the new resolution path.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace the OpenRouter HTTP client with a DeepSeek client:
- data/openrouter/ -> data/deepseek/; OpenRouterClient -> DeepSeekClient
(+ DeepSeekCompletion / DeepSeek*Exception)
- base URL api.deepseek.com, drop OpenRouter-only headers
- DeepSeek has no strict json_schema: use response_format json_object
and rely on the prompt for shape (ai_schema.dart removed)
- secure-storage key openrouter_api_key -> deepseek_api_key
- default model deepseek/deepseek-v4-flash -> deepseek-chat
- l10n strings, test dart-defines (DEEPSEEK_API_KEY/_TEST_MODEL), docs
Also bundles in-progress findBodyIgnoreRule (body-level ignore rules
applied before the AI call) already present in the working tree.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>