Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

274 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Athar

أثر · Athar

The free, local-first replacement for "The Measure of a Plan" (TMOAP) budget Excel.
Trace every riyal — or dollar, dirham, rupee, pound — you spend. Quietly. On your device. Without spreadsheets.
تتبع أموالك. بوضوح.

License Android Min SDK 28 Kotlin 2.1.0 Compose Material 3 CI status

How it works · Features · Screenshots · Building · Roadmap · Privacy


أثر · Athar is a local-first Android app — an open-source, privacy-first replacement for the popular "The Measure of a Plan" (TMOAP) personal finance Excel workbook. It reads your bank SMS, parses every transaction, auto-categorizes against a 729-rule merchant catalog plus local user-learned rules, and replaces a complex Excel budget workbook with three calm screens: Today · Trends · Plan. Arabic + English. Multi-currency (18 codes). Encrypted on-device. No cloud. No ads. No telemetry. Ever.

Why · Replacing TMOAP

The Measure of a Plan (TMOAP) is a beloved personal-finance Excel workbook used by thousands worldwide to track monthly cash flow, savings rate, wishlists, and historical comparisons. It is rigorous, beautiful, and entirely manual — every transaction is typed in by hand.

Athar carries TMOAP's discipline (monthly cash flow → savings capacity → wishlist gating, historical period-vs-prior comparison, dashboard charts) into a phone that lives in your pocket and reads your bank SMS automatically. You get TMOAP-grade analysis without TMOAP's manual data-entry tax.

Search keywords: TMOAP replacement · The Measure of a Plan Excel alternative · open-source budget tracking app · personal finance spreadsheet replacement · monthly cash flow tracker · savings rate calculator · expense tracker without cloud · Excel budget Android · SMS budget app · privacy-first finance · multi-currency budget app · zero-knowledge expense tracker · Arabic budget app · Saudi budget tracker.

Other tools force a trade-off:

  • A spreadsheet (TMOAP, YNAB-on-sheet, custom Google Sheets) that knows your categories but requires manual entry for every transaction
  • A SaaS app (Mint, YNAB, Monarch, Copilot, Money Lover) that ingests transactions but sends your financial graph to a third-party server, runs ads, doesn't speak Saudi/Gulf banking, or doesn't work without a cloud account

Athar bridges that gap, locally and quietly. Your data never leaves the device unless you export it yourself.

Features

Today (اليوم)

  • ✅ One landmark net-flow number with count-up animation
  • Income + Expense pills (olive / ember) — see your monthly inflow and outflow at a glance
  • Savings-rate caption (e.g., "معدّل الادخار · 18٪") — the TMOAP discipline, on the home screen
  • Goals check — a compact savings-rate target and emergency-fund cue pulled from Plan targets
  • Today section at the top of the list filters to transactions where date == today so you instantly see what you spent today (with Today's net · X SAR subtitle in olive/ember). Below it: "This month's recent" for context.
  • ✅ Pending tray for SMS-captured transactions awaiting your confirmation
  • ✅ Swipe right to confirm · swipe left to dismiss · bulk actions for 5+ pending entries
  • ✅ Pending rows suggest a category from safe same-merchant confirmed history, with per-row and bulk safe-apply actions, category impact summaries, and no silent broad-rule creation
  • Ember attention banner when pending > 0 — "%d transactions awaiting review · Tap to review →" — impossible to miss above the net-flow number. Dust-color secondary banner appears below it when today had any auto-dismissed transactions, so parser false-negatives never go unnoticed.
  • Fail-safe ingestion (beta.15): SMS that parse as transactions are NEVER auto-dismissed; if the categorizer is uncertain, the transaction lands in PENDING for explicit user review. Money never silently disappears. See docs/adr/ADR-008-ingestion-fail-safe.md for rationale.
  • ✅ Auto-confirm transactions when category is already known (CategoryRule match); user fixes are recorded as new rules so the same merchant auto-confirms next time
  • ✅ FAB to add a manual transaction in seconds, with specific recent-merchant quick-add chips, quick phrase/voice fill, pasted receipt/OCR-text prefill, on-device receipt image OCR prefill, and multiple local encrypted receipt attachments that can be viewed/exported later from the edit sheet

Trends (النمط) — TMOAP-depth analysis

  • ✅ Period selector: month · 3 months · year · period-vs-prior · custom range
  • Headline numbers card with delta-vs-prior % and expense-as-%-of-income
  • Income · Expenses · Savings breakdown with savings-rate %
  • Monthly Dashboard — 3 panels (income / expense / savings) over the last 12 months, each with budget-target line + computed average line overlays (TMOAP "Income by Month / Expenses by Month / Savings by Month" parity)
  • Period-vs-prior comparison bars for income/expense/savings (TMOAP "Historical Comparison" sheet parity)
  • Category comparison table with delta in money + delta % per category
  • Proportional category split horizontal stacked bar (pie-chart replacement — pies banned per design brief)
  • Tap a bar → 12-month drilldown for that category, with monthly target overlay
  • ✅ Top-8 category bar chart
  • ✅ Hijri date display optional

Plan (الخطة)

  • Budget targets per category with variance pills (over/under)
  • Editable monthly targets — tap any row, type the number, save
  • Goals tab — savings-rate target and emergency-fund target, computed from confirmed history and liquid accounts
  • Bills calendar — Plan → Bills projects recurring rules 60 days ahead, highlights overdue items, and folds uncategorized pending transactions into the same scannable list
  • Bill reminders — opt-in, quiet reminders 2 days before, on due date, and once if a recurring expense remains pending
  • Wishlist with savings-capacity math (NOW / WAIT until YYYY-MM / INFEASIBLE)
  • Wishlist with TMOAP-style savings-capacity math — start month, desired horizon, remaining amount, needed/month, reconciliation-safe operating capacity, and NOW / WAIT until YYYY-MM / INFEASIBLE status
  • Wishlist planning summary — remaining wishlist backlog, ready-now count, next reachable month, target monthly pressure, and capacity-risk count
  • Family investments pool with percentage-based return entry, proportional share %, delete pool/contributor
  • Recurring transactions — define rent / salary / Netflix / utilities once; rules materialize into PENDING transactions on their due date

Ingestion + categorization (Saudi-first, universal-ready)

  • Al Rajhi SMS parser (Arabic + English) — purchase, transfer, deposit, profit deposit, loan instalment, credit card payment, declined transactions, transfers between own accounts
  • STC Bank · Alinma · D360 · Barq templates derived from real corpus, with date extraction so historical SMS sit in their correct months
  • User-defined templates — paste a sample SMS from your bank, mark the anchor strings around the amount/merchant, and confirm the live parse preview before saving (W-4)
  • Spam-resistant pipeline-AD suffix block (CITC convention), sender allow-list, ~40 ignore patterns for OTP/promo/marketing (Tasaheal, "Buy X Get Y", "Earn 10,000")
  • Sender-ID tolerant parsing — built-in bank sender matching trims edge whitespace and ignores casing drift, while known bank/wallet maintenance, fee, fraud-awareness, migration, and account-admin notices are ignored instead of becoming failed parses or pending transactions
  • Fallback parser merchant preservation — Arabic Al Rajhi purchase, transfer, and biller fallback rows preserve explicit merchant/counterparty labels when present, keeping pending rows useful for category rules and local learning instead of bank-sender placeholders
  • Private-corpus parser cleanup — Arabic card settlements, salary/cashback, D360 own-account transfers, public-service payments, account/card admin notices, account-tail purchase labels, ATM withdrawals, bank-fee debits, wallet refunds, and Al Rajhi header-only electronic/public-service payments are routed, ignored, or labeled correctly; a local received-message audit now reports 0 failed known-bank messages and 0 parsed expense rows with missing merchants
  • Parser registry parity — app ingestion, corpus tests, and private-audit work now use the same built-in SMS template registry, so new bank/wallet/notification templates cannot silently diverge from production order
  • Bank-admin notice filtering — beneficiary add/activation, mobile-login/biometric, card-product, card-service recovery, savings-promo, app-migration, brand, document, and fraud-awareness notices from known banks are ignored instead of polluting the SMS audit as failed parses
  • Notification listener path for Play-Store-safe distribution, with generic bank-app push parsing plus wallet/card-app phrases, peer-payment sent you/got paid income, posted refund/reversal/chargeback income, normalized ATM/cash-withdrawal, bank-fee, debt-payment, car-payment, mortgage-payment, utility-bill, salary-income, cashback-income, cash/cheque-deposit income, subscription-payment, merchant-preserving subscription renewals, insurance-premium, rent-payment, condo-fees, mobile-recharge, traffic-fine, government-service, parking-payment, toll-payment, transit-fare, medical, pharmacy, education, charity, zakat, fuel, grocery, restaurant, coffee, food-delivery, taxi-ride, flight-ticket, hotel, travel-booking, car-rental, clothing, electronics, online-shopping, cinema-ticket, event-ticket, game-purchase, gift-card, gift, flower-delivery, furniture-purchase, home-goods, appliance-purchase, work-expense, and office-supplies labels, bank-specific card-charge/debit-card merchant extraction, merchant-first charge/card-transaction copy, status-prefixed posted transaction merchant hints including processed/settled copy, title-first, body-line, label/value, digit-starting multi-line, digit-starting explicit merchant hints, digit-starting income/transfer counterparties, merchant names that begin with cleanup words such as Card Factory, at-symbol merchant hints such as @ Starbucks, card-used and card-used-at merchant hints, expense-side recipient/beneficiary merchant labels, amount-adjacent trailing merchant/biller extraction, structured Merchant:/Merchant Name:/Location:/Card acceptor:/Sender:/Recipient:/Biller:/Payer:/Receiver: labels, balance-aware transaction amount selection, clear balance-after extraction, balance/credit-state ignores, card/account admin ignores, spending-summary/recap ignores, reward/cashback amount guards, payment/money-request guards, OTP/payment-authorization and temporary-authorization-hold ignores, broader global ISO and regional-symbol notification currencies, comma-decimal amount formats, scheduled-payment, withdrawal-limit, fee-schedule, debt-reminder, deposit-limit/hold notices, car-payment reminder, mortgage-payment reminder/offer, condo-fee reminders/assessment notices, utility-bill-reminder, recurring-expense-reminder, subscription/rent offer/quote/discount ignores, insurance-premium quote/offer/estimate ignores, telecom-recharge-promo, public-service-reminder, mobility-payment-reminder, public-service/mobility quote/estimate/status/discount ignores, essential-life quote/estimate/status/reminder/appeal ignores, everyday-commerce offer/estimate/reservation/reminder, travel offer/itinerary/reservation/quote/reminder, retail-shopping offer/cart/shipping-status ignores, entertainment promo/showtime/presale/reservation/game-offer ignores, gift promo/balance/reminder/offer ignores, home-goods quote/cart/delivery/order-status/installation/warranty/offer ignores, work-expense claim/order-status ignores, salary-transfer financing-offer, and marketing-discount ignores, Google Pay/Samsung Pay package variants, broader MENA/APAC/Australia/US/Canada/Germany finance package coverage, Saudi wallet packages, and exact ANB package gating
  • Life-admin notification labels — posted home-service, gym-membership, and childcare/daycare payment pushes normalize to exact seed-backed labels while provider names are preserved when present and offer/quote/reminder copy with amounts is ignored
  • Car-maintenance notification labels — posted car-service, oil-change, car-wash, and tire-service payment pushes normalize to exact seed-backed labels while provider names are preserved when present and quote/estimate/appointment/reminder/offer copy with amounts is ignored
  • Car-payment notification labels — posted auto-loan, vehicle-finance, and Arabic car-instalment payment pushes normalize to the exact seed-backed Car payment label while auto-finance offers, due reminders, schedules, and estimates with amounts are ignored
  • Mortgage notification labels — posted mortgage, home-loan, housing-finance, and Arabic mortgage-instalment payment pushes normalize to the exact seed-backed Mortgage payment label while offers, due reminders, schedules, refinance/rate estimates, pre-approvals, and eligibility copy with amounts are ignored
  • Condo-fee notification labels — posted condo, HOA, strata, and building service-charge payment pushes normalize to the exact seed-backed Condo fees label while named associations/buildings are preserved when present and due reminders, assessments, invoices, statements, unpaid, and overdue copy with amounts are ignored
  • Gift notification labels — posted gift-card, gift, and flower-delivery payment pushes normalize to exact seed-backed gift labels while specific florists are preserved when present and free-gift promos, gift-card balances, expiry/reminder copy, and offers with amounts are ignored
  • Home-goods notification labels — posted furniture, home-goods, and appliance purchase pushes normalize to exact seed-backed home/electronics labels while named stores are preserved when present and quotes, carts/wishlists, delivery/order status, installation/assembly, warranty, reminders, and offers with amounts are ignored
  • Income notification labels — posted tax refund, expense reimbursement/refund/reversal/chargeback, and bonus income pushes normalize to exact seed-backed income labels while estimates, claims, and bonus promos with amounts are ignored
  • Cashback-income notification labels — posted cashback credits normalize to exact seed-backed Cashback income / دخل كاش باك side-income labels while cashback offers and reward-only copy with amounts are ignored
  • Deposit-income notification labels — posted cash, ATM, check, and cheque deposits normalize to exact seed-backed Other income labels while deposit limits, holds, pending notices, fees, and rate copy with amounts are ignored
  • Side-income notification labels — posted freelance, rental, dividend, and interest income pushes normalize to exact seed-backed side-income labels while sources are preserved when present and invoices, estimates, projections, rate updates, and announcements with amounts are ignored
  • Work-expense notification labels — posted work/business expense and office-supplies purchase pushes normalize to exact seed-backed work labels while named stores are preserved when present and claims, reports, quotes, offers, carts, shipping, and order-status copy with amounts are ignored
  • Multi-currency capture — foreign-card spend keeps both the original amount and the SAR equivalent
  • Self-transfer detection — moves to your own savings account flagged as "Own account move" (savings), not expense
  • Auto-detected recurring patterns — scans your confirmed history, surfaces "Same merchant, same amount, 3+ distinct months at similar day-of-month" candidates as suggestions you confirm with one tap, reuses the account/category only when every detected occurrence already agreed, and lets you override the active account/category before saving
  • 90-day historical SMS backfill on first install
  • ✅ Rule engine with 729 public seed rules across the bundled category catalog (beta.17+R-05+G-11 — expanded from 44 curated rules with AI-categorized patterns plus reviewed priority-90 catalog/private-audit/public-common batches and exact notification labels for recurring expenses, condo fees, telecom recharge, public-service payments, mobility payments, essential-life payments, everyday commerce, travel, retail shopping, entertainment, life-admin expenses, car maintenance, car payments, mortgage payments, gift payments, furniture purchases, home-goods purchases, appliance purchases, work expenses, office supplies, tax refunds, expense reimbursements, bonus income, cashback income, cash/check/cheque deposits, and freelance/rental/dividend/interest side income, then cleaned so private-person and ambiguous local side-income labels stay out of the public seed; rules auto-refresh on app upgrade)
  • ✅ Built-in category catalog refresh — existing installs receive newly bundled categories on app upgrade without overwriting user-edited names, archived state, targets, custom categories, or sort order; the bundled catalog now covers the concrete TMOAP workbook setup categories such as Condo fees, Work, Tax refund, Expense reimbursement, Bonus, and Other income
  • ✅ "Always categorize X as Y?" learn-from-correction loop — as of beta.18 the learned rule is backfilled to every existing PENDING + DISMISSED row matching the specific merchant pattern, not just future SMS. Picking "Always" for one Hemmah charge fixes every stranded Hemmah in one tap; generic labels stay one-row edits
  • ✅ Today and History show a short localized feedback card after "Always categorize..." so users know how many existing matching rows were fixed, or that future rows will auto-categorize when there were no existing matches
  • ✅ Transaction lists show readable localized category names instead of raw internal category IDs, including archived-category labels for old rows
  • Local category rule learning — after three confirmed transactions for the exact same specific merchant all share one category, Athar creates an exact local rule so future matches stop asking. Explicit "Always" rules still win for specific merchants; ambiguous English/Arabic merchant labels are ignored by the same guard used by Today, History, and bulk categorization
  • ✅ Source of every categorization is explainable (rule id, confidence)

Settings + ops

  • Multi-currency display — pick from 18 ISO-4217 codes (USD · EUR · GBP · AED · EGP · INR · PKR · TRY · SAR · KWD · QAR · BHD · OMR · JOD · CAD · AUD · CHF · JPY) with Arabic + English currency labels
  • Per-account ingestion routing — add SMS sender aliases or card/account tails to each account so new bank messages land on the right checking, savings, or credit-card account instead of the manual seed account
  • AES-256-GCM encrypted backup (Argon2-equivalent KDF, passphrase-protected)
  • Statement import + CSV export for Excel and bank-statement interop — preview detected fields, currency totals, and sample rows, edit/exclude bad rows or move individual rows to another account before confirmation, skip already-imported rows, then import TMOAP/Athar CSVs, transaction-grid XLSX workbooks, common statement CSVs/TSVs with description/amount, split debit/credit, or debit-credit indicator columns, OFX/QFX, or MT940 files; category lookup is type-aware and accepts TMOAP labels such as Public transportation, Wife, Job, Side project, and income Other; export annual data for your accountant
  • TMOAP Budget Targets import — Settings previews the workbook's Budget Targets sheet and applies matched monthly category targets only after confirmation, using the same TMOAP-aware expense/income category resolver as statement import
  • TMOAP Wishlist import — Settings previews the workbook's Wishlist sheet, then creates new wishes or updates matching existing wishes by item name after confirmation
  • TMOAP Family Investments import — Settings previews the workbook's family-investment pool and imports contributors without duplicating lower summary-table rows or repeat imports
  • Manual CSV column mapping — when a bank's CSV/TSV headers are unfamiliar, map date, merchant, amount/debit/credit, currency, category, type, and notes before preview/confirm
  • Annual accountant/tax PDF export — pick a year in Settings and export income/expense totals, category totals, and the confirmed transaction list
  • First-run XLSX/CSV import — new users can bring a TMOAP / Excel transaction log into Athar during onboarding instead of hunting for the Settings exchange later
  • SQLCipher database encryption at rest, key wrapped via Android Keystore
  • SMS audit log — every parsed/failed/ignored SMS retained, never deleted
  • Support diagnostics export — Settings writes a redacted JSON report with SMS parse counts, pseudonymous sender hashes, body-shape fingerprints/flags, failed-template groups, redacted parser errors, aggregate categorization-backlog counts, hashed specific repeated-merchant groups, and category-backlog recommendations for History repeated cleanup, bulk CSV categorization, manual cleanup, or no action. Generic labels such as payment, cash, bank, or كاش count toward total backlog but not repeated-group guidance. No raw SMS body, sender, merchant, amount, balance, card, account number, transaction row, or note is included
  • SMS audit log — every parsed/failed/ignored SMS retained, never deleted, with sender-health counts so failed banks and spammy senders are easy to spot after a backfill
  • Activity log — every transaction edit, with timestamp
  • All transactions history (H-01, beta.12) — searchable list of every transaction across all time, filter chips for status (All / Confirmed / Pending / Dismissed), type (Expenses / Income / Transfers), source (SMS / notification / manual / import / recurring / share), and category state (All / Uncategorized / Repeated backlog / Categorized), with row subtitles showing readable category names. The repeated-backlog filter isolates actionable repeated uncategorized merchants after the current search/source/type/status filters, sorts the largest visible same-merchant groups first, shows the visible group size on each repeated row, can select or explicitly apply a suggested category to the current top group in one bulk action, shows safe group/transaction impact before applying multiple visible safe repeated groups in one explicit action, and keeps that cleanup card open after top-group or safe-groups apply so the next group is ready after refresh. Tap any row to edit category or delete, or enter selection mode, select rows by tap, shown filter result, top repeated group, or same visible merchant, verify same-merchant context in the bulk card/category sheet, use unambiguous same-merchant history suggestions, quick-apply those suggestions explicitly, and apply one compatible category to many expense/income rows at once. Repeated same-merchant bulk assignments learn an exact local rule so future rows auto-categorize. Reachable from Settings → "All transactions"
  • Recover dismissed (beta.15) — one-tap action moves every DISMISSED transaction back to PENDING so users on older builds can recover what was hidden by the now-removed auto-dismiss policy
  • SMS backfill scans entire inbox (beta.11) — no 90-day cap; pass daysBack: Int? = null to scan all history
  • Rescan + clean button — shows the pending count, asks for confirmation, then wipes the pending tray and re-runs backfill with the latest templates
  • Per-app language picker (beta.11) — Follow system / Arabic / English; flips text + layout direction (RTL/LTR) on the fly via CompositionLocalProvider(LocalLayoutDirection). Language card sits at the TOP of Settings for discoverability
  • Own-account list — register the last-4 of your accounts so internal transfers are flagged as savings moves
  • Hijri date toggle
  • Subscriptions screen (R-04, beta.17+) — recurring rules reframed as subscriptions with Active / Paused sections, monthly-total card, one-tap Active↔Paused toggle, and account/category routing repair for existing rules
  • Confirm-before-create sheet (R-03, beta.17+) — tapping a recurring suggestion opens a sheet to edit cadence (Monthly/Weekly/Yearly), day-of-month, account, and category before saving the rule
  • Bulk categorize with AI (beta.18+) — copy the in-app AI prompt, export non-transfer PENDING/DISMISSED/uncategorized transactions to CSV, grouped so repeated specific merchants appear first with a merchant_group_count and row-level category_options, run it through ChatGPT/Claude, import the filled file or saved fenced csv response back. Choose full-context export when the linked local SMS/notification audit body helps categorization, or private export when you want the same import contract with raw_body blank. The prompt includes seed-backed guidance for normalized parser labels such as ATM withdrawals, bank fees, deposits, reimbursements, mobile recharge, work expenses, travel, retail, and life-admin payments. A single unambiguous compatible category choice can update blank peers in the same repeated specific-merchant group, while generic labels such as payment, cash, merchant, bank, or كاش stay row-by-row only; the importer accepts category IDs, copied option strings, or bilingual display labels, incompatible expense/income category mismatches are skipped with visible reason counts, and the preview shows category impact before Apply import. Each unambiguous type-safe specific merchant→category decision upserts one exact local rule so future SMS for the same normalized merchant auto-categorize without duplicate, stale, or generic exact rules. No API keys, no cloud round-trip — your personal merchant library grows permanently
  • Local category rule learning — repeated confirmed exact-merchant/category history creates private priority-150 exact rules. Explicit edit-sheet learning is also limited to specific merchants. No cloud, no community sharing, and no learning from ambiguous English/Arabic merchant labels
  • Reconcile to bank balance (beta.19) — per-account "تسوية / Reconcile" chip. Enter your bank's actual balance; Athar inserts one manual adjustment transaction so the running balance matches. No silent history rewrite, full audit trail
  • Share your rules with the community (beta.20) — Settings → "Help others · share your rules" exports only specific "Always categorize X" substring merchant→category mappings as JSON, then opens a pre-filled GitHub issue. Generic labels such as payment, cash, bank, كاش, and دفع, plus exact local rules from bulk imports or repeated-history learning, stay on device. Maintainer reviews accepted substring rules into the next release's seed for every user. Zero transaction data leaves your device
  • Home-screen widgets (beta.21+) — three localized Glance widgets: Month summary (net + Income/Expense/Net-worth pills), Today snapshot (today's net + pending count), and Pending list (top-3 pending transactions with Confirm / Dismiss / Categorize shortcuts). Widget body copy follows Athar's Arabic/English app-language preference, and widgets refresh after language or display-currency changes. Long-press home screen → Widgets → Athar
  • Support diagnostics export — Settings → "Support diagnostics" creates athar-support-diagnostics.json, a bounded redacted parser and categorization-backlog report for maintainers. It includes counts, sender hashes, body-shape fingerprints/flags, failed-template groups, redacted errors, coverage metrics, hashed specific uncategorized-merchant groups, and aggregate recommendation codes only. Generic labels still count in total backlog but not repeated-backlog recommendations. No raw SMS bodies, merchant names, transaction rows, notes, balances, amounts, or account/card numbers are included
  • Reconciliation no longer inflates expenses (beta.22) — manual adjustment transactions (تسوية يدوية) still move net worth but are excluded from monthly spend/income totals, Trends bars, Plan actuals, and widget snapshots
  • Update-availability nudge via Obtainium (beta.23) — Settings → "تابع التحديثات / Stay up to date" hands off update-tracking to Obtainium via a deep link. Athar stays fully offline (no INTERNET permission); Obtainium watches the GitHub releases page and notifies you when a new build ships
  • Recurring rules management with auto-detected suggestions from repeated specific merchants only, safe account/category defaults from unanimous history, active-account selection for manual rules and suggestion confirmation, existing-rule account/category repair, manual "Run now", and WorkManager auto-run so due subscriptions land in Pending without visiting Settings
  • ✅ Categories management (rename, archive, reorder, custom adds)

Screenshots

Captured from the v0.1.0-beta.1 signed APK running on a Pixel 6 / Android 14 emulator.


Onboarding · welcome

Onboarding · privacy

Onboarding · SMS perm

Today · empty state

Trends · empty

Plan · budget targets

Settings

About · credits

How it works

┌────────────────────────────────────────────────────────────────────┐
│  SMS broadcast      Notification listener      Manual entry        │
│       │                       │                      │              │
│       └─────────┬─────────────┴──────────┬──────────┘              │
│                 ▼                        ▼                          │
│           RawIngestEvent           Transaction (CONFIRMED)          │
│                 │                        │                          │
│                 ▼                        │                          │
│    SmsIngestionPipeline                  │                          │
│      ┌─ audit log (PARSED/FAILED/IGNORED)│                          │
│      ├─ parser (Al Rajhi templates)      │                          │
│      ├─ categorizer (rules → classifier) │                          │
│      └─ persist (PENDING)                │                          │
│                 ▼                        ▼                          │
│         ╔══════════════════════════════════════╗                    │
│         ║  Encrypted Room DB (SQLCipher)       ║                    │
│         ║  key wrapped via AndroidKeyStore     ║                    │
│         ╚══════════════════════════════════════╝                    │
│                 │                                                   │
│        ┌────────┼────────┬──────────┐                              │
│        ▼        ▼        ▼          ▼                              │
│      Today    Trends   Plan       Settings                          │
└────────────────────────────────────────────────────────────────────┘

The architecture intentionally separates each ingestion source from the parse/categorize/persist pipeline so the distribution flavor (sideload vs Play-Store-eligible) is a config change, not a rewrite.

See docs/adr/ for the decision records:

  • ADR-001 — Stack: Kotlin 2.1 + Compose Material 3 + Hilt + Room + multi-module
  • ADR-002 — Local-first: no backend, no telemetry, ever
  • ADR-003 — Encryption at rest: SQLCipher + Keystore-wrapped DB key
  • ADR-004 — MVP status after 24 build waves

Tech stack

Layer Choice
Language Kotlin 2.1.0
UI Jetpack Compose · Material 3
DI Hilt 2.54
Persistence Room 2.6 · SQLCipher 4.6 (AES-256-GCM, AndroidKeyStore-wrapped key)
Async Coroutines + Flow
Navigation Compose Navigation 2.8 (single-activity, type-safe routes)
Charts Custom Compose primitives (horizontal bar + monthly vertical bar)
Date/time kotlinx-datetime · java.time.chrono.HijrahDate for Hijri
Money java.math.BigDecimal — never Float/Double
Build Gradle 8.10 · convention plugins via build-logic/ included build · version catalog
Tests JUnit 5 · Truth · Turbine · Paparazzi (scaffolded) · Maestro (10 flows)
Typography Thmanyah typeface — sans + serif-display + serif-text
Logging Timber (debug); no Crashlytics (privacy commitment)

Building

# 1. JDK 17 + Android SDK
#    Either install Android Studio (bundles both), or:
#      JDK:  https://adoptium.net/  (Temurin 17)
#      SDK:  Android command-line tools, then `sdkmanager "platforms;android-35" "build-tools;35.0.1"`

# 2. Point the build at your SDK
echo "sdk.dir=/path/to/Android/Sdk" > local.properties

# 3. Bootstrap the Gradle wrapper (only first time)
gradle wrapper --gradle-version 8.10.2

# 4. Build
./gradlew :app:assemblePersonalFullSmsDebug

# 5. Install on a connected device
./gradlew :app:installPersonalFullSmsDebug
# or:
adb install app/build/outputs/apk/personalFullSms/debug/app-personalFullSms-debug.apk

Two flavors:

Flavor Permissions Distribution path
personalFullSms RECEIVE_SMS, READ_SMS Sideload only — your own daily-driver build
storeSafe No SMS perms Play-Store-eligible — uses NotificationListenerService, manual entry, statement import

Tests

./gradlew test                                   # all JVM unit tests
./gradlew :ml:categorizer:test                   # one module
./gradlew :app:assemblePersonalFullSmsDebug :app:assembleStoreSafeDebug
./gradlew :app:lintPersonalFullSmsDebug :app:lintStoreSafeDebug
./gradlew connectedAndroidTest                   # instrumented (needs emulator/device)
maestro test .maestro/flows/                     # 10 E2E flows

Roadmap

Shipped in v0.1.0-beta.1 → current

Foundations (beta.1):

  • ✅ Phase 0 foundations · 15 Gradle modules · build-logic convention plugins
  • ✅ Excel parity for manual entry (M-01..M-13)
  • ✅ Pending tray with swipe gestures (S-17..S-19)
  • ✅ Hijri date toggle (P-07)
  • ✅ SQLCipher encryption-at-rest with Keystore-wrapped key (ADR-003)
  • ✅ AES-256-GCM JSON backup + restore · statement import + CSV export
  • ✅ Wishlist + Family Investments (Phase 4)
  • ✅ Trends drilldown chart (M-07)
  • ✅ SMS audit + Activity log (S-21, S-23, P-08)
  • ✅ Al Rajhi SMS parsing + categorization (S-01..S-09)

Bank coverage + sustainability (beta.2 → beta.4):

  • ✅ Al Rajhi real-corpus templates (12 message types: PoS, online, transfers, deposits, profit, loan)
  • ✅ STC Bank · Alinma · D360 · Barq templates
  • ✅ User-defined SMS templates (W-4) — onboard your bank without code
  • ✅ Spam-resistant ingestion pipeline (ADR-006): sender allow-list + -AD block + 40 ignore patterns
  • ✅ Date extraction from SMS body (7 formats) so historical SMS sit in their correct months
  • ✅ Auto-confirm by category when confidence is high; uncertain parsed transactions stay in Pending for explicit user review
  • ✅ Self-transfer / own-account detection
  • ✅ Investment percentage-based returns + delete pool/contributor
  • ✅ TMOAP-seeded private build (gitignored) for the developer's own data — public APK stays clean

TMOAP-depth analysis (beta.5):

  • ✅ G-9 — Monthly Income/Expense/Savings bar panels with budget-target + average overlay lines
  • ✅ Period-vs-prior comparison bars (income/expense/savings)
  • ✅ Headline numbers card with savings rate + expense-as-%-of-income
  • ✅ Category comparison table with delta money + delta %
  • ✅ Proportional category split (horizontal stacked bar)
  • ✅ Custom date-range selector on Trends

Global sprint Tier 1 (beta.6 → beta.8):

  • G-1 — Multi-currency display (18 ISO-4217 codes with Arabic + English labels, currency picker in Settings)
  • G-2 — Income visibility (income + expense pills + savings-rate on Today header)
  • G-3 — Recurring transactions (rent / salary / Netflix / utilities — manual rules + specific-merchant auto-detected suggestions from history)
  • G-9 — TMOAP-depth Trends

Global sprint Tier 1 continued (beta.9):

  • G-4 — Multi-account + net worth view: Room v4→v5 migration adds 6 columns to the account table (openingBalance, sortOrder, archivedAt, notes, updatedAt); legacy DEBIT/CREDIT enum remapped to CHECKING/SAVINGS/CREDIT_CARD/CASH/INVESTMENT/OTHER. New AccountRepositoryImpl.observeNetWorth() aggregates openingBalance + Σ(CONFIRMED transactions) per account, returns the live net-worth flow used by the Today header pill and the new Accounts screen (CRUD + archive + edit + per-currency breakdown). Manual seed account is now a first-class CASH account, non-deletable but renameable/archivable.
  • G-6 — Custom date-range selector on Plan: Plan now has the same period picker as Trends (month / 3-month / year / custom). Monthly targets scale by average month-length of the selected range, with a caption (×N multiplier) so budget-vs-actual stays apples-to-apples.
  • G-5 — Localization (full): locale picker, DataStore persistence, attachBaseContext Configuration override + Compose LocalLayoutDirection provider. ~300 user-facing strings extracted to values/ (Arabic default) + values-en/ across app:onboarding, core:design-system, feature:today, feature:trends, feature:plan, feature:settings. ViewModels emit typed sealed states (AccountError, BackupStatus.ExportSuccess / ExportFailure(detail), etc.) and the Composable layer resolves them to stringResource(), so VMs stay pure (no Context dependency). Visually QA'd end-to-end on emulator: switched to English → all UI English + LTR (chart legends "Average/Target", swipe-row "Confirm/Dismiss", FAB + settings-gear flip sides, category-picker search field translates); switched back to Arabic → all UI Arabic + RTL. Remaining persisted-data debt (acceptable): the auto-seeded "النقدي" Cash-account name (user-renameable), SMS self-transfer merchant/notes (stored in DB at ingest time; future work would inject ApplicationContext or use a sentinel value resolved at render).

User-testing patches (beta.11–beta.15):

  • H-01 / All-transactions history (beta.12) — searchable + filterable list of every transaction; user can drill in from Settings, fix categories one by one, learn-rule propagates corrections to future SMS.
  • Today-section filter + pending banner (beta.13) — Today list now splits today's transactions from this-month-recent; ember banner above the header shouts "%d transactions awaiting review" with tap-to-history CTA. Stale-edit-sheet regression fixed with key(tx.id) { … } + synchronous state reset on EditTransactionViewModel.load().
  • Dismissed-today banner (beta.14) — dust-color secondary banner surfaces parser false-negatives so the user catches transactions Athar discarded.
  • Fail-safe ingestion (beta.15, ADR-008) — auto-dismiss removed entirely from the pipeline. Anything that successfully parses as a transaction lands in CONFIRMED (categorizer matched) or PENDING (user must decide). Never DISMISSED automatically. Money no longer silently disappears. One-tap "Recover dismissed transactions" Settings action moves every legacy DISMISSED row back to PENDING for existing users.
  • AI triage workflow (R-02, docs/AI_SMS_TRIAGE_PROMPT.md) — copy-paste prompt teaches an external AI (ChatGPT/Claude/Gemini) to read a bulk SMS export and return JSON with transactions + new parser_templates + new categorization_rules. Developer pastes JSON back, merges into seed_rules.json and per-bank template files. Lets the user expand bank coverage from any device's SMS without code changes per batch.

Current validation status

  • ✅ The recovered PR stack (#11–#30) is integrated locally on dev/integration-recovered-stack; details are in docs/RECOVERY_2026-06-13.md.

  • ✅ JVM tests, both debug APK builds, and both app lint variants pass with JDK 17.

  • ✅ The scoped dev/today-goals-nudge branch also passes :feature:today:test plus the full JVM test/build/lint stack after adding the Today Goals check.

  • ✅ The scoped dev/bill-reminders branch passes :core:domain:test, :feature:plan:compileDebugKotlin, :app:compilePersonalFullSmsDebugKotlin, and the full JVM test/build/lint stack after adding opt-in bill reminders. The full lint stack was run with --max-workers=1 because parallel lint analysis intermittently crashed inside Android lint's Kotlin FIR resolver on existing unit tests.

  • ✅ The scoped dev/sender-matching-reliability branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after hardening sender matching and adding sanitized corpus tests. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/notification-phrase-coverage branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after adding wallet/card-app notification phrase coverage. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/csv-import-preview-confirm branch passes :core:data:test, :feature:settings:test, and the full JVM test/build/lint stack after adding CSV import preview/confirm. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/notification-app-handlers branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after adding peer-payment, global-currency, Google Pay, and Samsung Pay notification coverage. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/ofx-qfx-import-preview branch passes :core:data:test, :feature:settings:test, and the full JVM test/build/lint stack after adding OFX/QFX statement import through the preview-confirm path. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/mt940-import-preview branch passes :core:data:test, :feature:settings:test, and the full JVM test/build/lint stack after adding MT940 statement import through the preview-confirm path. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/import-account-selection branch passes :core:data:test, :feature:settings:test, and the full JVM test/build/lint stack after adding destination-account selection to statement import confirmation. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/csv-delimiter-detection branch passes :core:data:test, :feature:settings:test, and the full JVM test/build/lint stack after adding comma/semicolon/tab delimiter detection to statement CSV import. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/csv-debit-credit-indicator branch passes :core:data:testDebugUnitTest, :core:data:compileDebugKotlin, and the full JVM test/build/lint stack after adding positive-amount CSV debit/credit indicator support. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/import-duplicate-safety branch passes :core:data:testDebugUnitTest, :core:data:compileDebugKotlin, :feature:settings:testDebugUnitTest, :feature:settings:compileDebugKotlin, and the full JVM test/build/lint stack after adding account-scoped duplicate-safe statement imports. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/localized-amount-parsing branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after adding localized comma-decimal amount parsing to generic notification and fallback SMS paths. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/curated-seed-rules-batch-2 branch passes :core:data:test and the full JVM test/build/lint stack after adding 15 more reviewed priority-90 seed rules. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/curated-seed-rules-batch-3 branch passes :core:data:testDebugUnitTest and the full JVM test/build/lint stack after adding 11 more reviewed priority-90 seed rules, bringing the active seed to 644 rules. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1; runtime validation remains blocked because adb devices -l returned no attached devices.

  • ✅ The scoped dev/notification-bank-specific-phrases branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after adding bank-specific notification merchant extraction and package coverage. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/global-notification-phrases branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after adding merchant-first charge/card-transaction notification parsing, broader ISO currency preservation, scheduled-payment ignores, and more global finance package coverage. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/manual-entry-voice-phrase branch passes :feature:today:testDebugUnitTest, :feature:today:compileDebugKotlin, and the full JVM test/build/lint stack after adding typed/voice quick-entry fill to Add Transaction. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1.

  • ✅ The scoped dev/manual-entry-receipts branch passes focused :core:domain:test, :core:data:testDebugUnitTest, :core:data:compileDebugKotlin, :feature:today:testDebugUnitTest, :feature:today:compileDebugKotlin, and the full JVM test/build/lint stack after adding encrypted manual receipt attachments.

  • ✅ The scoped dev/receipt-view-export branch passes :feature:today:test and the full JVM test/build/lint stack after adding edit-sheet receipt view/export/remove. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1; runtime tap-through remains blocked because adb devices -l returned no attached devices.

  • ✅ The scoped dev/bank-admin-notice-ignores branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after adding sanitized bank-admin notice ignores. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1; runtime tap-through remains blocked because adb devices -l returned no attached devices.

  • ✅ The scoped dev/csv-manual-column-mapping branch passes :core:data:testDebugUnitTest, :feature:settings:testDebugUnitTest, and the full JVM test/build/lint stack after adding manual CSV/TSV column mapping to statement import. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1; runtime Settings import tap-through remains blocked because adb devices -l returned no attached devices.

  • ✅ The scoped dev/import-preview-row-exclusion branch passes :core:data:testDebugUnitTest, :feature:settings:testDebugUnitTest, and the full JVM test/build/lint stack after adding import preview row exclusion. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1; runtime Settings import tap-through remains blocked because adb devices -l returned no attached devices.

  • ✅ The scoped dev/import-currency-review branch passes :core:data:testDebugUnitTest, :feature:settings:testDebugUnitTest, and the full JVM test/build/lint stack after adding per-currency import preview summaries. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1; runtime Settings import tap-through could not complete because the installed AtharPixelQaApi35 x86_64 AVD exits without the Android Emulator hypervisor driver, leaving adb devices -l empty.

  • ✅ The scoped dev/import-row-field-overrides branch passes :core:data:testDebugUnitTest, :feature:settings:testDebugUnitTest, and the full JVM test/build/lint stack after adding statement import preview row field editing. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1; runtime Settings import tap-through could not complete because the installed AtharPixelQaApi35 x86_64 AVD exits without the Android Emulator hypervisor driver, leaving adb devices -l empty.

  • ✅ The scoped dev/import-row-account-overrides branch passes :core:data:testDebugUnitTest, :feature:settings:testDebugUnitTest, and the full JVM test/build/lint stack after adding per-row account review to statement import previews. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, --no-daemon, and --max-workers=1; runtime Settings import tap-through could not complete because adb devices -l returned no attached devices and emulator -accel-check reports that the Android Emulator hypervisor driver is not installed.

  • ✅ The scoped dev/private-corpus-parser-hardening branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after adding sanitized ignore coverage for the last known-bank failures in the private family-device SMS export. A temporary local audit over 8,136 exported messages reported zero failed known-bank messages after the change; the raw export and audit helper remain uncommitted. Runtime tap-through remains blocked because adb devices -l returned no attached devices and emulator -accel-check reports that the Android Emulator hypervisor driver is not installed.

  • ✅ The scoped dev/private-corpus-fallback-parser-hardening branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after preserving Arabic Al Rajhi purchase, transfer, and biller labels from the private family-device SMS export. A temporary local audit over 8,136 exported messages reduced parsed expense rows with missing merchants from 3,800 to 474 and increased categorized expenses from 79 to 945; the raw export and audit helper remain uncommitted.

  • ✅ The scoped dev/curated-seed-rules-private-audit-batch branch passes :core:data:testDebugUnitTest and the full JVM test/build/lint stack after adding 13 reviewed priority-90 seed rules from aggregate-only private audit review, bringing the active seed to 657 rules. The raw export and temporary audit helper remain uncommitted; runtime tap-through remains blocked because no ADB target is attached and the local AVD still cannot boot without the Android Emulator hypervisor driver.

  • ✅ The scoped dev/private-corpus-missing-merchant-parser branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after routing Arabic card settlements, salary/cashback rows, D360 own-account transfers, public-service payment labels, and account/card admin notices correctly. A temporary app-equivalent local audit over 8,136 exported messages reduced parsed expense rows with missing merchants from 474 to 20; the raw export and temporary audit helper remain uncommitted. Runtime tap-through was attempted, but adb devices -l returned no attached devices and a bounded software-acceleration boot of AtharPixelQaApi35 exited before exposing ADB.

  • ✅ The scoped dev/curated-seed-rules-post-r13-audit branch passes parser tests, seed asset tests, and the full JVM test/build/lint stack after fixing account-tail merchant precedence, normalizing ATM withdrawal / bank-fee labels, and adding 10 reviewed priority-90 seed rules, bringing the active seed to 667 rules. A temporary app-equivalent local audit over 8,136 exported messages increased categorized parsed expenses from 1,113 to 1,238; the raw export and temporary audit helper remain uncommitted. Runtime install/tap-through was attempted, but no ADB target was attached and a bounded software-rendered boot of AtharPixelQaApi35 exited with -1073741819 before exposing ADB.

  • ✅ The scoped dev/xlsx-statement-import-preview branch passes :core:data:testDebugUnitTest plus the full JVM test/build/lint stack after adding direct transaction-grid XLSX import through the statement preview-confirm path. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, ANDROID_HOME=C:\Users\waok\Android\Sdk, --no-daemon, and --max-workers=1; runtime Settings/onboarding import tap-through could not complete because no device was attached, emulator -accel-check reports that the Android Emulator hypervisor driver is not installed, and a bounded software boot of AtharPixelQaApi35 stayed offline in ADB for 3 minutes.

  • ✅ The scoped dev/curated-seed-rules-post-xlsx-audit branch passes :core:data:testDebugUnitTest and the full JVM test/build/lint stack after adding 11 reviewed priority-90 seed rules from aggregate-only private audit review, bringing the active seed to 678 rules. A temporary local audit over 8,136 exported messages increased categorized parsed expenses from 1,238 to 1,265; the raw export and temporary audit helper remain uncommitted. Runtime tap-through was not applicable to this seed-only slice; adb devices -l still returned no attached devices and emulator -accel-check still reports that the Android Emulator hypervisor driver is not installed.

  • ✅ The scoped dev/notification-merchant-hints-followup branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after adding conservative notification merchant/counterparty hints for for, on, Arabic في, new transaction: merchant amount, and credit of ... from copy. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, ANDROID_HOME=C:\Users\waok\Android\Sdk, --no-daemon, and --max-workers=1; runtime notification tap-through could not complete because no device was attached and emulator -accel-check still reports that the Android Emulator hypervisor driver is not installed.

  • ✅ The scoped dev/transaction-category-labels branch passes :feature:today:testDebugUnitTest and the full JVM test/build/lint stack after replacing raw transaction category IDs in Today and History rows with localized category names, including archived-category labels for older rows. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, ANDROID_HOME=C:\Users\waok\Android\Sdk, --no-daemon, and --max-workers=1; runtime Today/History tap-through could not complete because no device was attached and the local AtharPixelQaApi35 x86_64 AVD exited with x86_64 emulation currently requires hardware acceleration.

  • ✅ The scoped dev/curated-seed-rules-public-leftovers branch passes :core:data:testDebugUnitTest and the full JVM test/build/lint stack after adding 8 reviewed priority-90 public/common seed rules, bringing the active seed to 686 rules. Broad catalog leftovers such as pizza, hospital, pharmacy, gym, airport, metro, and university remain excluded to avoid false positives; runtime tap-through is not applicable to this seed-only slice.

  • ✅ The scoped dev/notification-package-coverage-followup branch passes :ingestion:notification-listener:test, :ingestion:sms-parser:test, and the full JVM test/build/lint stack after allowing more known finance-app packages from MENA, Australia, India/Southeast Asia, and the US through both the Android notification listener filter and the existing conservative notification parser. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, ANDROID_HOME=C:\Users\waok\Android\Sdk, --no-daemon, and --max-workers=1; runtime notification tap-through could not complete because no device was attached, the x86_64 AVD requires the missing Android Emulator hypervisor driver, and the arm64 AVD is not supported on this x86_64 host.

  • ✅ The scoped dev/notification-labeled-fields branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after preserving merchants/counterparties from structured notification labels such as Merchant:, Sender:, Recipient:, Beneficiary:, and colon-separated From: fields. Validation was run with JAVA_HOME=C:\Users\waok\.codex\jdks\jdk-17.0.19+10, ANDROID_HOME=C:\Users\waok\Android\Sdk, --no-daemon, and --max-workers=1; runtime notification tap-through could not complete because no ADB device was attached, the arm64 AVD is not supported on this x86_64 host, and a bounded headless AtharPixelQaApi35 x86_64 launch with -accel off stayed offline in ADB after reconnect.

  • ✅ The scoped dev/sms-audit-full-filter-history branch passes :feature:settings:testDebugUnitTest and the full JVM test/build/lint stack after making SMS audit status filters select their visible 200 rows from the full audit history, so older Failed/Ignored rows remain reachable after large backfills instead of being hidden behind the All-window cap. Runtime tap-through could not complete because no ADB device was attached and emulator -accel-check still reports that the Android Emulator hypervisor driver is not installed.

  • ✅ The scoped dev/notification-party-label-fields branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after preserving structured notification party labels such as Biller:, Arabic المفوتر, Payer:, Remitter:, Receiver:, and transfer Payee: so more store-safe rows carry useful merchants/counterparties for categorization and local learning. Runtime notification tap-through could not complete because no ADB device was attached, emulator -accel-check reports that the Android Emulator hypervisor driver is not installed, and a bounded AtharPixelQaApi35 software launch did not expose an online ADB device after 3 minutes.

  • ✅ The scoped dev/curated-seed-rules-arabic-public-labels branch passes :core:data:testDebugUnitTest and the full JVM test/build/lint stack after adding Arabic public-platform seed coverage for Ejar, Mobily, Gonsure, and Tameeni, bringing the active seed to 690 rules while keeping the raw private SMS export uncommitted. Runtime install/launch was attempted, but the software-launched AtharPixelQaApi35 AVD stayed offline in ADB.

  • ✅ The scoped dev/multiple-receipts-per-transaction branch passes focused data/Today tests and the full JVM test/build/lint stack after letting one transaction keep multiple encrypted receipt images. It bumps Room to v7, removes the unique receipt-per-transaction index, preserves backup/export behavior, and updates Add/Edit transaction receipt controls so each saved receipt can be viewed, exported, or removed independently. Runtime install/launch was attempted, but no local AVD reached an online ADB state.

  • ✅ The scoped dev/receipt-text-prefill branch passes focused quick-entry parser tests, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 and ATHAR_PRIVATE_SMS_EXPORT set after letting the Add Transaction quick-entry field accept pasted receipt/OCR text. It extracts the total, merchant, and date from conservative English/Arabic receipt text, skips VAT/tax/subtotal/quantity lines, and still reuses local recent-merchant categories when the extracted merchant matches confirmed history. Runtime personalFullSmsDebug install was attempted with the built APK; AtharPixelQaApi35 exited before exposing ADB with exit code 1 because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and evidence was written to build/qa/receipt-text-prefill-emulator/.

  • ✅ The scoped dev/receipt-image-ocr branch passes focused Today parser/compile validation, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 and ATHAR_PRIVATE_SMS_EXPORT set after adding on-device ML Kit receipt image OCR. It runs after an image receipt is attached, reuses the conservative receipt text parser to prefill amount, merchant, date, and matching category, preserves Quick Entry text, and keeps the receipt attached with a clear status when OCR finds no usable text or fails. Runtime personalFullSmsDebug install was attempted with the built APK; AtharPixelQaApi35 exited before exposing ADB with exit code 1 because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and evidence was written to build/qa/receipt-image-ocr-emulator/.

  • ✅ The scoped dev/wishlist-planning-summary branch passes focused Wishlist domain tests, Plan compilation, and the full JVM test/build/lint stack after adding the W-09 Wishlist planning summary. Runtime install/launch was attempted; AtharPixelQaApi35 exited with Windows access-violation code -1073741819, and a windowed-hidden retry logged Failed to load opengl32sw before opening an emulator crash dialog with no ADB device.

  • ✅ The scoped dev/notification-balance-amount-selection branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after making generic bank-app notifications prefer the posted transaction amount over earlier balance/available-balance amounts in English and Arabic notification copy. Runtime install/launch was attempted; emulator -accel-check still reports no Android Emulator hypervisor driver, and a bounded AtharPixelQaApi35 software boot left only an emulator-5554 offline ADB transport with no emulator process.

  • ✅ The scoped dev/notification-marketing-discount-guards branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after preventing Arabic bank marketing discount offers from becoming fake expense rows while preserving real Arabic خصم ... debit notifications. Runtime install/launch was attempted; after clearing a stale headless qemu process and AVD locks, AtharPixelQaApi35 still stayed offline in ADB for 3 minutes under software acceleration.

  • ✅ The scoped dev/notification-reward-amount-guards branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after ignoring reward-only cashback notifications, skipping reward-adjacent amounts when a real spend amount is present, and preserving cashback credits as income. Runtime install/launch was attempted; AtharPixelQaApi35 again stayed offline in ADB for 3 minutes under software acceleration and the stuck headless process/locks were cleaned up afterward.

  • ✅ The scoped dev/notification-security-code-amount-guards branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after ignoring OTP/verification-code payment authorization notifications with amounts in English and Arabic while preserving real posted payment notifications. Runtime install/launch was attempted; AtharPixelQaApi35 emitted boot logs but never exposed an online ADB device, and stale AVD locks were cleaned afterward.

  • ✅ The scoped dev/notification-authorization-hold-guards branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after ignoring pending authorization, pre-authorization, temporary card-hold, and Arabic temporary-hold notification amounts while preserving real posted card-transaction notifications. Runtime install/launch was attempted; AtharPixelQaApi35 crashed before exposing ADB after Failed to load opengl32sw, and stale AVD locks were cleaned afterward.

  • ✅ The scoped dev/notification-balance-only-hint-guards branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after ignoring balance-only notifications even when they contain account/location hint wording such as at your checking account or Arabic لدى حسابك, while preserving balance-before-spend debit notifications. Runtime install/launch was attempted; AtharPixelQaApi35 crashed before exposing ADB after Failed to load opengl32sw, and stale AVD locks were cleaned afterward.

  • ✅ The scoped dev/notification-credit-state-guards branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after ignoring available-credit, credit-limit, cash-advance-limit, and Arabic credit-state notification amounts while preserving real credited-income notifications. Runtime install/launch was attempted; AtharPixelQaApi35 crashed before exposing ADB after Failed to load opengl32sw, and stale AVD locks were cleaned afterward.

  • ✅ The scoped dev/notification-admin-notice-guards branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after ignoring finance-app card/account administration notices such as card activation, terms updates, device-link notices, and Arabic card activation copy while preserving real card-use transaction notifications. Runtime install/launch was attempted; AtharPixelQaApi35 did not reach online ADB, logged Failed to load opengl32sw, opened an emulator crash dialog, and stale AVD locks were cleaned afterward.

  • ✅ The scoped dev/notification-spending-summary-guards branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after ignoring weekly/monthly spending recaps, English you spent ... this month summaries, and Arabic spending-summary notices while preserving real merchant spend notifications. Runtime install/launch was attempted; AtharPixelQaApi35 did not reach online ADB, logged Failed to load opengl32sw, opened an emulator crash dialog, and stale AVD locks were cleaned afterward.

  • ✅ The scoped dev/private-corpus-micro-parser-audit branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after moving the built-in SMS parser template order into a shared parser-module registry used by both app DI and corpus tests. Runtime install/launch was attempted; AtharPixelQaApi35 did not reach online ADB, logged Failed to load opengl32sw, opened an emulator crash dialog, and stale AVD locks were cleaned afterward.

  • ✅ The scoped dev/curated-seed-rules-global-common-batch branch passes :core:data:testDebugUnitTest and the full JVM test/build/lint stack after adding 15 concrete global public/common seed rules for subscription/software, delivery, and grocery labels, bringing the active seed to 705 rules without using or committing private SMS contents. Runtime install/launch was attempted; a bounded AtharPixelQaApi35 software boot emitted startup logs but never exposed an online ADB device, and the default x86_64 launch exited with x86_64 emulation currently requires hardware acceleration; stale AVD locks were cleaned afterward.

  • ✅ The scoped dev/private-corpus-admin-ignore-followup branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after adding sanitized ignores for private-corpus bank administration/account-state notices with numbers, and parsing structured wallet refunds as income. A temporary received-message audit over the private export reduced parsed expenses with missing merchants from 18 to 5; the raw export and scratch audit helper remain uncommitted. Runtime install/launch was attempted; AtharPixelQaApi35 emitted startup logs under -accel off but never exposed an online ADB device, so install could not run.

  • ✅ The scoped dev/alrajhi-electronic-payment-labels branch passes :ingestion:sms-parser:test and the full JVM test/build/lint stack after preserving Al Rajhi header-only electronic-payment and Ministry of Interior public-service labels as merchants. A temporary received-message audit over the private export reduced parsed expenses with missing merchants from 5 to 0; the raw export and scratch audit helper remain uncommitted. Runtime install/launch was attempted; AtharPixelQaApi35 emitted startup logs under -accel off but never exposed an online ADB device, so APK install and screenshot capture could not run.

  • ✅ The scoped dev/curated-seed-rules-post-r16-audit branch passes :ingestion:sms-parser:test, :core:data:testDebugUnitTest, and the full JVM test/build/lint stack after adding a gated redacted private-corpus aggregate audit and promoting the public buffet restaurant seed rule, bringing the active seed to 706 rules. The redacted local report inspects the private export without writing raw bodies, keeps failed known-bank messages and missing-merchant expenses at 0, and reduces uncategorized parsed expenses from 1,102 to 1,101. Runtime install/launch was attempted; AtharPixelQaApi35 stayed emulator-5554 offline under -accel off, so APK install and screenshot capture could not run, and the stuck headless qemu process/locks were cleaned.

  • ✅ The scoped dev/support-diagnostics-category-backlog branch passes :core:data:testDebugUnitTest and the full JVM test/build/lint stack after adding redacted transaction category-backlog counts and hashed uncategorized-merchant groups to support diagnostics. Runtime install/launch was attempted with the built personalFullSmsDebug APK; AtharPixelQaApi35 exited before exposing ADB with Windows access-violation code -1073741819 under both -gpu swiftshader_indirect and -gpu off software launches, and stale AVD locks were cleaned.

  • ✅ The scoped dev/support-diagnostics-category-coverage branch passes focused support diagnostics tests, full :core:data:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after adding a redacted category_coverage block plus per-group and cumulative backlog share to athar-support-diagnostics.json. The report now shows whether category cleanup is concentrated in repeated hashed merchants or scattered across one-off rows, while still omitting raw merchants, transaction rows, notes, amounts, balances, senders, and SMS bodies. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and the bounded hidden AtharPixelQaApi35 retry exited before exposing an online ADB device with exit code 1 because x86_64 emulation currently requires hardware acceleration, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/support-diagnostics-category-coverage-emulator/.

  • ✅ The scoped dev/bulk-categorize-group-impact branch passes focused bulk CSV/prompt tests and the full JVM/debug-APK/lint stack with JDK 17 after adding read-only rank/share/cumulative-share columns to the bulk category CSV after merchant_group_count. The export now gives humans and external AI a clear order for the highest-payoff repeated merchant cleanup while keeping old/new CSV import compatibility. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and the bounded hidden AtharPixelQaApi35 launch exited before exposing an online ADB device with exit code 1 because x86_64 emulation currently requires hardware acceleration, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/bulk-categorize-group-impact-emulator/, and the stale AVD lock was cleaned afterward.

  • ✅ The scoped dev/bulk-categorize-import-preview branch passes focused bulk importer/Settings ViewModel tests and the full JVM/debug-APK/lint stack with JDK 17 after making bulk-categorize CSV selection run a dry-run preview before any transaction/rule writes. Settings now shows update/rule/skip counts, holds the selected bytes only in memory, and applies the import only after Apply import. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and the bounded hidden AtharPixelQaApi35 launch exited after 5 seconds with exit code 1 because x86_64 emulation currently requires hardware acceleration, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/bulk-categorize-import-preview-emulator/, and the stale multiinstance.lock was cleaned after confirming no emulator/qemu/netsim process was running.

  • ✅ The scoped dev/bulk-categorize-import-impact-summary branch passes focused bulk importer/Settings ViewModel tests, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 and ATHAR_PRIVATE_SMS_EXPORT set after adding a localized category-impact line to the dry-run bulk import preview. The impact summary is computed only after the same matching, category resolution, type checks, and safe same-merchant propagation as the real import, so users can see which categories will receive updates before Apply import without exposing row ids, merchants, amounts, or raw SMS bodies. Runtime personalFullSmsDebug install was attempted with the built APK; AtharPixelQaApi35 exited before exposing ADB with exit code 1 because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and evidence was written to build/qa/bulk-categorize-import-impact-summary-emulator/.

  • ✅ The scoped dev/category-backlog-action-summary branch passes :core:data:testDebugUnitTest, the gated private SMS export audit, and the full JVM test/build/lint stack after making the bulk category CSV skip transfers, group repeated merchants first, and expose merchant_group_count. The private audit still reports 7,887 records, 3,864 parser successes, 0 failed known-bank messages, 0 missing-merchant parsed expenses, and 1,101 uncategorized parsed expenses for this workflow. Runtime install/launch was attempted; AtharPixelQaApi35 exited before exposing ADB with Windows access-violation code -1073741819, and stale AVD locks were cleaned.

  • ✅ The scoped dev/bulk-categorize-category-options branch passes :core:data:testDebugUnitTest, the gated private SMS export audit, and the full JVM test/build/lint stack after adding row-level category_options to the bulk categorization CSV so ChatGPT/Claude or a human can choose valid active category IDs from the current app category table. The latest module-scoped private audit report shows 7,887 records, 3,864 parser successes, 0 parser failures, 0 failed known-bank messages, 193 missing-merchant parsed expenses, and 1,385 uncategorized parsed expenses. Runtime install/launch was attempted; AtharPixelQaApi35 stayed emulator-5554 offline under a bounded -no-window -no-snapshot -no-audio -no-boot-anim -gpu swiftshader_indirect -accel off launch, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/private-audit-missing-merchant-shapes branch passes :ingestion:sms-parser:test, the gated private SMS export audit, and the full JVM test/build/lint stack after adding redacted missing-merchant shape groups to the private audit and fixing universal Arabic action detection so fallback حوالة rows become transfers instead of uncategorized expenses. The latest module-scoped private audit report shows 7,887 records, 3,864 parser successes, 0 parser failures, 0 failed known-bank messages, 2,374 parsed expenses, 1,262 categorized parsed expenses, 1,112 uncategorized parsed expenses, 0 missing-merchant parsed expenses, 0 raw bodies written, and no inactive catalog matches. Runtime install/launch was attempted; AtharPixelQaApi35 stayed emulator-5554 offline under a bounded -no-window -no-snapshot -no-audio -no-boot-anim -gpu swiftshader_indirect -accel off launch, and cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/private-audit-uncategorized-groups branch passes :ingestion:sms-parser:test, the gated private SMS export audit, and the full JVM test/build/lint stack after adding top hashed uncategorized merchant groups to the gated private audit report. The latest report still writes 0 raw bodies and shows the categorization backlog is concentrated enough to act on: top hashed groups have 55, 27, 12, 11, and 11 samples, with merchant length/script buckets and parser-template counts but no raw labels. Runtime install/launch was attempted; AtharPixelQaApi35 stayed emulator-5554 offline under a bounded -no-window -no-snapshot -no-audio -no-boot-anim -gpu swiftshader_indirect -accel off launch, so APK install could not run, and cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/bulk-categorize-group-import branch passes :core:data:testDebugUnitTest and the full JVM test/build/lint stack after making bulk categorization import apply one unambiguous category choice to blank peers in the same imported repeated-merchant group. Conflicting merchant-group choices update only explicit rows and do not train a learned rule. Runtime install/launch was attempted; AtharPixelQaApi35 exited before exposing ADB with Windows access-violation code -1073741819, stale AVD locks were removed, and cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/bulk-categorize-exact-import-rules branch passes :core:data:testDebugUnitTest and the full JVM test/build/lint stack after making bulk category imports train exact local merchant rules and making community-rule export omit exact local rules from bulk import or repeated-history learning. Runtime install/launch was attempted; AtharPixelQaApi35 exposed only an offline ADB transport briefly, then exited before install with Windows access-violation code -1073741819, and cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/bulk-categorize-category-value-normalization branch passes :core:data:testDebugUnitTest, :core:domain:test, the forced gated private SMS audit, git diff --check, and the full JVM test/build/lint stack after making bulk category import accept copied category option strings, copied bilingual display labels, and case-variant category IDs while keeping active-category resolution, type checks, skip counters, repeated-group propagation, and exact local rule training conservative. The forced private audit wrote redacted aggregate output only: 7,887 records, 3,864 parser successes, 4,023 ignored, 0 parser failures, 0 failed known-bank messages, 2,374 parsed expenses, 1,276 categorized expenses, 1,098 uncategorized expenses, 0 missing-merchant parsed expenses, and rawBodiesWritten = 0. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and a bounded hidden AtharPixelQaApi35 software launch stayed emulator-5554 offline, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/bulk-categorize-category-value-normalization-emulator/, and cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/bulk-categorize-type-safe-import branch passes :core:data:testDebugUnitTest, git diff --check, and the full JVM test/build/lint stack after making bulk category import reject category/type mismatches, skip incompatible repeated-merchant propagation, and avoid exact-rule training for mixed-type groups. Runtime install/launch was attempted with the built personalFullSmsDebug APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 reached only emulator-5554 offline, and cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/bulk-categorize-skip-breakdown branch passes :core:data:testDebugUnitTest, :feature:settings:testDebugUnitTest, git diff --check, and the full JVM test/build/lint stack after adding aggregate skip-reason counts to bulk category import and the Settings result card. Runtime install/launch was attempted with the built personalFullSmsDebug APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 stayed emulator-5554 offline for the bounded software launch, and cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/bulk-categorize-copy-prompt branch passes :core:domain:test, :feature:settings:testDebugUnitTest, git diff --check, and the full JVM test/build/lint stack after adding a one-tap Settings action that copies the external-AI bulk categorization prompt. Runtime install/launch was attempted with the built personalFullSmsDebug APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 stayed emulator-5554 offline for the bounded software launch, stale AVD locks were removed, and cleanup finished with no attached ADB device and no emulator/qemu/netsim process.

  • ✅ The scoped dev/bulk-categorize-fenced-csv-import branch passes :core:data:testDebugUnitTest, git diff --check, and the full JVM test/build/lint stack after accepting saved AI responses that contain a valid fenced csv block. Runtime install/launch was attempted with the built personalFullSmsDebug APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exited before exposing an online ADB device with Windows access-violation code -1073741819, runtime evidence was written to build/qa/bulk-categorize-fenced-csv-import-emulator/, and cleanup finished with no emulator/qemu/netsim process and no AVD locks.

  • ✅ The scoped dev/bulk-categorize-private-export branch passes :core:domain:test, :core:data:testDebugUnitTest, :feature:settings:testDebugUnitTest, :feature:settings:compileDebugKotlin, git diff --check, and the full JVM test/build/lint stack after adding a private bulk CSV export that keeps matching/category context but leaves raw_body blank. Runtime install/launch was attempted with the built personalFullSmsDebug APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exited before exposing an online ADB device with Windows access-violation code -1073741819, runtime evidence was written to build/qa/bulk-categorize-private-export-emulator/, and cleanup finished with no emulator/qemu/netsim process and no AVD locks.

  • ✅ The scoped dev/notification-pos-transaction-phrases branch passes :ingestion:sms-parser:test --tests "com.athar.ingestion.smsparser.GenericBankNotificationTemplateTest", :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after making generic POS/card transaction notification copy preserve clean merchant labels such as Trader Joe's and Carrefour. Runtime storeSafeDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 stayed emulator-5554 offline during the bounded software launch, runtime evidence was written to build/qa/notification-pos-transaction-phrases-emulator/, and cleanup finished with no attached ADB device, no adb/emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/notification-location-labels branch passes :ingestion:sms-parser:test --tests "com.athar.ingestion.smsparser.GenericBankNotificationTemplateTest", :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after making structured Location:, Merchant Name:, and Card acceptor: fields preserve merchants on posted finance-app notifications. Runtime storeSafeDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 stayed emulator-5554 offline during the bounded software launch, runtime evidence was written to build/qa/notification-location-labels-emulator/, and cleanup finished with no attached ADB device, no adb/emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/notification-payment-request-guards branch passes :ingestion:sms-parser:test --tests "com.athar.ingestion.smsparser.GenericBankNotificationTemplateTest", :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after ignoring amount-bearing payment/money request notifications that are not posted money movement. Runtime storeSafeDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 stayed emulator-5554 offline during the bounded software launch, runtime evidence was written to build/qa/notification-payment-request-guards-emulator/, and cleanup finished with no attached ADB device, no adb/emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/notification-status-prefix-merchant-hints branch passes :ingestion:sms-parser:test --tests "com.athar.ingestion.smsparser.GenericBankNotificationTemplateTest", :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after preserving merchants from status-prefixed posted transaction copy such as Payment successful: Noon SAR 99.00, Transaction completed - Carrefour AED 42.00, and Purchase approved: Toast Box SGD 6.40. Runtime storeSafeDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 stayed emulator-5554 offline during the bounded software launch, runtime evidence was written to build/qa/notification-status-prefix-merchant-hints-emulator/, and cleanup finished with no attached ADB device, no adb/emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/notification-recipient-label-hints branch passes :ingestion:sms-parser:test --tests "com.athar.ingestion.smsparser.GenericBankNotificationTemplateTest", :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after making posted expense notifications preserve merchants from structured Recipient:, Receiver:, and Beneficiary: labels while existing transfer recipient labels remain transfer counterparties. Runtime storeSafeDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 stayed emulator-5554 offline during the bounded software launch, runtime evidence was written to build/qa/notification-recipient-label-hints-emulator/, and post-inspection cleanup finished with no attached ADB device, no adb/emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/notification-card-used-merchant-hints branch passes :ingestion:sms-parser:test --tests "com.athar.ingestion.smsparser.GenericBankNotificationTemplateTest", :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after preserving merchants from card-used status labels such as Card used: Lulu SAR 55.00 and Card ending in 1234 was used - Amazon USD 12.99. Runtime storeSafeDebug install was retried with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35Arm exited because arm64 system images are not supported on this x86_64 host, a visible x86 software launch opened an emulator crash dialog and left stale locks, and a cleaned headless x86 software launch stayed emulator-5554 offline until the bounded wait expired. Install/screenshot/UI-dump/logcat capture could not run; evidence was written under build/qa/notification-card-used-merchant-hints-emulator*, and cleanup finished with no adb/emulator/qemu/netsim process and no AVD locks.

  • ✅ The scoped dev/notification-card-used-at-merchant-hints branch passes :ingestion:sms-parser:test --tests "com.athar.ingestion.smsparser.GenericBankNotificationTemplateTest", :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after preserving merchants from card-used-at copy such as Your card was used at Lulu for SAR 55.00 and Debit card used at Carrefour AED 42.00. Runtime storeSafeDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 emitted startup logs and exited before an online ADB device appeared, so install/screenshot/UI-dump/logcat capture could not run. Runtime evidence was written to build/qa/notification-card-used-at-merchant-hints-emulator/, and cleanup finished with no adb/emulator/qemu/netsim process and no AVD locks.

  • ✅ The scoped dev/notification-package-coverage-global-followup branch passes :ingestion:notification-listener:test, :ingestion:sms-parser:test, the focused GenericBankNotificationTemplateTest, the forced gated private SMS audit, git diff --check, and the full JVM test/build/lint stack after adding verified Canadian, German, and Saudi wallet/bank package IDs to both store-safe notification gates and tightening ANB to exact verified package IDs. Runtime storeSafeDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline during the bounded software launch, so install/screenshot/UI-dump/logcat capture could not run. Runtime evidence was written to build/qa/notification-package-coverage-global-followup-emulator/. A follow-up retry also wrote build/qa/notification-package-coverage-global-followup-emulator-retry/; AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and the x86_64 AVD emitted startup logs but exited before any online ADB device appeared. Cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/notification-essential-life-labels branch passes the focused GenericBankNotificationTemplateTest, :ingestion:sms-parser:test, :ingestion:notification-listener:test, :core:data:testDebugUnitTest, the forced gated private SMS audit, and the full JVM test/build/lint stack after normalizing posted medical, pharmacy, education, charity, and zakat notification payments to exact seed-backed labels, preserving specific clinics/charities, ignoring essential-life due reminders or donation appeals with amounts, and bringing the active public seed to 672 rules. Runtime storeSafeDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline, so install/screenshot/UI-dump/logcat capture could not run. Runtime evidence was written to build/qa/notification-essential-life-labels-emulator/, and cleanup stopped the qemu/netsim process with no attached ADB device remaining.

  • ✅ The scoped dev/notification-everyday-commerce-labels branch passes the focused GenericBankNotificationTemplateTest, :ingestion:sms-parser:test, :ingestion:notification-listener:test, :core:data:testDebugUnitTest, the forced gated private SMS audit, git diff --check, and the full JVM test/build/lint stack after normalizing posted fuel, grocery, restaurant, coffee, food-delivery, and taxi-ride notification payments to exact seed-backed labels, preserving specific stations/ride merchants, ignoring everyday-commerce offers, estimates, reservations, and reminders with amounts, and bringing the active public seed to 678 rules. Runtime storeSafeDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 exposed only emulator-5554 offline, so install/screenshot/UI-dump/logcat capture could not run. Runtime evidence was written to build/qa/notification-everyday-commerce-labels-emulator/, and cleanup left no attached ADB device and no emulator/qemu/netsim process.

  • ✅ The scoped dev/notification-travel-labels branch passes the focused GenericBankNotificationTemplateTest, :ingestion:sms-parser:test, :ingestion:notification-listener:test, :core:data:testDebugUnitTest, the forced gated private SMS audit, and the full JVM test/build/lint stack after normalizing posted flight-ticket, hotel, travel-booking, and car-rental notification payments to exact seed-backed travel labels, preserving named airlines/providers, ignoring travel offers, itineraries, reservations, quotes, and reminders with amounts, and bringing the active public seed to 682 rules. Runtime storeSafeDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 did not expose an online ADB device during the bounded software launch, so install/screenshot/UI-dump/logcat capture could not run. Runtime evidence was written to build/qa/notification-travel-labels-emulator/, and cleanup left no attached ADB device and no emulator/qemu/netsim process.

  • ✅ The scoped dev/notification-retail-shopping-labels branch passes the focused GenericBankNotificationTemplateTest, :ingestion:sms-parser:test, :ingestion:notification-listener:test, :core:data:testDebugUnitTest, the forced gated private SMS audit, git diff --check, and the full JVM test/build/lint stack after normalizing posted clothing, electronics, and online-shopping notification payments to exact seed-backed retail labels, preserving named stores, ignoring retail offers, carts, price drops, shipping/order-status copy with amounts, and bringing the active public seed to 685 rules. Runtime storeSafeDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 did not expose a boot-complete online ADB device, so install/screenshot/UI-dump/logcat capture could not run. Runtime evidence was written to build/qa/notification-retail-shopping-labels-emulator/, and cleanup left no attached ADB device and no emulator/qemu/netsim process.

  • ✅ The scoped dev/notification-entertainment-labels branch passes the focused GenericBankNotificationTemplateTest, :ingestion:sms-parser:test, :ingestion:notification-listener:test, :core:data:testDebugUnitTest, the forced gated private SMS audit, git diff --check, and the full JVM test/build/lint stack after normalizing posted cinema-ticket, event-ticket, and game-purchase notification payments to exact seed-backed entertainment labels, preserving named venues/events, ignoring entertainment promos, showtimes, presales, reservations, and game offers with amounts, and bringing the active public seed to 688 rules. The forced private audit wrote redacted aggregate output only: 7,887 records, 3,864 parser successes, 4,023 ignored, 0 parser failures, 0 failed known-bank messages, and 0 missing-merchant parsed expenses. Runtime storeSafeDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and a bounded hidden AtharPixelQaApi35 software launch did not expose a boot-complete online ADB device, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/notification-entertainment-labels-emulator/, and cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/notification-life-admin-labels branch passes the focused GenericBankNotificationTemplateTest, :ingestion:sms-parser:test, :ingestion:notification-listener:test, :core:data:testDebugUnitTest, the forced gated private SMS audit, and the full JVM test/build/lint stack after normalizing posted home-service, gym-membership, and childcare/daycare notification payments to exact seed-backed labels, preserving named providers, ignoring offers, quotes, and reminders with amounts, and bringing the active public seed to 691 rules. The forced private audit wrote redacted aggregate output only: 7,887 records, 3,864 parser successes, 4,023 ignored, 0 parser failures, 0 failed known-bank messages, 2,374 parsed expenses, 1,276 categorized expenses, 1,098 uncategorized expenses, 0 missing-merchant parsed expenses, and rawBodiesWritten = 0. Runtime storeSafeDebug install was attempted with the built APK; AtharPixelQaApi35 exited because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed, while AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Evidence was written to build/qa/notification-life-admin-labels-emulator/.

  • ✅ The scoped dev/notification-car-maintenance-labels branch passes the focused GenericBankNotificationTemplateTest, :ingestion:sms-parser:test, :ingestion:notification-listener:test, :core:data:testDebugUnitTest, the forced gated private SMS audit, git diff --check, and the full JVM test/build/lint stack after normalizing posted car-service, oil-change, car-wash, and tire-service notification payments to exact seed-backed labels, preserving named providers, ignoring quotes, estimates, appointments, reminders, and offers with amounts, and bringing the active public seed to 695 rules. The forced private audit wrote redacted aggregate output only: 7,887 records, 3,864 parser successes, 4,023 ignored, 0 parser failures, 0 failed known-bank messages, 2,374 parsed expenses, 1,276 categorized expenses, 1,098 uncategorized expenses, 0 missing-merchant parsed expenses, and rawBodiesWritten = 0. Runtime storeSafeDebug install was attempted with the built APK; AtharPixelQaApi35 exited because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed, while AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Evidence was written to build/qa/notification-car-maintenance-labels-emulator/.

  • ✅ The scoped dev/notification-car-payment-labels branch passes the focused GenericBankNotificationTemplateTest, :ingestion:sms-parser:test, :ingestion:notification-listener:test, :core:data:testDebugUnitTest, the forced gated private SMS audit, and the full JVM test/build/lint stack after normalizing posted auto-loan, vehicle-finance, and Arabic car-instalment notification payments to the exact seed-backed Car payment label, ignoring auto-finance offers, due reminders, schedules, and estimates with amounts, preserving the existing generic Loan instalment debt label, and bringing the active public seed to 696 rules. The forced private audit wrote redacted aggregate output only: 7,887 records, 3,864 parser successes, 4,023 ignored, 0 parser failures, 0 failed known-bank messages, 2,374 parsed expenses, 1,276 categorized expenses, 1,098 uncategorized expenses, 0 missing-merchant parsed expenses, and rawBodiesWritten = 0. Runtime storeSafeDebug install was attempted with the built APK; AtharPixelQaApi35 exited because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed, while AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Evidence was written to build/qa/notification-car-payment-labels-emulator/.

  • ✅ The scoped dev/notification-mortgage-payment-labels branch passes the focused GenericBankNotificationTemplateTest, :ingestion:sms-parser:test, :ingestion:notification-listener:test, :core:data:testDebugUnitTest, the forced gated private SMS audit, and the full JVM test/build/lint stack after normalizing posted mortgage, home-loan, housing-finance, and Arabic mortgage-instalment notification payments to the exact seed-backed Mortgage payment label, ignoring mortgage offers, due reminders, schedules, refinance/rate estimates, pre-approvals, and eligibility copy with amounts, preserving the existing generic Loan instalment debt label, and bringing the active public seed to 697 rules. The forced private audit wrote redacted aggregate output only: 7,887 records, 3,864 parser successes, 4,023 ignored, 0 parser failures, 0 failed known-bank messages, 2,374 parsed expenses, 1,276 categorized expenses, 1,098 uncategorized expenses, 0 missing-merchant parsed expenses, and rawBodiesWritten = 0. Runtime storeSafeDebug install was attempted with the built APK; AtharPixelQaApi35 exited because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed, while AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Evidence was written to build/qa/notification-mortgage-payment-labels-emulator/.

  • ✅ The scoped dev/notification-condo-fee-labels branch passes the focused GenericBankNotificationTemplateTest, focused SeedRulesAssetTest, git diff --check, the forced gated private SMS audit, and the full JVM test/build/lint stack after normalizing posted condo, HOA, strata, and building service-charge notification payments to the exact seed-backed Condo fees label, preserving named associations/buildings, ignoring due reminders, assessments, invoices, statements, unpaid, and overdue copy with amounts, and bringing the active public seed to 704 rules. The forced private audit wrote redacted aggregate output only: 7,887 records, 3,864 parser successes, 4,023 ignored, 0 parser failures, 0 failed known-bank messages, 2,374 parsed expenses, 1,287 categorized expenses, 1,087 uncategorized expenses, 0 missing-merchant parsed expenses, 20 hashed uncategorized merchant groups, and rawBodiesWritten = 0. Runtime storeSafeDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and a bounded hidden AtharPixelQaApi35 launch never exposed an online ADB device, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/notification-condo-fee-labels-emulator/, and cleanup finished with no emulator/qemu/adb/netsim process and no AVD lock files.

  • ✅ The scoped dev/notification-gift-payment-labels branch passes the focused GenericBankNotificationTemplateTest, :ingestion:sms-parser:test, :ingestion:notification-listener:test, :core:data:testDebugUnitTest, the forced gated private SMS audit, and the full JVM test/build/lint stack after normalizing posted gift-card, gift, and flower-delivery notification payments to exact seed-backed gift labels, preserving named florists such as Floward, ignoring gift promos, balances, expiry/reminder copy, and offers with amounts, and bringing the active public seed to 700 rules. The forced private audit wrote redacted aggregate output only: 7,887 records, 3,864 parser successes, 4,023 ignored, 0 parser failures, 0 failed known-bank messages, 2,374 parsed expenses, 1,276 categorized expenses, 1,098 uncategorized expenses, 0 missing-merchant parsed expenses, 20 hashed uncategorized merchant groups, and rawBodiesWritten = 0. Runtime storeSafeDebug install was attempted with the built APK; AtharPixelQaApi35 exited because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed, while AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Evidence was written to build/qa/notification-gift-payment-labels-emulator/.

  • ✅ The scoped dev/notification-home-goods-labels branch passes the focused GenericBankNotificationTemplateTest, :ingestion:sms-parser:test, :ingestion:notification-listener:test, :core:data:testDebugUnitTest, the forced gated private SMS audit, and the full JVM test/build/lint stack after normalizing posted furniture, home-goods, and appliance purchase notification payments to exact seed-backed home/electronics labels, preserving named stores such as IKEA, ignoring quotes, carts/wishlists, delivery/order-status, installation/assembly, warranty, reminder, and offer copy with amounts, and bringing the active public seed to 703 rules. The forced private audit wrote redacted aggregate output only: 7,887 records, 3,864 parser successes, 4,023 ignored, 0 parser failures, 0 failed known-bank messages, 2,374 parsed expenses, 1,276 categorized expenses, 1,098 uncategorized expenses, 0 missing-merchant parsed expenses, 20 hashed uncategorized merchant groups, and rawBodiesWritten = 0. Runtime storeSafeDebug install was attempted with the built APK; AtharPixelQaApi35 exited because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed, while AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Evidence was written to build/qa/notification-home-goods-labels-emulator/.

  • ✅ The scoped dev/seed-rules-private-name-hygiene branch passes :core:data:testDebugUnitTest, the forced gated private SMS audit, git diff --check, and the full JVM test/build/lint stack after removing 51 legacy private-person or ambiguous local side-income seed rules, adding an asset guard for future low-priority side-income seeds, and bringing the active public seed to 667 rules. The redacted private audit still writes 0 raw bodies, keeps parser failures and missing merchants at 0, and reports 1,276 categorized parsed expenses / 1,098 uncategorized parsed expenses; the lower private-corpus categorization count is intentional because those counterparties now belong in local learned rules, not the public seed. Runtime personalFullSmsDebug install was attempted; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 did not expose a boot-complete online ADB device, and final cleanup had no attached ADB device, no qemu/emulator/netsim process, and no AVD locks.

  • ✅ The scoped dev/category-seed-missing-categories branch passes focused core-data tests, full test, and the full debug APK build/lint stack with JDK 21 after making bundled category seeding upgrade-safe and enabling JUnit Platform for Android library tests. Runtime personalFullSmsDebug install was attempted; the built APK was ready, emulator -accel-check reported the Android Emulator hypervisor driver is not installed, and AtharPixelQaApi35 stayed emulator-5554 offline for the 120-second bounded launch, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/category-seed-missing-categories-emulator/, and final cleanup left no attached ADB device or emulator/qemu/netsim process.

  • ✅ The scoped dev/tmoap-category-parity branch passes focused CSV/category asset/prompt tests, full test, and the full debug APK build/lint stack with JDK 21 after adding the missing concrete TMOAP workbook categories and making statement category lookup transaction-type aware. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, and two bounded hidden AtharPixelQaApi35 software launches (-gpu swiftshader_indirect -accel off and -gpu off -accel off) exited after 4 seconds with Windows access-violation code -1073741819, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/tmoap-category-parity-emulator/ and build/qa/tmoap-category-parity-emulator-gpu-off/, and final cleanup left no attached ADB device, no emulator/qemu/netsim process, and no AVD lock files.

  • ✅ The scoped dev/tmoap-budget-target-import branch passes focused budget-target/XLSX/Settings tests, git diff --check, full test, and the full debug APK build/lint stack with JDK 21 after adding a separate Settings preview-confirm import for the TMOAP Budget Targets sheet. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, and AtharPixelQaApi35 only exposed an offline ADB transport under bounded software launch, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/tmoap-budget-target-import-emulator/; cleanup stopped the orphaned qemu process, removed the stale AVD lock, and left no attached ADB device, no emulator/qemu/netsim process, and no AVD lock files.

  • ✅ The scoped dev/tmoap-wishlist-import branch passes focused Wishlist/Budget Target/Settings tests, git diff --check, full test, and the full debug APK build/lint stack with JDK 21 after adding a separate Settings preview-confirm import for the TMOAP Wishlist sheet. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, and AtharPixelQaApi35 only exposed an offline ADB transport under bounded software launch, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/tmoap-wishlist-import-emulator/; cleanup stopped qemu/netsim, removed stale AVD locks, and left no attached ADB device, no qemu/emulator/netsim/adb process, and no AVD lock files.

  • ✅ The scoped dev/tmoap-investments-import branch passes focused Investment/Wishlist/Settings tests, git diff --check, full test, and the full debug APK build/lint stack with JDK 21 after adding a separate Settings preview-confirm import for the TMOAP Family Investments sheet. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed, and AtharPixelQaApi35 only exposed an offline ADB transport under bounded software launch, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/tmoap-investments-import-emulator/; cleanup stopped qemu/netsim, removed stale AVD locks, and left no attached ADB device, no qemu/emulator/netsim/adb process, and no AVD lock files.

  • ✅ The scoped dev/notification-trailing-party-hints branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after making store-safe notification parsing preserve compact amount-adjacent merchant/biller labels while stripping trailing balance/card/status suffixes. Runtime store-safe install was attempted; AtharPixelQaApi35 exposed only an offline ADB transport, exited before install with Windows access-violation code -1073741819, and cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/notification-regional-currency-symbols branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after preserving regional notification currency symbols such as S$, R$, RM, Rp, , , ฿, and as the correct ISO currencies instead of defaulting to SAR or plain USD. Runtime store-safe install was attempted; AtharPixelQaApi35 exited before exposing ADB with Windows access-violation code -1073741819, stale AVD locks were cleaned, and final cleanup had no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/notification-balance-after-extraction branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after preserving clear resulting balances from generic bank-app transaction notifications while leaving ambiguous balance-before-spend copy unset. Runtime store-safe install was attempted; AtharPixelQaApi35 exited before exposing an online ADB device with Windows access-violation code -1073741819, stale AVD locks were cleaned, and final cleanup had no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/curated-seed-rules-private-followup branch passes the gated private SMS audit, :core:data:testDebugUnitTest, and the full JVM test/build/lint stack after adding three reviewed priority-90 public/reusable seed rules, bringing the active seed to 709 rules. The redacted private audit still writes 0 raw bodies, keeps parser failures and missing merchants at 0, and reduces uncategorized parsed expenses from 1,112 to 1,077. Runtime personalFullSmsDebug install was attempted; AtharPixelQaApi35 did not expose an online ADB device under bounded -gpu swiftshader_indirect or -gpu off software launches, so install/screenshot capture could not run, and cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/private-audit-root-report branch passes the focused PrivateSmsExportAuditTest, the forced gated private SMS audit, git diff --check, and the full JVM test/build/lint stack after pinning the private-corpus audit output to repository-root build/private-corpus-audit/latest.json. The root redacted report now carries the rich aggregate fields in the expected place: 7,887 records, 3,864 parser successes, 4,023 ignored, 0 parser failures, 0 failed known-bank messages, 2,374 parsed expenses, 1,276 categorized parsed expenses, 1,098 uncategorized parsed expenses, 0 missing-merchant parsed expenses, 20 hashed uncategorized merchant groups, and rawBodiesWritten = 0. Runtime personalFullSmsDebug install was attempted with the built APK; AtharPixelQaApi35 exited because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and evidence was written to build/qa/private-audit-root-report-emulator/.

  • ✅ The scoped dev/private-audit-coverage-summary branch passes the focused PrivateSmsExportAuditTest, :ingestion:sms-parser:test, the forced gated private SMS audit, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after adding redacted category-coverage and uncategorized-group concentration metrics to the private audit. The forced root report still writes 0 raw bodies and reports 7,887 records, 3,864 parser successes, 4,023 ignored, 0 parser failures, 0 failed known-bank messages, 2,374 parsed expenses, 1,287 categorized expenses, 1,087 uncategorized expenses, 0 missing-merchant parsed expenses, top-20 hashed uncategorized groups covering 184 rows, 903 uncategorized rows outside those groups, and rawBodiesWritten = 0. Runtime personalFullSmsDebug install was attempted; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and a bounded hidden AtharPixelQaApi35 software launch exposed only emulator-5554 offline, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/private-audit-coverage-summary-emulator/, and cleanup finished with no emulator/qemu/adb/netsim process and no AVD lock entries.

  • ✅ The scoped dev/history-bulk-category-cleanup branch passes focused History bulk-selection tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after adding type-safe visible-row selection in History and a compact category-apply flow that confirms compatible expense/income rows while skipping transfers. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 did not expose a boot-complete online ADB device during the bounded hidden software launch, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-bulk-category-cleanup-emulator/, and cleanup finished with no emulator/qemu/adb/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-select-visible-cleanup branch passes focused History select-visible tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after adding a Select shown action to History selection mode, so a filtered cleanup set can be selected in one step before the existing type-safe category assignment. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-select-visible-cleanup-emulator/, and cleanup finished with no emulator/qemu/adb/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-select-same-merchant branch passes focused History same-merchant tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after adding a Same merchant action to History selection mode, so one representative visible row can select its currently shown normalized-merchant peers before the existing type-safe category assignment. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 did not reach an online ADB device or boot_completed=1, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-select-same-merchant-emulator/, and cleanup finished with no emulator/qemu/adb/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-exact-rule-learning branch passes focused History exact-rule tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after making repeated same-merchant History bulk category assignment create one exact local rule and show future-auto-categorization feedback. Mixed merchants, single-row selections, generic merchants, and explicit non-exact user rules do not train broad rules. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 did not reach an online ADB device or boot_completed=1, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-exact-rule-learning-emulator/, and cleanup finished with no emulator/qemu/adb/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-repeated-backlog-filter branch passes focused repeated-backlog History tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after adding a localized Repeated backlog category-state chip to History. The filter runs after status/type/source/search filters, includes only uncategorized non-transfer rows, groups by normalized merchant plus expense/income kind, ignores generic merchant keys, and reuses the existing selection/category/exact-rule-learning flow. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline without an online ADB device or boot_completed=1, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-repeated-backlog-filter-emulator/, and cleanup stopped the headless qemu process, removed stale AVD locks, killed ADB, and finished with no emulator/qemu/adb/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-repeated-backlog-counts branch passes focused repeated-count History tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after adding localized visible same-merchant group counts to History row subtitles while the Repeated backlog filter is active. Counts are computed from the visible filtered rows, reuse normalized merchant plus expense/income kind grouping, and stay hidden outside repeated-backlog mode. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline without an online ADB device or boot_completed=1, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-repeated-backlog-counts-emulator/, and cleanup finished with no emulator/qemu/adb/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-repeated-backlog-priority branch passes focused repeated-priority History tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after sorting the Repeated backlog result by visible same-merchant group size, largest first. The priority order is computed after the active status/type/source/search filters, keeps rows within a group stable, keeps equal-size groups deterministic by first visible occurrence, and does not affect All, Uncategorized, or Categorized ordering. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 exited before exposing an online ADB device or boot_completed=1 with exit code -1073741819, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-repeated-backlog-priority-emulator/, and cleanup finished with no emulator/qemu/adb/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-repeated-backlog-top-group branch passes focused top-group History tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after adding a localized Top group bulk-selection chip for the Repeated backlog view. The chip selects the largest visible same-merchant group in one action, replaces the current selection, disables once exactly that group is selected, and leaves Select shown, Same merchant, type-safe category assignment, and exact-rule learning unchanged. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline without an online ADB device or boot_completed=1, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-repeated-backlog-top-group-emulator/, and cleanup finished with no emulator/qemu/adb/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-bulk-selected-merchant-context branch passes focused selected-merchant History tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after showing same-merchant context in the bulk card and category sheet. The context appears only when selected visible rows share one specific merchant, uses the first visible selected row's merchant label, and stays hidden for mixed selections or generic merchant keys. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 exited before exposing an online ADB device or boot_completed=1 with exit code -1073741819, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-bulk-selected-merchant-context-emulator/, and cleanup finished with no emulator/qemu/adb/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-bulk-category-suggestion branch passes focused same-merchant suggestion History tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after making the History bulk category sheet preselect one active compatible category when full local same-merchant history has exactly one category. The sheet shows a localized suggestion count, keeps Apply explicit, and hides suggestions for conflicting history, inactive categories, mixed merchants, or generic merchant keys. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and the bounded hidden AtharPixelQaApi35 launch through C:\Users\waok\Android\Sdk\emulator\emulator.exe exited before exposing an online ADB device or boot_completed=1 with exit code -1073741819, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-bulk-category-suggestion-emulator/, and cleanup finished with no new emulator/qemu/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-bulk-suggestion-quick-apply branch passes focused quick-apply History tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after adding a localized Apply <category> chip to the History bulk card whenever the H-15 conservative suggestion is valid and normal bulk apply is allowed. The chip uses the existing type-safe bulk apply path, keeps the category picker available for override, and does not change exact-rule learning, transfer skipping, or mixed-type blocking. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and the bounded hidden AtharPixelQaApi35 launch through C:\Users\waok\Android\Sdk\emulator\emulator.exe exited before exposing an online ADB device or boot_completed=1 with exit code -1073741819, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-bulk-suggestion-quick-apply-emulator/, and cleanup finished with no new emulator/qemu/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-top-group-suggestion-apply branch passes focused top-group suggestion History tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after adding a localized Apply top <category> (<count>) chip to the Repeated backlog bulk card when the largest visible group has one valid H-15 same-merchant history suggestion. It applies that top group through the existing type-safe bulk apply path while preserving Top group, selected-row quick apply, category override, exact-rule learning, and transfer/mixed-type safeguards. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and the bounded hidden AtharPixelQaApi35 launch through C:\Users\waok\Android\Sdk\emulator\emulator.exe exited before exposing an online ADB device or boot_completed=1 with exit code -1073741819, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-top-group-suggestion-apply-emulator/, and cleanup finished with no new emulator/qemu/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-top-group-cleanup-mode branch passes focused History tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after keeping History selection mode open when the direct top repeated suggestion action succeeds. It clears selected rows, preserves normal selected-row bulk apply exit behavior, and lets the refreshed repeated-backlog card expose the next largest group without reopening cleanup mode. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and the bounded hidden AtharPixelQaApi35 launch through C:\Users\waok\Android\Sdk\emulator\emulator.exe exited before exposing an online ADB device or boot_completed=1 with exit code 1, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-top-group-cleanup-mode-emulator/, and cleanup finished with no emulator/qemu/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-safe-groups-apply branch passes focused safe-groups History tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after adding a localized Apply safe groups (<count>) chip to the Repeated backlog bulk card when more than one visible repeated group has a valid H-15 same-merchant suggestion. The action applies all and only safe suggested groups through the existing type-safe helper, leaves conflicting groups untouched, learns exact local rules for eligible applied groups, keeps selection mode open, and clears selected rows. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and the bounded hidden AtharPixelQaApi35 launch through C:\Users\waok\Android\Sdk\emulator\emulator.exe exited before exposing an online ADB device or boot_completed=1 with exit code 1, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-safe-groups-apply-emulator/, and cleanup finished with no emulator/qemu/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-safe-groups-summary branch passes focused History tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after adding a localized safe-suggestions summary to the Repeated backlog bulk card. The card now shows the safe group count and total transaction count before the explicit safe-groups action, without changing H-15/H-19 safety criteria or apply behavior. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and the bounded hidden AtharPixelQaApi35 software launch exited before exposing an online ADB device with exit code -1073741819, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-safe-groups-summary-emulator/, and cleanup finished with no emulator/qemu/netsim process and no AVD lock files.

  • ✅ The scoped dev/history-next-safe-group-apply branch passes focused History tests, full :feature:today:testDebugUnitTest, git diff --check, and the full JVM/debug-APK/lint stack with JDK 17 after adding a localized Apply safe <category> (<count>) chip to the Repeated backlog bulk card when the top repeated group conflicts but one lower repeated group is safe. The action reuses the safe-groups apply path for that single group, keeps cleanup mode open, learns the same exact local rule, and leaves the conflicting top group visible and untouched. Runtime personalFullSmsDebug install was attempted with the built APK; emulator -accel-check reported the Android Emulator hypervisor driver is not installed and the bounded hidden AtharPixelQaApi35 software launch exited before exposing an online ADB device with exit code -1073741819, so install/screenshot/UI-dump/logcat capture could not run. Evidence was written to build/qa/history-next-safe-group-apply-emulator/, and cleanup finished with no emulator/qemu/netsim process and no AVD lock files.

  • ✅ The scoped dev/notification-refund-reversal-income branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, git diff --check, and the full JVM test/build/lint stack after making posted notification refund/reversal/chargeback copy parse as income while preserving the from ... counterparty. Runtime storeSafeDebug install was attempted; AtharPixelQaApi35 exited before exposing an online ADB device with Windows access-violation code -1073741819 under both bounded -gpu swiftshader_indirect and -gpu off software launches, so install/screenshot/logcat capture could not run, and cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ✅ The scoped dev/notification-atm-withdrawal-guards branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, git diff --check, and the full JVM test/build/lint stack after normalizing ATM/cash-withdrawal notification rows to ATM Withdrawal and ignoring withdrawal-limit notices with amounts. Runtime storeSafeDebug install was attempted; AtharPixelQaApi35 stayed emulator-5554 offline for the bounded software launch, so install/screenshot/logcat capture could not run. The stale qemu process and AVD locks were cleaned afterward, leaving no attached ADB device and no emulator/qemu/netsim process.

  • ✅ The scoped dev/notification-bank-fee-guards branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, git diff --check, and the full JVM test/build/lint stack after normalizing posted bank-fee notification rows to Bank fees and ignoring fee-schedule/tariff notices with amounts. Runtime storeSafeDebug install was attempted; AtharPixelQaApi35 exited before exposing an online ADB device with Windows access-violation code -1073741819, so install/screenshot/logcat capture could not run, and cleanup finished with no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ⏳ Device E2E, screenshot UI audit, and notification tap-through still need a physical Android device or a working accelerated emulator. On 2026-06-14 AtharPixelQaApi35 emitted software-boot logs but exited before exposing ADB, later W-09 retries crashed before ADB, the G-11 balance retry left only an offline ADB transport, the G-11 discount-guard and reward-guard retries stayed offline after stale-lock cleanup, the G-11 security-code retry emitted boot logs without an online ADB device, the G-11 authorization-hold, balance-only, credit-state, admin-notice, spending-summary, and parser-registry retries crashed before ADB after Failed to load opengl32sw, the global-common seed retry either stayed without online ADB under software boot or exited because x86_64 emulation requires hardware acceleration, the R-15 admin-ignore retry and R-16 electronic-payment retry stayed without online ADB under -accel off, the R-05 post-R16 audit retry stayed emulator-5554 offline under -accel off, the S-21 diagnostics and R-07 backlog-context retries exited before ADB with -1073741819, the R-07 category-options, R-07 category-value-normalization, R-17 missing-merchant-shapes, and R-18 uncategorized-groups retries stayed emulator-5554 offline under -accel off, the latest R-07 group-impact, import-preview, import-impact-summary, G-8 receipt-text-prefill, and G-8 receipt-image-ocr retries exited with code 1 because the Android Emulator hypervisor driver is not installed and x86_64 emulation requires hardware acceleration, and AtharPixelQaApi35Arm exits because arm64 system images are not supported by this x86_64 host, preventing install, launch, screenshots, and tap-through.

  • ⏳ The latest R-18 private-audit-root-report runtime retry also could not install or launch on 2026-06-14: the built personalFullSmsDebug APK was ready, but AtharPixelQaApi35 exited before exposing ADB because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed; AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Runtime evidence was written to build/qa/private-audit-root-report-emulator/, and the stale AVD lock was removed after confirming no emulator/qemu process was running.

  • ⏳ The latest R-07 group-import runtime retry also could not install or launch on 2026-06-14: AtharPixelQaApi35 exited before exposing ADB with Windows access-violation code -1073741819 after stale-lock cleanup.

  • ⏳ The latest R-07 exact-import-rules runtime retry also could not install or launch on 2026-06-14: AtharPixelQaApi35 briefly exposed only emulator-5554 offline, then exited before ADB with Windows access-violation code -1073741819; stale AVD locks were cleaned.

  • ⏳ The latest R-07 type-safe-import runtime retry also could not install or launch on 2026-06-14: the built personalFullSmsDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 reached only emulator-5554 offline; stuck qemu/ADB processes were stopped, AVD locks were removed, and final cleanup had no attached ADB device and no emulator/qemu/netsim process.

  • ⏳ The latest R-07 skip-breakdown runtime retry also could not install or launch on 2026-06-14: the built personalFullSmsDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline for the bounded software launch; install/screenshot/logcat capture could not run, and final cleanup had no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ⏳ The latest R-07 copy-prompt runtime retry also could not install or launch on 2026-06-14: the built personalFullSmsDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline for the bounded software launch; install/screenshot/logcat capture could not run, stale AVD locks were removed, and final cleanup had no attached ADB device and no emulator/qemu/netsim process.

  • ⏳ The latest G-11 trailing-party-hints runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 briefly exposed only emulator-5554 offline, then exited before install with Windows access-violation code -1073741819; stale AVD locks were cleaned.

  • ⏳ The latest G-11 regional-currency-symbols runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 exited before exposing ADB with Windows access-violation code -1073741819; stale AVD locks were cleaned and ADB was restarted.

  • ⏳ The latest G-11 balance-after-extraction runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 exited after 2 seconds with Windows access-violation code -1073741819; stale AVD locks were cleaned and ADB was restarted.

  • ⏳ The latest G-11 refund/reversal-income runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 exited before exposing an online ADB device with Windows access-violation code -1073741819 under both -gpu swiftshader_indirect and -gpu off software launches; stale AVD locks were cleaned.

  • ⏳ The latest G-11 ATM-withdrawal runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 stayed emulator-5554 offline for the bounded software launch; the stale qemu process and AVD locks were cleaned.

  • ⏳ The latest G-11 bank-fee runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 exited before exposing an online ADB device with Windows access-violation code -1073741819; stale AVD locks were cleaned.

  • ⏳ The latest G-11 POS-transaction-phrases runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline during the bounded software launch; install/screenshot/logcat capture could not run, and cleanup finished with no adb/emulator/qemu/netsim process and no AVD locks.

  • ⏳ The latest G-11 location-labels runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline during the bounded software launch; install/screenshot/UI-dump/logcat capture could not run, and cleanup finished with no adb/emulator/qemu/netsim process and no AVD locks.

  • ⏳ The latest G-11 payment-request-guards runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline during the bounded software launch; install/screenshot/UI-dump/logcat capture could not run, and cleanup finished with no adb/emulator/qemu/netsim process and no AVD locks.

  • ⏳ The latest G-11 status-prefix merchant-hints runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline during the bounded software launch; install/screenshot/UI-dump/logcat capture could not run, the new emulator/qemu processes and stale AVD locks were cleaned, and post-inspection cleanup finished with no adb/emulator/qemu/netsim process and no AVD locks.

  • ⏳ The latest G-11 recipient-label-hints runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline during the bounded software launch; install/screenshot/UI-dump/logcat capture could not run, the new emulator/qemu processes and stale AVD locks were cleaned, and post-inspection cleanup finished with no adb/emulator/qemu/netsim process and no AVD locks.

  • ⏳ The latest G-11 card-used merchant-hints runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35Arm is unsupported on this x86_64 host, a visible x86 software launch opened an emulator crash dialog, and the cleaned headless x86 software launch stayed emulator-5554 offline through the bounded wait; install/screenshot/UI-dump/logcat capture could not run, stale AVD locks were cleaned, and final cleanup had no adb/emulator/qemu/netsim process and no AVD locks.

  • ⏳ The latest G-11 card-used-at merchant-hints runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 emitted startup logs then exited before an online ADB device appeared; install/screenshot/UI-dump/logcat capture could not run, stale AVD locks were cleaned, and final cleanup had no adb/emulator/qemu/netsim process and no AVD locks.

  • ⏳ The latest G-11 life-admin-labels runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 exited before exposing ADB because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed; AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Runtime evidence was written to build/qa/notification-life-admin-labels-emulator/.

  • ⏳ The latest G-11 car-maintenance-labels runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 exited before exposing ADB because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed; AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Runtime evidence was written to build/qa/notification-car-maintenance-labels-emulator/.

  • ⏳ The latest G-11 car-payment-labels runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 exited before exposing ADB because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed; AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Runtime evidence was written to build/qa/notification-car-payment-labels-emulator/.

  • ⏳ The latest G-11 mortgage-payment-labels runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 exited before exposing ADB because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed; AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Runtime evidence was written to build/qa/notification-mortgage-payment-labels-emulator/.

  • ⏳ The latest G-11 gift-payment-labels runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 exited before exposing ADB because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed; AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Runtime evidence was written to build/qa/notification-gift-payment-labels-emulator/.

  • ⏳ The latest G-11 home-goods-labels runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 exited before exposing ADB because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed; AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Runtime evidence was written to build/qa/notification-home-goods-labels-emulator/.

  • ✅ The scoped dev/notification-income-labels branch passes focused parser and seed tests, git diff --check, and the full JVM/debug-APK/lint stack after normalizing posted tax refund, expense reimbursement/refund/reversal/chargeback, and bonus income notification rows to exact seed-backed income labels, ignoring estimate/claim/promo copy with amounts, and raising the active seed to 710 rules.

  • ⏳ The latest G-11 income-labels runtime retry also could not install or launch on 2026-06-15: the built APKs were ready, but AtharPixelQaApi35 exited before exposing ADB because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed; AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host. Runtime evidence was written to build/qa/notification-income-labels-emulator/.

  • ✅ The scoped dev/notification-work-expense-labels branch passes focused parser and seed tests, git diff --check, and the full JVM/debug-APK/lint stack after normalizing posted work/business expense and office-supplies purchase notification rows to exact seed-backed work-expense labels, ignoring claim/report/quote/offer/cart/shipping/order-status copy with amounts, and raising the active seed to 714 rules.

  • ⏳ The latest G-11 work-expense-labels runtime retry also could not install or launch on 2026-06-15: the built APKs were ready, but AtharPixelQaApi35 exited before exposing ADB because x86_64 emulation requires hardware acceleration and the Android Emulator hypervisor driver is not installed; AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/notification-work-expense-labels-emulator/.

  • ✅ The scoped dev/notification-side-income-labels branch passes focused parser and seed tests and the full JVM/debug-APK/lint stack after normalizing posted freelance, rental, dividend, and interest income notification rows to exact seed-backed side-income labels, ignoring invoice/estimate/projection/rate/announcement copy with amounts, and raising the active seed to 722 rules.

  • ⏳ The latest G-11 side-income-labels runtime retry also could not install or launch on 2026-06-15: the built APKs were ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exited with Windows access-violation code -1073741819, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/notification-side-income-labels-emulator/.

  • ✅ The scoped dev/notification-cashback-income-labels branch passes focused parser and seed tests, git diff --check, and the full JVM/debug-APK/lint stack after normalizing posted cashback credits to exact seed-backed English/Arabic side-income labels, preserving named reward sources, keeping cashback offers ignored, and raising the active seed to 724 rules.

  • ⏳ The latest G-11 cashback-income-labels runtime retry also could not install or launch on 2026-06-15: the built APKs were ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exited before install because x86_64 emulation requires hardware acceleration, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/notification-cashback-income-labels-emulator/.

  • ✅ The scoped dev/notification-deposit-income-labels branch passes focused parser and seed tests, git diff --check, and the full JVM/debug-APK/lint stack after normalizing posted cash, ATM, check, and cheque deposits to exact seed-backed Other income labels, ignoring deposit limits/holds/pending/fee/rate notices with amounts, and raising the active seed to 729 rules.

  • ⏳ The latest G-11 deposit-income-labels runtime retry also could not install or launch on 2026-06-15: the built APKs were ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exited before install because x86_64 emulation requires hardware acceleration, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/notification-deposit-income-labels-emulator/.

  • ✅ The scoped dev/support-diagnostics-backlog-recommendations branch passes focused support diagnostics tests, git diff --check, and the full JVM/debug-APK/lint stack after adding a redacted category_backlog_recommendation block to athar-support-diagnostics.json. The recommendation derives only from aggregate backlog size and hashed repeated-group sizes, so support can suggest History repeated cleanup, bulk CSV categorization, small manual cleanup, or no action without raw merchants, amounts, notes, SMS bodies, or transaction rows.

  • ⏳ The latest S-21 backlog-recommendations runtime retry also could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exited before install because x86_64 emulation requires hardware acceleration, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/support-diagnostics-backlog-recommendations-emulator/.

  • ✅ The scoped dev/bulk-categorize-specific-merchant-guards branch passes focused bulk CSV tests, focused bulk AI prompt tests, git diff --check, and the full JVM/debug-APK/lint stack after making generic merchant labels such as payment, purchase, cash, merchant, and bank row-by-row only in the bulk categorization workflow. Explicit filled generic rows still update, but generic keys no longer get repeated-group ranks, propagate categories to blank peers, or train exact local rules.

  • ⏳ The latest R-07 specific-merchant-guards runtime retry also could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exited before install because x86_64 emulation requires hardware acceleration, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/bulk-categorize-specific-merchant-guards-emulator/.

  • ✅ The scoped dev/shared-specific-merchant-guard branch passes focused domain/data/Today/History tests, git diff --check, and the full JVM/debug-APK/lint stack after moving the specific-merchant guard into core:domain and sharing it across bulk categorization, Today suggestions, History repeated-backlog cleanup, and local auto-learning. Generic English/Arabic labels such as payment, cash, bank, كاش, and دفع stay row-by-row and cannot drive suggestions, repeated groups, inherited bulk rows, or exact local rules.

  • ⏳ The latest R-07 shared-specific-merchant runtime retry also could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exited after 5 seconds because x86_64 emulation requires hardware acceleration, AtharPixelQaApi35Arm exited after 5 seconds because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/shared-specific-merchant-guard-emulator/.

  • ✅ The scoped dev/support-diagnostics-specific-merchant-guard branch passes focused support diagnostics tests, git diff --check, and the full JVM/debug-APK/lint stack after making support diagnostics reuse the shared specific-merchant guard. Repeated generic labels now count toward total category backlog but no longer produce hashed repeated groups or trigger History repeated-backlog recommendations.

  • ⏳ The latest S-21 diagnostics-specific-merchant runtime retry also could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exited after 5 seconds because x86_64 emulation requires hardware acceleration, AtharPixelQaApi35Arm exited after 5 seconds because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/support-diagnostics-specific-merchant-guard-emulator/.

  • ✅ The scoped dev/community-rules-specific-merchant-guard branch passes focused community-rule exporter tests, git diff --check, and the full JVM/debug-APK/lint stack after making Settings' "Help others · share your rules" export reuse the shared specific-merchant guard. Legacy explicit substring rules for generic labels such as payment, cash, bank, كاش, and دفع now stay local instead of becoming public seed proposals.

  • ⏳ The latest community-rules-specific-merchant runtime retry also could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exited before install because x86_64 emulation requires hardware acceleration, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/community-rules-specific-merchant-guard-emulator/.

  • ✅ The scoped dev/seed-rules-specific-merchant-pattern-types branch passes focused SeedRulesAssetTest, git diff --check, and the full JVM/debug-APK/lint stack after adding optional seed-rule patternType, keeping merchant seeds as substring by default, and making generic-prefix shared labels such as cash deposit, bank fees, and كاش باك بطاقة ائتمانية exact matches. Asset tests now reject future generic-prefix substring seeds, and the AI merge script preserves existing exact seed rows.

  • ⏳ The latest seed-rules-specific-merchant runtime retry also could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exited before install because x86_64 emulation requires hardware acceleration, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/seed-rules-specific-merchant-pattern-types-emulator/.

  • ✅ The scoped dev/seed-rules-content-refresh branch passes focused RuleSeedRefreshTest/SeedRulesAssetTest, git diff --check, and the full JVM/debug-APK/lint stack after making startup seed refresh compare bundled signatures (pattern, patternType, categoryId, priority) instead of only row count. Existing installs now receive metadata-only seed updates, while user-learned and auto-local-* rules stay local and outside the refresh/delete path.

  • ⏳ The latest seed-rules-content-refresh runtime retry also could not install or launch on 2026-06-15: the built personalFullSmsDebug and storeSafeDebug APKs were ready, emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exited with code 1 because x86_64 emulation requires hardware acceleration, AtharPixelQaApi35Arm exited with code 1 because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/seed-rules-content-refresh-emulator/; cleanup left no emulator/qemu/adb/netsim process and no AVD lock files.

  • ✅ The scoped dev/bulk-ai-prompt-label-guidance branch passes focused MerchantBulkAiPromptTest, git diff --check, and the full JVM/debug-APK/lint stack after adding seed-backed label guidance to the copied external-AI bulk categorization prompt. The prompt now maps common normalized labels such as ATM Withdrawal, Bank fees, mobile recharge, tax refunds, reimbursements, cashback, deposits, work expenses, life-admin, shopping, travel, and event tickets to the right category ids while preserving the same reviewed CSV import contract.

  • ⏳ The latest bulk-ai-prompt-label-guidance runtime retry also could not install or launch on 2026-06-15: the built personalFullSmsDebug and storeSafeDebug APKs were ready, emulator -accel-check reported the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exited with code 1 because x86_64 emulation requires hardware acceleration, AtharPixelQaApi35Arm exited with code 1 because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/bulk-ai-prompt-label-guidance-emulator/; cleanup left no emulator/qemu/adb/netsim process and no AVD lock files.

  • ✅ The scoped dev/private-audit-backlog-recommendation branch passes focused PrivateSmsExportAuditTest, git diff --check, and the full JVM/debug-APK/lint stack after adding a redacted categoryBacklogRecommendation block to the gated private-corpus audit. The forced root report still writes 0 raw bodies and now recommends history_repeated_backlog first plus bulk_categorize_export second from aggregate-only evidence: 1,087 uncategorized parsed expenses, largest hashed group 55, and top-20 hashed groups covering 184 rows.

  • ⏳ The latest private-audit-backlog-recommendation runtime retry also could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed, the x86 AtharPixelQaApi35 software launch exposed only emulator-5554 offline, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and no online ADB device appeared. Runtime evidence was written to build/qa/private-audit-backlog-recommendation-emulator/; cleanup stopped the leftover qemu process and removed stale AVD locks.

  • ✅ The scoped dev/today-repeated-backlog-nudge branch passes focused Today/History tests, git diff --check, and the full JVM/debug-APK/lint stack after making Today surface repeated specific uncategorized groups as an aggregate-only nudge. Tapping it opens History with Repeated backlog selected and selection mode active so the existing top-group/safe-group cleanup controls are immediately available; generic labels such as payment, cash, bank, كاش, and دفع still cannot trigger repeated-cleanup shortcuts.

  • ⏳ The latest Today repeated-backlog runtime retry also could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed, the x86 AtharPixelQaApi35 launch exited before exposing an online ADB device with code -1073741819, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/today-repeated-backlog-nudge-emulator/; cleanup removed stale AVD locks and left no emulator/qemu/netsim/adb process.

  • ✅ The scoped dev/wishlist-reconciliation-capacity branch passes focused WishlistCalcTest, Plan feature compilation, git diff --check, and the full JVM/debug-APK/lint stack after making Wishlist monthly capacity ignore balance reconciliation adjustments. The calculation now uses confirmed operating income/expense only, so manual account-balance corrections still affect net worth without making Wishlist projections falsely infeasible or overly generous.

  • ⏳ The latest Wishlist reconciliation-capacity runtime retry also could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed, the x86 AtharPixelQaApi35 launch stayed without an ADB transport during the bounded window and opened emulator crash-consent logging, AtharPixelQaApi35Arm exited because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/wishlist-reconciliation-capacity-emulator/; cleanup stopped the leftover qemu process and removed stale AVD locks.

  • ✅ The scoped dev/widgets-localized-copy branch passes focused widget compilation, git diff --check, and the full JVM/debug-APK/lint stack after making Month, Today, and Pending widget body/action copy resolve from Arabic/English resources using Athar's saved app-language preference. Widget launches, actions, refresh behavior, and data calculations are unchanged.

  • ⏳ The latest widget-localized-copy runtime retry also could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed, the x86 AtharPixelQaApi35 launch exited before exposing an online ADB device with code 1 because x86_64 emulation requires hardware acceleration, AtharPixelQaApi35Arm exited with code 1 because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/widgets-localized-copy-emulator/; cleanup removed the target AVD lock and left no attached ADB device.

  • ✅ The scoped dev/widget-preference-refresh branch passes focused core-data/app Hilt compilation, git diff --check, and the full JVM/debug-APK/lint stack after making real app-language or display-currency preference changes request the existing debounced widget refresh. Re-saving the same value stays a no-op, and widget data/actions remain unchanged.

  • ⏳ The latest widget preference-refresh runtime retry also could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed, the x86 AtharPixelQaApi35 launch exited before exposing an online ADB device with code 1 because x86_64 emulation requires hardware acceleration, AtharPixelQaApi35Arm exited with code 1 because arm64 system images are unsupported on this x86_64 host, and final adb devices listed no attached devices. Runtime evidence was written to build/qa/widget-preference-refresh-emulator/; cleanup removed the target AVD lock and left no attached ADB device.

  • ✅ The scoped dev/notification-insurance-nonposted-guards branch passes focused GenericBankNotificationTemplateTest, git diff --check, and the full JVM/debug-APK/lint stack after ignoring insurance/policy-premium quote, offer, and estimate notifications with amounts while keeping posted premium payments and named insurers on the existing Insurance premium path.

  • ⏳ The latest insurance non-posted runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, but adb devices -l listed no connected devices, where emulator could not find an Android emulator executable in this resumed shell, and :app:installStoreSafeDebug failed with No connected devices!. Evidence was written to build/qa/notification-insurance-nonposted-guards-emulator/.

  • ✅ The scoped dev/notification-subscription-rent-nonposted-guards branch passes focused GenericBankNotificationTemplateTest, git diff --check, and the full JVM/debug-APK/lint stack after ignoring subscription, membership, recurring-payment, and rent-payment offer/quote/discount notifications with amounts while keeping posted subscription and rent payments on their existing shared labels.

  • ⏳ The latest subscription/rent non-posted runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, but adb devices -l listed no connected devices, where emulator could not find an Android emulator executable in this resumed shell, and :app:installStoreSafeDebug failed with No connected devices!. Evidence was written to build/qa/notification-subscription-rent-nonposted-guards-emulator/.

  • ✅ The scoped dev/notification-essential-life-nonposted-guards branch passes focused GenericBankNotificationTemplateTest, git diff --check, and the full JVM/debug-APK/lint stack after ignoring medical, pharmacy, education, and Arabic school-fee quote/estimate/status notifications with amounts while keeping posted essential-life payments on their existing shared labels.

  • ⏳ The latest essential-life non-posted runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, but adb devices -l listed no connected devices, where emulator could not find an Android emulator executable in this resumed shell, and :app:installStoreSafeDebug failed with No connected devices!. Evidence was written to build/qa/notification-essential-life-nonposted-guards-emulator/.

  • ✅ The scoped dev/notification-public-mobility-nonposted-guards branch passes focused GenericBankNotificationTemplateTest, git diff --check, and the full JVM/debug-APK/lint stack after ignoring public-service and mobility quote, estimate, offer, discount, status, application, appointment, and reservation notifications with amounts while keeping posted traffic-fine, government-service, parking, toll, and transit payments on their existing shared labels.

  • ⏳ The latest public-service/mobility non-posted runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, adb devices -l listed no connected devices, emulator -list-avds found AtharPixelQaApi35 and AtharPixelQaApi35Arm, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, and a bounded hidden AtharPixelQaApi35 launch exited with Windows access-violation code -1073741819 before an online ADB device appeared. :app:installStoreSafeDebug failed with No connected devices!, and evidence was written to build/qa/notification-public-mobility-nonposted-guards-emulator/.

  • ✅ The scoped dev/notification-recurring-merchant-renewal branch passes focused GenericBankNotificationTemplateTest, parser/listener module tests, git diff --check, and the full JVM/debug-APK/lint stack after parsing posted subscription or membership renewal notifications, preserving named merchants such as Netflix/Spotify, and keeping future renewal reminders ignored.

  • ⏳ The latest notification recurring-renewal runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, and a bounded hidden AtharPixelQaApi35 software launch exposed only emulator-5554 offline through the wait window. :app:installStoreSafeDebug skipped the offline device and failed with No online devices found; cleanup stopped the emulator/qemu children, ran adb reconnect offline, and ended with no attached devices. Evidence was written to build/qa/notification-recurring-merchant-renewal-emulator/.

  • ✅ The scoped dev/notification-processed-settled-merchant-hints branch passes focused GenericBankNotificationTemplateTest, parser/listener module tests, git diff --check, and the full JVM/debug-APK/lint stack after preserving merchants from posted Payment processed:, Transaction settled -, and Purchase processed: notification copy.

  • ⏳ The latest notification processed/settled runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, and bounded hidden AtharPixelQaApi35 software launches either exposed only emulator-5554 offline or no ADB transport before the wait window ended. :app:installStoreSafeDebug failed with No connected devices!; cleanup ran adb reconnect offline and ended with no attached devices. Evidence was written to build/qa/notification-processed-settled-merchant-hints-emulator/.

  • ✅ The scoped dev/notification-title-merchant-hints branch passes focused GenericBankNotificationTemplateTest, parser/listener module tests, git diff --check, and the full JVM/debug-APK/lint stack after preserving merchant titles from posted multi-line notification payloads such as Noon\nCard purchase..., Carrefour\nAED..., and Toast Box\nPurchase processed... while rejecting bank-app titles such as Wise as merchants.

  • ⏳ The latest notification title-merchant runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, adb devices stayed empty through the wait window, and :app:installStoreSafeDebug failed with No connected devices!. Cleanup ended with no attached devices and no emulator/qemu/netsim process. Evidence was written to build/qa/notification-title-merchant-hints-emulator/.

  • ✅ The scoped dev/notification-body-line-merchant-hints branch passes focused GenericBankNotificationTemplateTest, parser/listener module tests, git diff --check, and the full JVM/debug-APK/lint stack after preserving merchant body lines after posted amount/title lines such as Card purchase SAR 99.00\nNoon and AED 42.00 card transaction settled\nCarrefour while rejecting bank-app lines such as Wise as merchants.

  • ⏳ The latest notification body-line merchant runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, adb devices stayed empty through the wait window, and :app:installStoreSafeDebug failed with No connected devices!. Cleanup ended with no attached devices and no emulator/qemu/netsim process. Evidence was written to build/qa/notification-body-line-merchant-hints-emulator/.

  • ✅ The scoped dev/notification-label-line-merchant-hints branch passes focused GenericBankNotificationTemplateTest, parser/listener module tests, git diff --check, and the full JVM/debug-APK/lint stack after skipping label-only merchant/location body lines and preserving the following real merchant line, such as Card purchase SAR 99.00\nMerchant\nNoon.

  • ⏳ The latest notification label-line merchant runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 stayed emulator-5554 offline through the wait window, and :app:installStoreSafeDebug skipped the offline device and failed with No online devices found. Cleanup stopped emulator/qemu children and ended with no attached devices. Evidence was written to build/qa/notification-label-line-merchant-hints-emulator/.

  • ✅ The scoped dev/notification-digit-start-merchant-hints branch passes focused GenericBankNotificationTemplateTest, parser/listener module tests, git diff --check, and the full JVM/debug-APK/lint stack after preserving digit-starting merchants such as 7-Eleven and 6th Street in title-first, body-line, and trailing amount notification hints while keeping numeric-only body lines merchantless.

  • ⏳ The latest notification digit-start merchant runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 stayed emulator-5554 offline through the wait window, and :app:installStoreSafeDebug skipped the offline device and failed with No online devices found. Cleanup stopped emulator/qemu children and ended with no attached devices. Evidence was written to build/qa/notification-digit-start-merchant-hints-emulator/.

  • ✅ The scoped dev/notification-digit-hint-merchant-fields branch passes focused GenericBankNotificationTemplateTest, parser/listener module tests, git diff --check, and the full JVM/debug-APK/lint stack after preserving digit-starting merchants from explicit hints such as at 7-Eleven, Merchant: 7-Eleven, and Payment to 3M while keeping numeric-only structured fields merchantless.

  • ⏳ The latest notification digit-hint merchant runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, no online ADB device appeared, and :app:installStoreSafeDebug failed with No connected devices!. Cleanup ended with no attached devices and no emulator/qemu/netsim process. Evidence was written to build/qa/notification-digit-hint-merchant-fields-emulator/.

  • ✅ The scoped dev/notification-digit-counterparty-hints branch passes focused GenericBankNotificationTemplateTest, parser/listener module tests, git diff --check, and the full JVM/debug-APK/lint stack after preserving digit-starting income and transfer counterparties such as 3M Payroll paid you, Sender: 3M Payroll, and Recipient: 401K Savings while keeping numeric-only counterparties rejected.

  • ⏳ The latest notification digit-counterparty runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 stayed emulator-5554 offline through the bounded wait, and :app:installStoreSafeDebug skipped the offline device and failed with No online devices found. Cleanup stopped the emulator/qemu children and ended with no attached devices and no emulator/qemu/netsim process. Evidence was written to build/qa/notification-digit-counterparty-hints-emulator/.

  • ✅ The scoped dev/notification-party-stopword-suffixes branch passes focused GenericBankNotificationTemplateTest, parser/listener module tests, git diff --check, and the full JVM/debug-APK/lint stack after preserving merchant names that start with cleanup words such as Card Factory and Via Roma Cafe while still stripping payment suffixes such as with Apple Pay, via Apple Pay, and using card ending 1234.

  • ⏳ The latest notification party-stopword runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, AtharPixelQaApi35 exposed no ADB device through the bounded wait, and :app:installStoreSafeDebug failed with No connected devices!. Cleanup ended with no attached devices and no emulator/qemu/netsim process. Evidence was written to build/qa/notification-party-stopword-suffixes-emulator/.

  • ✅ The scoped dev/notification-at-symbol-merchant-hints branch passes focused GenericBankNotificationTemplateTest, parser/listener module tests, git diff --check, and the full JVM/debug-APK/lint stack after normalizing at-symbol merchant hints such as USD 8.50 @ Starbucks, Card purchase SAR 18.00 @ 7-Eleven, and Purchase @Starbucks USD 8.50 approved while keeping numeric-only @ 123456789 values rejected.

  • ⏳ The latest notification at-symbol runtime attempt could not install or launch on 2026-06-15: the built storeSafeDebug APK was ready, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, bounded hidden AtharPixelQaApi35 launch exited before exposing an online ADB device because x86_64 emulation requires hardware acceleration, and :app:installStoreSafeDebug failed with No connected devices!. Cleanup ended with no attached devices and no emulator/qemu/netsim process. Evidence was written to build/qa/notification-at-symbol-merchant-hints-emulator/.

  • ✅ The scoped dev/recurring-suggestion-category-defaults branch passes focused RecurringSuggestionRepositoryImplTest/RecurringRulesViewModelTest, git diff --check, and the full JVM/debug-APK/lint stack after carrying a safe recurring-suggestion category only when every detected occurrence already used the same category, preselecting that category in the confirm sheet, and preserving it when the suggestion is accepted without an override.

  • ⏳ The latest recurring-suggestion category-default runtime attempt could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, adb devices -l initially listed no connected devices, emulator -list-avds found AtharPixelQaApi35 and AtharPixelQaApi35Arm, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, and a bounded hidden AtharPixelQaApi35 launch exposed only emulator-5554 offline for the full wait window. :app:installPersonalFullSmsDebug skipped the offline device and failed with No online devices found; cleanup restarted ADB and ended with no attached devices. Evidence was written to build/qa/recurring-suggestion-category-defaults-emulator/.

  • ✅ The scoped dev/recurring-suggestion-account-defaults branch passes focused RecurringSuggestionRepositoryImplTest/RecurringRulesViewModelTest, git diff --check, and the full JVM/debug-APK/lint stack after carrying a safe recurring-suggestion account only when every detected occurrence already used the same account and preserving the existing manual-account fallback for mixed history.

  • ⏳ The latest recurring-suggestion account-default runtime attempt could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, adb devices -l initially listed no connected devices, emulator -list-avds found AtharPixelQaApi35 and AtharPixelQaApi35Arm, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, the first bounded hidden AtharPixelQaApi35 launch exposed no ADB transport, and a short retry exposed only emulator-5554 offline. :app:installPersonalFullSmsDebug failed with No connected devices; cleanup stopped emulator/qemu/netsim children, restarted ADB, and ended with no attached devices. Evidence was written to build/qa/recurring-suggestion-account-defaults-emulator/.

  • ✅ The scoped dev/recurring-rule-account-picker branch passes focused RecurringRulesViewModelTest, git diff --check, and the full JVM/debug-APK/lint stack after adding active-account selection to manual recurring rule creation and suggestion confirmation. Explicit user account choice wins over safe inferred suggestion defaults, with the manual-account fallback preserved for empty account state.

  • ⏳ The latest recurring-rule account-picker runtime attempt could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, emulator -list-avds found AtharPixelQaApi35 and AtharPixelQaApi35Arm, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, and a bounded hidden AtharPixelQaApi35 launch exposed only emulator-5554 offline through the wait window. :app:installPersonalFullSmsDebug skipped the offline device and failed with No online devices found; cleanup stopped emulator/qemu children, restarted ADB, and ended with no attached devices. Evidence was written to build/qa/recurring-rule-account-picker-emulator/.

  • ✅ The scoped dev/recurring-rule-routing-editor branch passes focused RecurringRulesViewModelTest, settings feature compilation, git diff --check, and the full JVM/debug-APK/lint stack after showing account/category on recurring rule rows and adding a bottom-sheet editor that updates only existing rule routing fields.

  • ⏳ The latest recurring-rule routing-editor runtime attempt could not install or launch on 2026-06-15: the built personalFullSmsDebug APK was ready, emulator -accel-check reported that the Android Emulator hypervisor driver is not installed, and a bounded hidden AtharPixelQaApi35 launch with software acceleration exposed only emulator-5554 offline through the wait window. :app:installPersonalFullSmsDebug skipped the offline device and failed with No online devices found; cleanup stopped emulator/qemu children, restarted ADB, and ended with no attached devices. Evidence was written to build/qa/recurring-rule-routing-editor-emulator/.

  • ⏳ The latest TMOAP category parity runtime retry also could not install or launch on 2026-06-14: the built personalFullSmsDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and two bounded hidden AtharPixelQaApi35 software launches (-gpu swiftshader_indirect -accel off and -gpu off -accel off) exited after 4 seconds with Windows access-violation code -1073741819. Runtime evidence was written to build/qa/tmoap-category-parity-emulator/ and build/qa/tmoap-category-parity-emulator-gpu-off/, and final cleanup left no attached ADB device, no emulator/qemu/netsim process, and no AVD lock files.

  • ✅ The scoped dev/notification-debt-payment-labels branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after normalizing posted credit-card repayment and loan-instalment notification rows to shared debt labels, ignoring repayment reminders with amounts, and preventing card/account identifier numbers from winning amount selection. Runtime storeSafeDebug install was attempted; AtharPixelQaApi35 stayed emulator-5554 offline for the bounded software launch, so install/screenshot/logcat capture could not run. The new emulator/qemu processes and stale AVD locks were cleaned afterward, leaving no attached ADB device, no emulator/qemu/netsim process, and no AVD locks.

  • ⏳ The latest G-11 debt-payment runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 stayed emulator-5554 offline for 185 seconds under the bounded software launch; the new emulator/qemu processes and stale AVD locks were cleaned.

  • ✅ The scoped dev/notification-utility-bill-labels branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after normalizing generic electricity, water, and bill-payment notification rows to shared utility labels while preserving specific billers and ignoring utility bill reminders with amounts. Runtime storeSafeDebug install was attempted; AtharPixelQaApi35 stayed emulator-5554 offline for the bounded software launch, so install/screenshot/logcat capture could not run. The stuck emulator/qemu/netsim processes and stale AVD locks were cleaned afterward.

  • ⏳ The latest G-11 utility-bill runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 stayed emulator-5554 offline until the boot window timed out; emulator/qemu/netsim processes and stale AVD locks were cleaned.

  • ✅ The scoped dev/notification-salary-income-labels branch passes :ingestion:sms-parser:test, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after normalizing explicit salary/payroll income notification rows to shared salary labels while preserving payroll sources and ignoring salary-transfer financing offers with amounts. Runtime storeSafeDebug install was attempted; AtharPixelQaApi35 exposed only emulator-5554 offline, so install/screenshot/logcat capture could not run. The stuck emulator/qemu/netsim processes and stale AVD locks were cleaned afterward.

  • ⏳ The latest G-11 salary-income runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but AtharPixelQaApi35 exposed only emulator-5554 offline under the bounded software launch; emulator/qemu/netsim processes and stale AVD locks were cleaned.

  • ✅ The scoped dev/notification-recurring-expense-labels branch passes :ingestion:sms-parser:test, :core:data:testDebugUnitTest, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after normalizing posted subscription-payment, insurance-premium, and rent-payment notification rows to exact seed-backed labels, preserving specific insurers, ignoring recurring-expense reminders with amounts, and raising the active seed to 712 rules.

  • ⏳ The latest G-11 recurring-expense runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline during the bounded software launch; install/screenshot/logcat capture could not run, and emulator/qemu/netsim processes plus AVD locks were cleaned.

  • ✅ The scoped dev/notification-telecom-recharge-labels branch passes :ingestion:sms-parser:test, :core:data:testDebugUnitTest, :ingestion:notification-listener:test, and the full JVM test/build/lint stack after treating mobile/prepaid/airtime top-up notifications as telecom expenses, preserving carrier merchants, keeping non-telecom wallet top-ups as income, ignoring recharge promos with amounts, and raising the active seed to 713 rules.

  • ⏳ The latest G-11 telecom-recharge runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and AtharPixelQaApi35 stayed emulator-5554 offline during the bounded software launch; install/screenshot/logcat capture could not run, and emulator/qemu/netsim processes plus AVD locks were cleaned.

  • ✅ The scoped dev/notification-public-service-labels branch passes :ingestion:sms-parser:test, :core:data:testDebugUnitTest, :ingestion:notification-listener:test, git diff --check, and the full JVM test/build/lint stack after normalizing posted traffic-fine and government-service payment notifications to exact seed-backed labels, preserving specific agencies, ignoring public-service due reminders with amounts, avoiding broad fine false positives, and raising the active seed to 715 rules.

  • ⏳ The latest G-11 public-service runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and the bounded hidden AtharPixelQaApi35 software launch exited with Windows access-violation code -1073741819 before exposing an online ADB device; install/screenshot/logcat capture could not run, stale AVD locks were cleaned, and final cleanup had no attached ADB device and no emulator/qemu/netsim process.

  • ✅ The scoped dev/notification-mobility-payment-labels branch passes :ingestion:sms-parser:test, :core:data:testDebugUnitTest, :ingestion:notification-listener:test, git diff --check, and the full JVM test/build/lint stack after normalizing posted parking-payment, toll-payment, and transit-fare notifications to exact seed-backed labels, preserving specific mobility operators, ignoring mobility due/unpaid reminders with amounts, keeping parking fines on the public-service label, and raising the active seed to 718 rules.

  • ⏳ The latest G-11 mobility-payment runtime retry also could not install or launch on 2026-06-14: the built storeSafeDebug APK was ready, but emulator -accel-check reported the Android Emulator hypervisor driver is not installed and the bounded hidden AtharPixelQaApi35 software launch exited with Windows access-violation code -1073741819 before exposing an online ADB device; install/screenshot/logcat capture could not run, stale AVD locks were cleaned, and final cleanup had no attached ADB device and no emulator/qemu/netsim process.

In flight / remaining

ID Feature Status Effort Notes
QA-01 Runtime E2E + UI audit 0.5–1 day Needs physical Android device or accelerated emulator
G-7 Bill reminders Bills calendar + opt-in reminders shipped; runtime notification QA remains under QA-01
G-8 Manual transaction UX upgrades 1.5 days ✅ Recent-merchant autocomplete + quick-add chips · ✅ quick phrase/voice fill · ✅ pasted receipt/OCR-text prefill · ✅ on-device receipt image OCR prefill · ✅ multiple local encrypted receipt attachments · ✅ receipt view/export/remove from edit sheet
G-10 Savings-rate goals + emergency fund Plan → Goals tab plus Today Goals check shipped; device visual QA remains under QA-01
W-09 Wishlist planning summary Remaining backlog, ready-now count, next reachable month, target pressure, and capacity-risk count shipped
W-10 Wishlist reconciliation-safe capacity Balance reconciliation adjustments no longer distort monthly wishlist capacity
R-08 Widget localized copy + preference refresh Month, Today, and Pending widget body/action labels now follow Athar's Arabic/English app-language preference, and widgets refresh after language/display-currency changes; runtime widget visual QA remains under QA-01
G-11 Broader notification handlers 3 days Generic parser, wallet/card phrases, peer-payment/global-currency handlers, regional currency symbols, localized comma-decimal amount parsing, bank-specific card-charge/debit-card merchant extraction, merchant-first charge/card-transaction/POS transaction parsing, status-prefix merchant hints including processed/settled copy, title-first/body-line/label-value/digit-starting multi-line/digit-hint merchant hints, digit-starting income/transfer counterparties, cleanup-safe merchant names such as Card Factory, card-used/card-used-at merchant hints, recurring subscription-renewal merchant preservation, expense recipient/beneficiary merchant hints, amount-adjacent trailing merchant/biller extraction, structured merchant/location/party label-field extraction, balance-aware amount selection, clear balance-after extraction, ATM/bank-fee/debt-payment/utility-bill/salary-income/tax-refund/expense-reimbursement/bonus-income/cashback-income/cash-deposit/check-deposit/side-income/recurring-expense/telecom-recharge/public-service/mobility-payment/essential-life/everyday-commerce/travel/retail-shopping/entertainment/life-admin/car-maintenance/car-payment/mortgage-payment/condo-fees/gift-payment/home-goods shared labels, balance/credit/admin/summary/payment-request ignores, reward/cashback guards, OTP/payment-authorization and authorization-hold ignores, scheduled-payment/repayment-reminder/utility-bill-reminder/recurring-expense-reminder/subscription-rent offer-quote-discount/insurance-premium quote-offer-estimate/telecom-recharge-promo/public-service-reminder/mobility-payment-reminder/public-service-mobility quote-estimate-status-discount/essential-life quote-estimate-status-reminder-appeal/everyday-commerce offer-estimate-reservation-reminder/travel offer-itinerary-reservation-quote-reminder/retail-shopping offer-cart-shipping-status/entertainment promo-showtime-presale-reservation/life-admin offer-quote-reminder/car-maintenance quote-estimate-appointment-reminder/car-payment offer-reminder/mortgage offer-reminder-refinance-estimate/condo-fee due-assessment-reminder/gift promo-balance-reminder-offer/home-goods quote-cart-delivery-install-warranty-offer/salary-transfer-financing-offer/deposit-limit-hold/side-income invoice-estimate-rate/marketing-discount ignores, broader package coverage, and exact ANB gating shipped; more real bank copy remains
G-12 Bank statement / XLSX / CSV / OFX / QFX / MT940 import wizard 3 days XLSX transaction grids, CSV/TSV delimiter + header auto-detect, debit/credit indicator support, duplicate-safe preview/confirm, OFX/QFX, MT940, destination-account selection, manual CSV column mapping, row exclusion, currency review, field-level row editing, per-row account review, and separate TMOAP Budget Targets/Wishlist/Family Investments imports shipped
G-13 Zero-knowledge sync to companion devices 5 days E2E-encrypted via Dropbox / Drive / iCloud / WebDAV / S3 — user holds the key
G-14 Tax-export PDF for accountants 2 days Annual category totals + transaction list in user's locale

Full gap analysis: docs/ROADMAP_GLOBAL.md.

Deferred (technical-debt only)

  • ⏳ TFLite merchant classifier (rule engine handles ~90% of cases)
  • ⏳ Paparazzi snapshot baselines (need to record on a real machine)
  • ⏳ Macrobenchmarks (need a device)

Privacy

Athar makes three commitments (Master Brief §2.2, enforced in ADR-002 + ADR-003):

  1. No cloud transit of financial data without your explicit action. The only data that leaves the device is the AES-256-GCM backup file, which you save where you want.
  2. No ads, partnerships, affiliate links, telemetry, or third-party crash reporting.
  3. No friction that makes you feel bad. No streaks, no shame notifications, no scream red bars.

The DB is encrypted at rest with a 256-bit key resident in AndroidKeyStore. Without the device's secure hardware, the key is undecryptable. See SECURITY.md.

Contributing

PRs welcome. See CONTRIBUTING.md for the workflow and the spec-first loop the codebase was built with. The single source of truth is Athar_Master_Brief.md — please read it before opening a PR that adds a feature.

License

Apache License 2.0. Bank-template strings in ingestion:sms-parser are derived from observed SMS bodies (anonymized) and are released under the same terms.

Credits

Developed by Waleed Alhamedwalhamed.com

Inspired by The Measure of a Plan (TMOAP) budget tracking workbook by Tudor Mihailescu, whose monthly cash-flow + historical-comparison + savings-capacity discipline shaped Athar's Trends and Plan screens. Athar carries that spreadsheet's clarity into a phone that lives in your pocket — and removes the manual data-entry tax that TMOAP, by virtue of being a spreadsheet, can never eliminate.

If you were searching for "TMOAP for mobile", "The Measure of a Plan Android app", "open-source TMOAP", "TMOAP without Excel", "automated budget tracker that replaces my spreadsheet", "privacy-first alternative to YNAB / Mint / Monarch / Copilot", or "Saudi / Gulf / Middle East budget app with SMS reading" — Athar is the project you're looking for.


Built one disciplined wave at a time. The Excel sheet retires when Athar ships its v1.0.

About

أثر · Athar — local-first Android personal finance app that reads bank SMS, auto-categorizes against a Saudi merchant dictionary, replaces a complex Excel budget workbook with three calm screens. No cloud, no ads, no telemetry.

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages