Przejdź do treści głównej
Dziennik zmian

Dziennik zmian

Zobacz, co nowego w etappi.

Android 1.11.0 — 2026-08-12 (versionCode 14)

  • Features
    • web: say tax is added at checkout on every pre-checkout price (efc40a0)
    • api: report-only Paddle drift probe in the reconcile cron (faeb845)
    • mobile: arm PostHog key for store builds (331a247)
    • i18n: drop e2ee copy and reword the offline-first pitch (8fa6459)
    • db: drop e2ee schema in migration 0083 (39542fa)
    • web: split retention by early feature adoption (72faf3d)
    • web: add feature adoption to growth board (25d751f)
    • db: add feature-adoption growth report (ff8cd7b)
    • shared: add analytics feature-milestone vocabulary (1a9f9f4)
    • mobile: emit five product-usage events (329877e)
    • shared: share task-source vocabulary across apps (2f97b13)
    • shared: add 8 product events and the tier rule (0c04996)
    • api: add analytics delivery probe (040128b)
    • web: add a trial countdown to the dashboard (915f221)
    • api: geo-tag analytics events at the edge (9184bee)
    • api: add admin.billing.refund with audit trail (338a7c6)
    • api: sync payer emails to Paddle in reconcile cron (060de06)
    • api: daily billing reconciliation cron (1688490)
    • api: OIDC-verify Play RTDN, handle all types (f4df159)
    • api: expose trialEndsAt on the users.me access payload (5bd0610)
    • api: verify restored Apple transactions server-side (3ee3636)
    • db: add a trialing entitlement seed scenario (1d6989c)
    • shared: add a 'trial' entitlement source, narrowed to 'manual' on the wire (a3da1d0)
    • mobile: route Manage row to the store that charged (3684862)
    • name owning storefront in web billing pane (0826470)
    • api: getSubscription reports source and isLifetime (8fbae13)
    • sync: name the plan cause on a replay refusal (1697e1f)
    • api: refuse gated sync writes with a code instead of a bare 404 (77484cf)
    • db: add monetary columns to entitlements (e789fbc)
    • sync: stamp project_frozen on R02 freeze denials (55cb2a6)
    • api: re-gate calendar sync on the live plan across every background edge (0de19cc)
    • mobile: add PostHog rail with paywall funnel (c7d559e)
    • web: add growth board at /admin/metrics (df63da8)
    • db: add active-user and retention report modules (ad780d9)
    • api: make paddle webhook failures alertable (41b9bb3)
    • api: stamp which paddle account minted ctm_ (39bb293)
    • api: emit import and email-capture events (ab1c203)
    • mobile: mount GraceBanner on the remaining three tabs (bfc0f2b)
    • mobile: frozen-project read-only affordance (9a32c65)
    • mobile: downgrade project picker off the grace banner (424cf90)
    • web: frozen-project affordance for over-limit projects (ed46e6f)
    • api: emit business events to PostHog (3bcba7e)
    • i18n: add downgrade-picker and frozen-project copy (bdb095c)
    • web,mobile: register projects.downgradePreview in both REST registries (95cdf42)
    • db: add analytics raw event ledger + Art. 21 register (e7420c2)
    • db: add user_active_days, the active-user primitive (ef0ac7c)
    • billing: record the subscription a Clerk-side deletion cannot stop (a3b487c)
    • billing: stop the subscription a Play purchase supersedes (d12e6db)
    • web: identify the PostHog person as users.id (df2ba4f)
    • api: tell the user which projects the sweep will freeze (b672de4)
    • mobile: flash the first blocker from the completion-gate toast (1ac411f)
    • api: let the user pick which projects stay editable (793638f)
    • mobile: tappable dependency rows and blocker flash highlight (33fe7ff)
    • analytics: stamp app + platform on every event, detect desktop at runtime (2519bca)
    • i18n: add deps.open_a11y and deps.reveal_hint across locales (4dbd733)
    • mobile: claim www.etappi.app for iOS Universal Links (d9bcd3f)
    • ui: drop AI-priority sparkle indicator (0aa827f)
    • billing: tell a downgrading user the date and what freezes (dae65a6)
    • billing: archived projects are headroom, gate the un-archive (52cc545)
    • wire live App Store listing across surfaces (220ea31)
    • billing: block a cross-store purchase at the paywall (9ef1c1b)
    • billing: tell the user which store owns their plan (2ed63af)
    • billing: block cross-rail duplicate checkouts (e1b8cd2)
    • api: give a voluntary downgrade its own 14-day runway (4fc8b39)
    • shared: pre-flight denials carry a message key, not English (f81b10d)
    • web: surface plan denials from the sync seam as paywalls (e8694d7)
    • web: route plan denials to a single paywall surface (cbc78c0)
    • ui: replace suggestion chips with proposal cards (c680e23)
    • ui: section header with pending count and bulk accept (adf295e)
    • stop selling the pro + ai lifetime plan (cbbb413)
    • ui: proposal card for an AI priority suggestion (343ece3)
    • i18n: copy for bulk accept, retry and suggestion a11y (d34ede0)
    • ui: accept every priority suggestion in one action (084f792)
    • ui: carry the task title on every priority delta (87d9b44)
    • i18n: add grid create panel strings (1b27ee4)
    • web: carry the picked plan from marketing into billing checkout (f5fb6d0)
    • web: add five more switcher pages (16028a9)
    • web: sell every plan from the billing settings pane (24e0b33)
    • web: add Paddle.js checkout foundation (290c24d)
    • billing: add lifetime price keys and plan-change contracts (80658ed)
    • web: publish the public account-deletion page Play requires (4363e93)
    • i18n: parse quick-add dates and recurrence in de/fr/pl/uk (011eb2a)
    • web: photograph the hero device cluster from the real clients (e418ff9)
    • web: lead the marketing home with the multiplatform story (f805c68)
    • mobile: add the three Google Play screenshot sets (2d037f3)
    • mobile: add the phone screenshot set for the Play listing (0fa57e2)
    • mobile: split sign-in out of the screenshot flow and clear the e2ee gate (0401a29)
    • mobile: add Maestro flow for store listing screenshots (46f9117)
  • Fixes
    • mobile: resolve false-positive offline banner in simulators/emulators (259802c)
    • test: wait on the diagnostics values, not the panel header (0d4a170)
    • api: cancel untracked Paddle subscriptions before deleting an account (5c2693b)
    • billing: index entitlements.original_transaction_id (d618804)
    • billing: make a superseded-subscription cancel queryable (620b86c)
    • billing: tighten the checkout guard, drop the dead portal field (07ce654)
    • api: make the paddle webhook seam verifiable and bounded (c896994)
    • api: serialize concurrent refunds on one transaction (29afa18)
    • mobile: thread source into drizzle completion deps (4f85379)
    • api: close admin money-surface review findings (1d6e0f6)
    • web: render a trial state in the settings billing pane (86e1c62)
    • api: audit admin refunds before the money moves (4c33da4)
    • sync: repair the diff context PowerSync drops methods from (f530a5f)
    • mobile: make the trial banner fill opaque (51bfcd2)
    • mobile: widen FakeOp opData to allow null (32f29e7)
    • mobile: mount TrialBanner once above the root Stack (f309658)
    • mobile: type the partial-batch sync fixture for a real DELETE (1e0eba9)
    • api: bound entitlements granted on Paddle trial events (4ab2c73)
    • shared: stop the fuzz property generating values its schema rejects (f197fc5)
    • sync: require server say-so before reverting a denied create (924d3a5)
    • shared: stop the fuzz harness generating dates its own schema rejects (182b63c)
    • mobile: split the three attachment paywall denials (1445677)
    • mobile: route plan-denied sync drops to the paywall (997a0d6)
    • i18n: localize the two remaining sync-drop toasts (c9dcc19)
    • sync: revert the local row when a create is plan-denied (a28fd80)
    • mobile: reveal task-detail inputs above the keyboard (a3a3fa2)
    • db: give migration 0077 the ledger probe it needs (b9a25ce)
    • web: load Sentry natively so web error reporting actually runs (5ca8691)
    • ui,web: translate accessibilityState and derive roles on web (fe08d93)
    • web: give the sidebar project row's controls a role and a name (85bb971)
    • desktop: open Paddle portal and hosted checkout in the OS browser (f7139ea)
    • ui: close review findings on the priority proposal cards (cf1b5a9)
    • mobile: members paywall redirect sends the param the screen reads (50976fe)
    • refuse a plan preview with an unreadable total (21c1588)
    • web: plan change applies now, not next period (100c4e5)
    • shared: narrow entitlement source on the wire (5d8ea8e)
    • e2ee: classify opt-out failures instead of always reporting a conflict (8c4760e)
    • tasks: gate AI decompose on entitlement and surface paywall 403s (73af5a3)
    • give web lifetime its own entitlement source (4152fd8)
    • i18n: stop claiming the Todoist importer is Pro-only (4048ef5)
    • mobile: pin expo-location to the version its patch is keyed to (64c6142)
    • api: give the Paddle webhook an explicit failure taxonomy (ba5e407)
    • web: render the deletion bullet that was translated but never shown (6e0b963)
    • mobile: stop an Android push-token failure from wedging the reminder flow (e53cb5e)
    • i18n: resolve the five unresolved sync.* keys and harden the scanner (dd6e522)
    • mobile: keep every paywall failure recoverable, and unlock outside the screen (1590712)
    • i18n: fr plural one arms render the count, not a literal 1 (6 keys) (fdd03a8)
    • i18n: pl task-count plurals gain the few arm (2 keys) (3be5b43)
    • i18n: uk plural arms render the count instead of a literal 1 (2 keys) (069fb9b)
    • i18n: uk quick-add examples now parse in Ukrainian (5 keys) (076837d)
    • i18n: pl quick-add examples now parse in Polish (5 keys) (8dd102f)
    • i18n: fr quick-add examples now parse in French (3 keys) (7efdb09)
    • i18n: de quick-add examples now parse in German (3 keys) (9a60f43)
    • shared: parse Ukrainian dates typed with a typographic apostrophe (21b20de)
    • i18n: en typography sweep across 55 keys, plus the ui label mirrors (ff1b140)
    • i18n: fr projects.no_matches uses guillemets, not single quotes (92e1a00)
    • i18n: pl typography sweep across 42 keys (92c72c5)
    • i18n: de typography sweep across 45 keys (d2b2102)
    • i18n: uk typography sweep across 87 keys (1975856)
    • i18n: fr typography sweep across 223 keys (f74db41)
    • i18n: pl gendered address, calques and part-of-speech across 116 keys (0daa213)
    • i18n: fr calques, register and part-of-speech across 62 keys (2b76505)
    • i18n: de calques, register and part-of-speech across 65 keys (4f5a3d6)
    • i18n: remove Ukrainian calques and register drift across 59 keys (b3f9d2e)
    • i18n: unify German product glossary across 57 keys (91ea082)
    • i18n: unify French product glossary across 26 keys (91f50b6)
    • i18n: keep the two tier-neutral Ukrainian upsells tier-neutral (f8e6cde)
    • i18n: unify Polish product glossary across 28 keys (e2a3779)
    • i18n: unify Ukrainian product glossary across 51 keys (e9c9f4c)
    • i18n: correct three German third-person strings read as polite address (2f16ad4)
    • i18n: finish the German du conversion outside the audit list (8fa07ca)
    • i18n: convert the remaining German Sie strings to du (90166d2)
    • i18n: repair German placeholder frames in sync and MCP strings (394f4ab)
    • i18n: repair French agreement and placeholder frames (7bfbdb3)
    • i18n: repair Polish placeholder case in governing frames (9919f6a)
    • i18n: repair Ukrainian placeholder case in governing frames (e1dc629)
    • i18n: correct the Polish sidebar delete-dialog loading text (824012e)
    • i18n: correct the German sidebar delete-dialog loading text (aff427b)
    • i18n: correct the French sidebar delete-dialog loading text (c23c4d7)
    • i18n: fix German number agreement in the partial-import warning (0254850)
    • i18n: fix French number agreement in two plural messages (b36dd2f)
    • i18n: correct meaning-inverting French delete-dialog loading text (3ad6caf)
    • i18n: complete Polish plural categories (eeef06f)
    • i18n: complete Ukrainian plural categories (b24e4d0)
    • i18n: correct meaning-inverting Polish controls (42109ef)
    • i18n: correct meaning-inverting German controls (e2036d0)
    • mobile: accept the E2EE restore gate as a sign-in landing screen (9f37106)
    • mobile: make the board step a measured drag, not a fling (c669d85)
    • mobile: enumerate all four sign-in landing screens (d5fb797)
    • mobile: settle the shared-thread frame with measured drags (0d04c69)
    • db: fill the store-demo screens and comp the owner to Pro (0c05dde)
    • db: seed a third focus session and gate the frame on the synced activity row (957e4aa)
    • mobile: finish the capture flow and resolve maestro's nested artifact dir (7d31bc3)
    • db: name the store-demo owner and date its comment thread relative to today (829955f)
    • sync: resolve data keys from memory so the boot cannot deadlock (857e31b)
    • crypto: write the project-key cache without ON CONFLICT (9e6b314)
    • mobile: stop the env block from shadowing maestro -e (393f4f9)
    • mobile: name screenshots relative to the maestro output dir (0caad90)
    • ui,web: make overlay controls reachable and place popovers correctly (56110b4)
    • db: restore pg extensions after db:reset drops the schema (be9df49)
  • Other
    • excise e2ee from clients, shared schemas, and db client (f722189)
    • unwrap the attachment pipeline from E2EE (ef68e2c)
    • retire the tasks_decrypted shadow read-model (084a716)
    • shared: collapse encrypted-content bounds to plain length caps (3964d02)
    • shared: retire unproduced payment notification types (94e9031)
    • drop users.plan and plan_expires_at (f09b1fc)
    • db: drop plan from the users sync surface (9237a81)
    • api: split plan-gate, unify active check (6a0f1cd)
    • shared: move paywall error classifier out of apps/web (297dd7e)
    • shared: lift downgrade-picker row derivations into @etappi/shared (d06ad52)
    • mobile: extract blocker reveal scroll plumbing into use-blocker-reveal (20dae17)
    • shared: self-check one-time price keys (edc59fa)
    • mobile: freeze derived SKU lists (4e6190c)

iOS 1.22.0 — 2026-08-07 (build 69)

  • Features
    • mobile: claim www.etappi.app for iOS Universal Links (d9bcd3f)
    • ui: drop AI-priority sparkle indicator (0aa827f)
    • wire live App Store listing across surfaces (220ea31)
    • shared: pre-flight denials carry a message key, not English (f81b10d)
    • web: surface plan denials from the sync seam as paywalls (e8694d7)
    • web: route plan denials to a single paywall surface (cbc78c0)
    • ui: replace suggestion chips with proposal cards (c680e23)
    • ui: section header with pending count and bulk accept (adf295e)
    • stop selling the pro + ai lifetime plan (cbbb413)
    • ui: proposal card for an AI priority suggestion (343ece3)
    • i18n: copy for bulk accept, retry and suggestion a11y (d34ede0)
    • ui: accept every priority suggestion in one action (084f792)
    • ui: carry the task title on every priority delta (87d9b44)
    • i18n: add grid create panel strings (1b27ee4)
    • web: carry the picked plan from marketing into billing checkout (f5fb6d0)
    • web: add five more switcher pages (16028a9)
    • web: sell every plan from the billing settings pane (24e0b33)
    • web: add Paddle.js checkout foundation (290c24d)
    • billing: add lifetime price keys and plan-change contracts (80658ed)
    • web: publish the public account-deletion page Play requires (4363e93)
  • Fixes
    • mobile: reveal task-detail inputs above the keyboard (a3a3fa2)
    • desktop: open Paddle portal and hosted checkout in the OS browser (f7139ea)
    • ui: close review findings on the priority proposal cards (cf1b5a9)
    • mobile: members paywall redirect sends the param the screen reads (50976fe)
    • refuse a plan preview with an unreadable total (21c1588)
    • web: plan change applies now, not next period (100c4e5)
    • shared: narrow entitlement source on the wire (5d8ea8e)
    • e2ee: classify opt-out failures instead of always reporting a conflict (8c4760e)
    • tasks: gate AI decompose on entitlement and surface paywall 403s (73af5a3)
    • give web lifetime its own entitlement source (4152fd8)
    • i18n: stop claiming the Todoist importer is Pro-only (4048ef5)
    • mobile: pin expo-location to the version its patch is keyed to (64c6142)
    • api: give the Paddle webhook an explicit failure taxonomy (ba5e407)
    • web: render the deletion bullet that was translated but never shown (6e0b963)
    • mobile: stop an Android push-token failure from wedging the reminder flow (e53cb5e)
    • i18n: resolve the five unresolved sync.* keys and harden the scanner (dd6e522)
  • Other
    • shared: self-check one-time price keys (edc59fa)
    • mobile: freeze derived SKU lists (4e6190c)

iOS 1.21.0 — 2026-08-04 (build 68)

This is the build that went public. Approved and released on the App Store on 2026-08-06 — the first public Etappi release on any store. App Store Connect records the public version as 1.0, not 1.21.0; the numbers below are the repo's derived version, and the two are not reconciled (see docs/deployment.md#known-gaps-at-launch). Android is unaffected — it remains on a Play closed-testing track at 1.10.0 (versionCode 13).

  • Features
    • i18n: parse quick-add dates and recurrence in de/fr/pl/uk (011eb2a)
    • web: photograph the hero device cluster from the real clients (e418ff9)
    • web: lead the marketing home with the multiplatform story (f805c68)
    • mobile: add the three Google Play screenshot sets (2d037f3)
    • mobile: add the phone screenshot set for the Play listing (0fa57e2)
    • mobile: split sign-in out of the screenshot flow and clear the e2ee gate (0401a29)
    • mobile: add Maestro flow for store listing screenshots (46f9117)
  • Fixes
    • mobile: keep every paywall failure recoverable, and unlock outside the screen (1590712)
    • i18n: fr plural one arms render the count, not a literal 1 (6 keys) (fdd03a8)
    • i18n: pl task-count plurals gain the few arm (2 keys) (3be5b43)
    • i18n: uk plural arms render the count instead of a literal 1 (2 keys) (069fb9b)
    • i18n: uk quick-add examples now parse in Ukrainian (5 keys) (076837d)
    • i18n: pl quick-add examples now parse in Polish (5 keys) (8dd102f)
    • i18n: fr quick-add examples now parse in French (3 keys) (7efdb09)
    • i18n: de quick-add examples now parse in German (3 keys) (9a60f43)
    • shared: parse Ukrainian dates typed with a typographic apostrophe (21b20de)
    • i18n: en typography sweep across 55 keys, plus the ui label mirrors (ff1b140)
    • i18n: fr projects.no_matches uses guillemets, not single quotes (92e1a00)
    • i18n: pl typography sweep across 42 keys (92c72c5)
    • i18n: de typography sweep across 45 keys (d2b2102)
    • i18n: uk typography sweep across 87 keys (1975856)
    • i18n: fr typography sweep across 223 keys (f74db41)
    • i18n: pl gendered address, calques and part-of-speech across 116 keys (0daa213)
    • i18n: fr calques, register and part-of-speech across 62 keys (2b76505)
    • i18n: de calques, register and part-of-speech across 65 keys (4f5a3d6)
    • i18n: remove Ukrainian calques and register drift across 59 keys (b3f9d2e)
    • i18n: unify German product glossary across 57 keys (91ea082)
    • i18n: unify French product glossary across 26 keys (91f50b6)
    • i18n: keep the two tier-neutral Ukrainian upsells tier-neutral (f8e6cde)
    • i18n: unify Polish product glossary across 28 keys (e2a3779)
    • i18n: unify Ukrainian product glossary across 51 keys (e9c9f4c)
    • i18n: correct three German third-person strings read as polite address (2f16ad4)
    • i18n: finish the German du conversion outside the audit list (8fa07ca)
    • i18n: convert the remaining German Sie strings to du (90166d2)
    • i18n: repair German placeholder frames in sync and MCP strings (394f4ab)
    • i18n: repair French agreement and placeholder frames (7bfbdb3)
    • i18n: repair Polish placeholder case in governing frames (9919f6a)
    • i18n: repair Ukrainian placeholder case in governing frames (e1dc629)
    • i18n: correct the Polish sidebar delete-dialog loading text (824012e)
    • i18n: correct the German sidebar delete-dialog loading text (aff427b)
    • i18n: correct the French sidebar delete-dialog loading text (c23c4d7)
    • i18n: fix German number agreement in the partial-import warning (0254850)
    • i18n: fix French number agreement in two plural messages (b36dd2f)
    • i18n: correct meaning-inverting French delete-dialog loading text (3ad6caf)
    • i18n: complete Polish plural categories (eeef06f)
    • i18n: complete Ukrainian plural categories (b24e4d0)
    • i18n: correct meaning-inverting Polish controls (42109ef)
    • i18n: correct meaning-inverting German controls (e2036d0)
    • mobile: accept the E2EE restore gate as a sign-in landing screen (9f37106)
    • mobile: make the board step a measured drag, not a fling (c669d85)
    • mobile: enumerate all four sign-in landing screens (d5fb797)
    • mobile: settle the shared-thread frame with measured drags (0d04c69)
    • db: fill the store-demo screens and comp the owner to Pro (0c05dde)
    • db: seed a third focus session and gate the frame on the synced activity row (957e4aa)
    • mobile: finish the capture flow and resolve maestro's nested artifact dir (7d31bc3)
    • db: name the store-demo owner and date its comment thread relative to today (829955f)
    • sync: resolve data keys from memory so the boot cannot deadlock (857e31b)
    • crypto: write the project-key cache without ON CONFLICT (9e6b314)
    • mobile: stop the env block from shadowing maestro -e (393f4f9)
    • mobile: name screenshots relative to the maestro output dir (0caad90)
    • ui,web: make overlay controls reachable and place popovers correctly (56110b4)
    • db: restore pg extensions after db:reset drops the schema (be9df49)

Android 1.10.0 — 2026-08-01 (versionCode 13)

  • Features
    • ui: add autoFocus prop to QuickAddPalette (2c5b8a0)
    • ui: add density prop to EmptyState (8fda5f0)
    • ui: redraw the Today empty illustration as a settled list (1433a0d)
    • mobile: give Today an empty spot inside the scroll body (5d725f8)
    • ui: add EmptyToday illustration to the empty-state kit (3ca0ada)
    • db: add todayCompletedTasksQuery for Today's Done section (53e7ed8)
    • billing: surface storefront and numeric prices in non-production builds (8a7accc)
    • paywall: show Terms and Privacy at the point of purchase (49b51cf)
    • paywall: group plans by tier, one badge, badge on the card (0f7637b)
    • paywall: pure tier grouping and single-badge anchor selection (8aa914c)
    • paywall: translate purchase failures from a code, never a message (017110f)
    • paywall: add notice, tier, period and savings i18n keys (18de597)
    • billing: carry a BillingErrorCode instead of a raw SDK message (3858f92)
    • db: bound API query time with a statement timeout (21c0bf1)
    • e2ee: add the mobile owner escape hatch from encryption (340a9d5)
    • e2ee: add the web owner escape hatch from encryption (c15025c)
    • e2ee: authorize plaintext uploads after an owner decrypt (d9fb2e1)
    • e2ee: blob-sweep port adapters for decrypt-and-disable (17fe0a3)
    • mobile: add the CRUD upload-flush barrier (76a563f)
    • api: add attachment replace-bytes presign for the E2EE blob sweep (6ce62f4)
    • api: add e2ee.getMyDowngradeAuthorizations read route (3553213)
    • api: add projects.disableEncryption escape-hatch route (8caab25)
    • db: store owner-minted downgrade authorizations (66639ce)
    • shared: orchestrate the account-wide decrypt sweep (8dca73b)
    • shared: sweep attachment blobs with local staging before upload (180424c)
    • shared: rewrite scanned rows as plaintext through the CRUD queue (b6d9978)
    • shared: scan encrypted projects before any decrypt rewrite (ecebbe9)
    • shared: add device-local decrypt session to suspend upload encryption (551d5de)
    • shared: reconcile an authorized E2EE downgrade against the posture pin (853b2fd)
    • shared: add identity-keyed downgrade-authorization MAC (fae3727)
    • db: add growth report for activation and D7 stop-conditions (00b254d)
    • mobile: add filter duplicate route seeded from the source filter (12ea498)
    • mobile: swap filter detail Edit button for an overflow sheet (bd15e27)
    • mobile: add filter detail action sheet (19e92e6)
    • mobile: add filter detail action hook (fd93265)
    • mobile: collapse habit detail header to a single overflow action (6772990)
    • i18n: add filter actions/duplicate/copy-name keys, drop filter.edit_a11y (84f3db7)
    • mobile,web: surface a distinct S5-01 encryption-downgrade security alert (48edb8e)
    • mobile,web: platform E2EE posture stores + connector wiring (9c027e4)
    • shared: wire S5-01 downgrade guard into upload encrypt seam (3949c73)
    • shared: device-local per-project E2EE posture pin (TOFU) (8cdad29)
    • mobile: add the E2EE opt-out toggle to the Privacy section (51f8756)
    • shared: add settings.security.* i18n keys for the E2EE opt-out toggle (7680d66)
    • api,shared: surface ownsEncryptedProjects on users.me for opt-out toggle gating (c23fd91)
    • e2ee: quiet opt-out escape UI on the identity gate (web + mobile) (6e9d24f)
    • i18n: add e2ee opt-out gate copy (6 keys) across all 5 locales (a0bf2ea)
    • e2ee: wire opt-out persistence through gate machine, shared port, and REST client (e4fb9b3)
    • e2ee: honor account opt-out in the identity gate → passthrough (f22a375)
    • api: surface e2eeOptOut on users.me + setE2eeOptOut endpoint (3e29358)
    • db: add server-only users.e2ee_opt_out flag + ledger probe 75 (aafd277)
    • mobile: Today first, now the tabs root (fd01954)
    • mobile: add local-first habit archive + delete (d833702)
    • api: add sync DELETE route for habits (88c2021)
    • shared: add habit archive toast + actions a11y keys (12d1e42)
    • web: founder note, hero gloss, one CTA pair (plan 3.3-3.5) (80f9283)
    • web: simplify the landing pricing block (plan 3.2) (b1e9056)
    • web: merge the duplicated feature sections, add product shots (plan 3.1, 2.3) (9245a9c)
    • web: hero product shot (plan 2.2) (e4a8056)
    • web: responsive marketing nav with language switcher (1cd39d3)
    • e2ee: activate Encrypted. Everywhere. — real E2EE, gate enforced (e55d5cc)
    • web: shared markdown pipeline with GFM tables + sanitize (10f365c)
    • e2ee: enforce E2EE_GATE_ENFORCED end-to-end (5f10325)
    • mobile: add QR key verification display + camera scan (fef902c)
    • shared: add QR payload codec for out-of-band key confirmation (40b43d1)
    • mobile: add out-of-band key verification UI (safety numbers) (b4d14fa)
    • e2ee: seal project keys to members + live key-grant refetch (97422f8)
    • web: add out-of-band key verification UI (safety numbers) (7776d32)
    • shared: add warn-only trust-pin state machine for key verification (99b9676)
    • shared: derive symmetric emoji safety fingerprint from key pair (1cc7e7b)
    • repo: flush E2EE session keys on lock and sign-out (506b8ee)
    • repo: route content edits through local-first CRUD path (d220529)
    • repo: wire e2ee encrypt/decrypt client path (f27b859)
    • tasks: surface start_date end-to-end and close the date-field parity gaps (R41) (2770687)
    • mobile: recompose content-free E2EE pushes on-device (f0364a6)
    • web: chunk large imports and warn past the cap (cacdda5)
    • e2ee: activate content-column encrypt/decrypt (b8c4ba8)
    • db: add tasks.recurrence_parent_id self-FK (0073/R40) (61142df)
    • e2ee: classify refuse-write retryable, toast lock (06b0c10)
    • bucket task_dependencies + goals by membership (1b6b81e)
    • e2ee: refuse write on locked E2EE project (daacb55)
    • e2ee: reconcile locally-minted project keys on session start (ac62c4c)
    • e2ee: push sealed project key on create (best-effort) (2007a98)
    • e2ee: seal per-project data key on create (754f382)
    • mobile: universal file import in settings (7618de7)
    • mobile: add dormant e2ee identity gate (83b4ad0)
    • web: universal file-upload import UI in settings (b7397cc)
    • universal file import + ungate bulk import (00aea76)
    • web: dormant identity gate + e2ee_gate i18n (2deaab3)
    • shared: spot-check + gate retry + identity probe (daf7493)
    • shared: two-phase mint + identity gate machine (cd0351a)
    • web,mobile: add e2ee identity backup callers + onboarding factories (99f3669)
    • mobile: polish-title chip on task detail (B20) (6e88554)
    • shared: add identity mint/restore onboarding service (b82624c)
    • web: polish-title chip on task detail (B20) (e5be124)
    • shared: add BIP39 recovery-phrase module (a74908d)
    • shared: polish-title chip hook + i18n keys (B20) (3bbda12)
    • shared: add polish_title paywall code + REST schema (B20) (1938ae8)
    • web: wire similar-tasks suggestions into quick-add and inbox (2c25f74)
    • mobile: add dormant e2ee key-store adapters (93b232e)
    • db: add local-only project_keys_cache table + builders (e72a80b)
    • shared: add dormant e2ee getDataKey resolver (3e55aeb)
    • db: repoint entity reads to _decrypted views (991b31b)
    • api: add tasks.similar semantic duplicate endpoint (73a1701)
    • shared: generalize content-decrypt read model to all encrypted tables (a542bed)
    • mobile: wire react-native-libsodium provider boot for e2ee (f18217b)
    • api: add Voyage embeddings client for B22 similar-tasks (ee4920e)
    • db: add pgvector task-embedding column for similar-tasks (B22) (e3ee856)
    • scrub PII from Sentry on all platforms (12f2799)
    • api: close shareProject enum oracle (560b9a4)
    • repoint task reads to tasks_decrypted view (149104f)
    • web,mobile: stamp UI locale into Clerk unsafeMetadata at sign-up (ec7cd50)
    • db: add server-only users.activation_bootstrapped_at (8df13e9)
    • i18n: add welcome-email and sample-project starter copy (dcbe78d)
    • web,mobile: wire content-decryption boot-ready gate (dormant) (bcf78d0)
    • shared: add content-decryption read model (dormant) (cf3953c)
    • api: widen data export to full GDPR sweep (a278c38)
    • db: anonymize activity_log actor on delete (R61) (5ea7615)
    • api: cancel live billing on account deletion (cd8f0af)
    • e2ee: add attachment download decrypt path (7ae42e2)
    • shared: add E2EE seam to attachment uploads (18de53a)
    • shared: encrypt attachment fileName/mimeType on upload (b77c86d)
    • shared: add attachment blob crypto envelope (c44346d)
    • web: implement standalone blog and changelog routes and verify all package tests (81979f3)
    • ui: translate reminder presets via label bag (27b9011)
    • link /pricing from every pricing surface (ea16ac7)
    • add the /pricing FAQ (b26fbda)
    • add a standalone /pricing page (e291f26)
    • e2ee: encrypt content columns on the sync-upload boundary (2d4c714)
    • sell Pro+AI through web checkout (f330b55)
    • e2ee: server-only key storage tables and REST router (Phase 2) (c710f77)
    • shared: add libsodium E2EE crypto core (259c5f8)
  • Fixes
    • mobile: remove the location UI the app could never deliver (e00f89a)
    • mobile: recover from paywall catalogue and token failures (5937d66)
    • mobile: align location declarations with what the app actually does (0deb781)
    • api: reach encrypted wire formats without loading libsodium (5ed6776)
    • mobile: let a brand-new account finish onboarding offline (ea3a5e7)
    • mobile: anchor the offline banner under the chrome each route wears (c3428f4)
    • mobile: name the outage instead of blaming the password (c4dc01f)
    • mobile: lift the splash when the root error boundary catches (ca111f1)
    • mobile: bound the locale bootstrap below the splash cap (fa1b8d9)
    • mobile: bound Clerk boot stall below the splash cap (6fda9fb)
    • mobile: evict the Clerk resource cache on sign-out (1891a43)
    • mobile: stop the offline banner covering the screen title (cb2f038)
    • mobile: make cold start work with no network (eef69c4)
    • ui: draw illustration ink with muted, not border-light (907d3a7)
    • billing: one definition for entitlement source, one authority for client tier (70780ef)
    • ui: draw empty-today ink from muted, not borderLight (84248e0)
    • mobile: strip dev-client scheme and storage permissions from release builds (R111, R112) (d46c3e7)
    • mobile: purge process-global local stores when the device changes hands (R105, R106, R115) (21386de)
    • mobile: trust install attribution only from verified https launch URLs (R114) (6660d7c)
    • mobile: allowlist OS-delivered deep links at the router entry (R104) (a7355f1)
    • thread targetCalendarId through the compose adapter and local insert (e71fb3e)
    • api: gate filters and reminders on the declared plan flag (R107) (0a7c984)
    • mobile: make Today's "Done today" section reachable (4a0b824)
    • i18n: split Today's empty-state copy into cleared/free states (58f7a35)
    • api: correct false export bound claim, observe payload size (R109) (2a52a05)
    • api: make rate-limiter fail-open observable (R110) (b9d4c78)
    • mcp,api: add token_use discriminator between access and service tokens (R97) (63aaa66)
    • mcp: escape label id before filter-DSL interpolation (R99) (c5d5bd4)
    • ci: make four gates fail when they inspect nothing (7a31090)
    • release: pin the Sentry environment tag for store cuts (dadd51e)
    • billing: recover the numeric price from Android offer details (ea0c94a)
    • security: widen redaction denylist, scrub PII in logs, gate REST schemas (ae02006)
    • test: export Platform from the subscription screen's react-native mock (bd82c74)
    • paywall: compute the yearly-savings badge from live store prices (f15cf9c)
    • paywall: claim the free trial only when the store still offers it (8a34e93)
    • mobile: resolve store-facing paywall copy per platform (1aa143f)
    • api: bind PAT scope to a server-owned channel (b009c9c)
    • billing: swallow cancelled restores; stop leaking server text (c22cebf)
    • mobile,web: claim OAuth/deep-link URLs via verified Android App Links (R90) (b770d65)
    • mobile: gate Lock Screen widget titles behind the biometric lock (b819a4d)
    • mobile: purge widget App Group payloads on sign-out (7b2fda2)
    • shared: refuse attachment upload on E2EE posture downgrade (3dc4f40)
    • sync: redact mobile drop-telemetry body, hoist redactSyncBody to shared (042c115)
    • db: exempt migrations from the role statement_timeout (bb6995d)
    • mcp: stop persisting task content in audit rows (R116) (d4f0dda)
    • sec: budget push and calendar side-effects per actor (R96) (1781d0a)
    • sec: reclaim orphaned attachment objects with a daily sweep (R95) (25f7b60)
    • sec: bound attachments by count and total storage, not size alone (R95) (2908400)
    • sec: restore plan gate on import label creation (R94) (b59999e)
    • mobile: resolve the ATS plugin test path without node:url's URL type (9d7f881)
    • release: coerce the realtime URL and pin iOS ATS in store builds (f880c81)
    • e2ee: downgrade projects descendants-first (f1dc614)
    • ui: remove unused ListFooterComponent from FiltersScreen (06f5639)
    • ui: remove new filter label from FiltersScreen (bc1fa20)
    • ui: add native split for ConfirmDialog (3e9ce54)
    • mobile: translate the undo-failure toast for filter delete (3d829ba)
    • web,mobile: add opt-out escape to the E2EE restore screen (7afdc4a)
    • desktop: route external opens through opener plugin (4362eac)
    • mobile: avoid keyboard on identity gate shell (60dd668)
    • count down phrase clipboard, wipe on deadline (1341187)
    • e2ee: drop the Node Buffer dependency from the shared base64 codec (d25671f)
    • e2ee: report identity gate failures instead of discarding them (810addd)
    • mobile: do not run the identity gate before Clerk resolves a session (f241d45)
    • web: stop habit detail pulling the whole UI barrel (2ffb66a)
    • web,api: merge landing UX remediation and the Clerk key restore (0e98d2b)
    • mobile: pin css-tree resolution to the Hermes-safe nested copy (215180c)
    • ui,web: AA-compliant muted token and accessible names on marketing (plan 4.1-4.2) (afc08fb)
    • ui: accessible accent ink via --color-primary-text (plan 4.1) (34b192f)
    • i18n: correct platform claims on landing and features pages (7ba07c1)
    • db: bound the client task-tree walks so a cyclic parent cannot spin (c229878)
    • mobile: migrate the widget keychain item only on a positive read (f06a515)
    • mobile: revoke the widget PAT that a re-mint replaces (16c5aa5)
    • db: derive the tasks test-table DDL from the client schema (154963a)
    • api: contain prompt injection and cap inbound-mail AI spend (90578b9)
    • mobile: keep the widget PAT out of device backups (R85) (ed835db)
    • e2ee: bound REST upsert content with envelope-aware cap (67f610a)
    • mobile: restore iOS keyboard suggestions on task title (f2229e4)
    • e2ee: reconcile unbounded content contract across the dev merge (0da2925)
    • mobile: make task delete local-first to kill list delay (2fb1cb8)
    • e2ee: bound refuse-write parking so an unresolvable op cannot wedge the FIFO (d616e21)
    • mobile: latch QR match once, mirroring web panel (44d33d1)
    • keep QR scanner alive after mismatch; stabilize web camera (58bc667)
    • shared: reject empty expected key in QR match (f466bc2)
    • mobile: RoundedFill for verify emoji grid cells (f836a31)
    • api: bind OAuth callbacks to the initiating browser (R66) (a9e96c0)
    • api: narrow the extension Connect PAT to least privilege (R62) (aa6bc36)
    • shared: jitter fractional keys so offline devices never collide (R22) (d7ea459)
    • shared: collapse legacy habit-log rows on upsert (6bbaaeb)
    • shared: make habit-log upsert atomic via deterministic id (d5ef8ca)
    • api: rate-limit and generalize 401 on the signed export download (4cf736a)
    • shared: scrub Sentry request headers, cookies and query string (c885990)
    • mobile: guard calendar htmlLink with isSafeHttpUrl (R59) (117e35d)
    • mobile: fail-closed onboarding gate with bounded retry (R28) (9b93342)
    • web,mobile: ref-escape getToken in useRestMutation (R24) (673e148)
    • shared: bound tasks/upsert title + description (R58) (f0af209)
    • e2ee: guard reconcile local read against throw (6c80bfe)
    • api: guard replay apply-mine vs collab edits (b65a86f)
    • api: bound bulk-import rate + cap import ref length (4cc44f3)
    • e2ee: keep recovery-phrase clipboard wipe on unmount (3f4cd1a)
    • shared: harden e2ee identity gate mint path (2da57cf)
    • ui: prune spent undoable-action ids (9119ae2)
    • api: harden CalDAV/Apple-Calendar sync (security audit) (eeade07)
    • shared: harden e2ee recovery against a hostile server (ca8a6c3)
    • mobile: multicast cold-start deep-link holder per consumer (R25) (b059600)
    • mobile: guard local-first task-create paths against double-tap (R10) (9ba0d09)
    • ui: stop toast swipe from stealing fast row taps (R23) (fe99c1a)
    • ui: keep per-action undo slots so rapid actions don't clobber (R47) (f18ed7f)
    • shared: clear decrypt shadow on envelope→plaintext (c808fb6)
    • shared: pass AEAD AAD as string for cross-platform libsodium (b3ddb21)
    • db: make 0069 FK add migrate-safe (NOT VALID + VALIDATE) (6d38f5d)
    • mobile: stub getOptional in batch test (88c5cdb)
    • e2ee: harden attachment encrypt/decrypt seam (828da79)
    • mobile: resolve silent failures when deleting project on mobile (5abcc7b)
    • web: route Pro lifetime CTA to the app, not the sign-up funnel (90c9422)
    • web: correct pricing page's false FAQ and platform claims (a1c14b9)
    • stop claiming the free plan covers a full Todoist import (a558d58)
    • shared: drop false AI and MCP claims from pricing copy (51cb94f)
    • shared: harden E2EE crypto core per security review (b1e7e41)
  • Other
    • remove BETA_FREE_PROAI flag and its access-floor logic (bb54481)
    • today: drop the minHeight floor, use compact density (61c51a3)
    • shared: relocate buildMemberVerifications into shared crypto (23be34e)
    • e2ee: remove legacy AES-GCM local-write scheme (0b27b18)
    • shared: lift summarizeRows into import domain (15558e1)
    • harden e2ee 5a key-store adapters (8fdf8b6)

iOS 1.20.0 — 2026-08-01 (build 67)

  • Features
    • ui: add autoFocus prop to QuickAddPalette (2c5b8a0)
    • ui: add density prop to EmptyState (8fda5f0)
    • ui: redraw the Today empty illustration as a settled list (1433a0d)
    • mobile: give Today an empty spot inside the scroll body (5d725f8)
    • ui: add EmptyToday illustration to the empty-state kit (3ca0ada)
    • db: add todayCompletedTasksQuery for Today's Done section (53e7ed8)
    • e2ee: add the mobile owner escape hatch from encryption (340a9d5)
    • e2ee: add the web owner escape hatch from encryption (c15025c)
    • e2ee: authorize plaintext uploads after an owner decrypt (d9fb2e1)
    • e2ee: blob-sweep port adapters for decrypt-and-disable (17fe0a3)
    • mobile: add the CRUD upload-flush barrier (76a563f)
    • api: add attachment replace-bytes presign for the E2EE blob sweep (6ce62f4)
    • api: add e2ee.getMyDowngradeAuthorizations read route (3553213)
    • api: add projects.disableEncryption escape-hatch route (8caab25)
    • db: store owner-minted downgrade authorizations (66639ce)
    • shared: orchestrate the account-wide decrypt sweep (8dca73b)
    • shared: sweep attachment blobs with local staging before upload (180424c)
    • shared: rewrite scanned rows as plaintext through the CRUD queue (b6d9978)
    • shared: scan encrypted projects before any decrypt rewrite (ecebbe9)
    • shared: add device-local decrypt session to suspend upload encryption (551d5de)
    • shared: reconcile an authorized E2EE downgrade against the posture pin (853b2fd)
    • shared: add identity-keyed downgrade-authorization MAC (fae3727)
  • Fixes
    • mobile: remove the location UI the app could never deliver (e00f89a)
    • mobile: recover from paywall catalogue and token failures (5937d66)
    • mobile: align location declarations with what the app actually does (0deb781)
    • api: reach encrypted wire formats without loading libsodium (5ed6776)
    • mobile: let a brand-new account finish onboarding offline (ea3a5e7)
    • mobile: anchor the offline banner under the chrome each route wears (c3428f4)
    • mobile: name the outage instead of blaming the password (c4dc01f)
    • mobile: lift the splash when the root error boundary catches (ca111f1)
    • mobile: bound the locale bootstrap below the splash cap (fa1b8d9)
    • mobile: bound Clerk boot stall below the splash cap (6fda9fb)
    • mobile: evict the Clerk resource cache on sign-out (1891a43)
    • mobile: stop the offline banner covering the screen title (cb2f038)
    • mobile: make cold start work with no network (eef69c4)
    • ui: draw illustration ink with muted, not border-light (907d3a7)
    • billing: one definition for entitlement source, one authority for client tier (70780ef)
    • ui: draw empty-today ink from muted, not borderLight (84248e0)
    • mobile: strip dev-client scheme and storage permissions from release builds (R111, R112) (d46c3e7)
    • mobile: purge process-global local stores when the device changes hands (R105, R106, R115) (21386de)
    • mobile: trust install attribution only from verified https launch URLs (R114) (6660d7c)
    • mobile: allowlist OS-delivered deep links at the router entry (R104) (a7355f1)
    • thread targetCalendarId through the compose adapter and local insert (e71fb3e)
    • api: gate filters and reminders on the declared plan flag (R107) (0a7c984)
    • mobile: make Today's "Done today" section reachable (4a0b824)
    • i18n: split Today's empty-state copy into cleared/free states (58f7a35)
    • api: correct false export bound claim, observe payload size (R109) (2a52a05)
    • api: make rate-limiter fail-open observable (R110) (b9d4c78)
    • mcp,api: add token_use discriminator between access and service tokens (R97) (63aaa66)
    • mcp: escape label id before filter-DSL interpolation (R99) (c5d5bd4)
    • e2ee: downgrade projects descendants-first (f1dc614)
  • Other
    • remove BETA_FREE_PROAI flag and its access-floor logic (bb54481)
    • today: drop the minHeight floor, use compact density (61c51a3)

iOS 1.19.0 — 2026-07-31 (build 66)

  • Features
    • billing: surface storefront and numeric prices in non-production builds (8a7accc)
    • paywall: show Terms and Privacy at the point of purchase (49b51cf)
    • paywall: group plans by tier, one badge, badge on the card (0f7637b)
    • paywall: pure tier grouping and single-badge anchor selection (8aa914c)
    • paywall: translate purchase failures from a code, never a message (017110f)
    • paywall: add notice, tier, period and savings i18n keys (18de597)
    • billing: carry a BillingErrorCode instead of a raw SDK message (3858f92)
    • db: bound API query time with a statement timeout (21c0bf1)
    • db: add growth report for activation and D7 stop-conditions (00b254d)
    • mobile: add filter duplicate route seeded from the source filter (12ea498)
    • mobile: swap filter detail Edit button for an overflow sheet (bd15e27)
    • mobile: add filter detail action sheet (19e92e6)
    • mobile: add filter detail action hook (fd93265)
    • mobile: collapse habit detail header to a single overflow action (6772990)
    • i18n: add filter actions/duplicate/copy-name keys, drop filter.edit_a11y (84f3db7)
  • Fixes
    • ci: make four gates fail when they inspect nothing (7a31090)
    • release: pin the Sentry environment tag for store cuts (dadd51e)
    • billing: recover the numeric price from Android offer details (ea0c94a)
    • security: widen redaction denylist, scrub PII in logs, gate REST schemas (ae02006)
    • test: export Platform from the subscription screen's react-native mock (bd82c74)
    • paywall: compute the yearly-savings badge from live store prices (f15cf9c)
    • paywall: claim the free trial only when the store still offers it (8a34e93)
    • mobile: resolve store-facing paywall copy per platform (1aa143f)
    • api: bind PAT scope to a server-owned channel (b009c9c)
    • billing: swallow cancelled restores; stop leaking server text (c22cebf)
    • mobile,web: claim OAuth/deep-link URLs via verified Android App Links (R90) (b770d65)
    • mobile: gate Lock Screen widget titles behind the biometric lock (b819a4d)
    • mobile: purge widget App Group payloads on sign-out (7b2fda2)
    • shared: refuse attachment upload on E2EE posture downgrade (3dc4f40)
    • sync: redact mobile drop-telemetry body, hoist redactSyncBody to shared (042c115)
    • db: exempt migrations from the role statement_timeout (bb6995d)
    • mcp: stop persisting task content in audit rows (R116) (d4f0dda)
    • sec: budget push and calendar side-effects per actor (R96) (1781d0a)
    • sec: reclaim orphaned attachment objects with a daily sweep (R95) (25f7b60)
    • sec: bound attachments by count and total storage, not size alone (R95) (2908400)
    • sec: restore plan gate on import label creation (R94) (b59999e)
    • mobile: resolve the ATS plugin test path without node:url's URL type (9d7f881)
    • release: coerce the realtime URL and pin iOS ATS in store builds (f880c81)
    • ui: remove unused ListFooterComponent from FiltersScreen (06f5639)
    • ui: remove new filter label from FiltersScreen (bc1fa20)
    • ui: add native split for ConfirmDialog (3e9ce54)
    • mobile: translate the undo-failure toast for filter delete (3d829ba)
    • web,mobile: add opt-out escape to the E2EE restore screen (7afdc4a)

iOS 1.18.0 — 2026-07-27 (build 65)

  • Features
    • mobile,web: surface a distinct S5-01 encryption-downgrade security alert (48edb8e)
    • mobile,web: platform E2EE posture stores + connector wiring (9c027e4)
    • shared: wire S5-01 downgrade guard into upload encrypt seam (3949c73)
    • shared: device-local per-project E2EE posture pin (TOFU) (8cdad29)
    • mobile: add the E2EE opt-out toggle to the Privacy section (51f8756)
    • shared: add settings.security.* i18n keys for the E2EE opt-out toggle (7680d66)
    • api,shared: surface ownsEncryptedProjects on users.me for opt-out toggle gating (c23fd91)
    • e2ee: quiet opt-out escape UI on the identity gate (web + mobile) (6e9d24f)
    • i18n: add e2ee opt-out gate copy (6 keys) across all 5 locales (a0bf2ea)
    • e2ee: wire opt-out persistence through gate machine, shared port, and REST client (e4fb9b3)
    • e2ee: honor account opt-out in the identity gate → passthrough (f22a375)
    • api: surface e2eeOptOut on users.me + setE2eeOptOut endpoint (3e29358)
    • db: add server-only users.e2ee_opt_out flag + ledger probe 75 (aafd277)
    • mobile: Today first, now the tabs root (fd01954)
    • mobile: add local-first habit archive + delete (d833702)
    • api: add sync DELETE route for habits (88c2021)
    • shared: add habit archive toast + actions a11y keys (12d1e42)
    • web: founder note, hero gloss, one CTA pair (plan 3.3-3.5) (80f9283)
    • web: simplify the landing pricing block (plan 3.2) (b1e9056)
    • web: merge the duplicated feature sections, add product shots (plan 3.1, 2.3) (9245a9c)
    • web: hero product shot (plan 2.2) (e4a8056)
    • web: responsive marketing nav with language switcher (1cd39d3)
    • e2ee: activate Encrypted. Everywhere. — real E2EE, gate enforced (e55d5cc)
    • web: shared markdown pipeline with GFM tables + sanitize (10f365c)
    • e2ee: enforce E2EE_GATE_ENFORCED end-to-end (5f10325)
    • mobile: add QR key verification display + camera scan (fef902c)
    • shared: add QR payload codec for out-of-band key confirmation (40b43d1)
    • mobile: add out-of-band key verification UI (safety numbers) (b4d14fa)
    • e2ee: seal project keys to members + live key-grant refetch (97422f8)
    • web: add out-of-band key verification UI (safety numbers) (7776d32)
    • shared: add warn-only trust-pin state machine for key verification (99b9676)
    • shared: derive symmetric emoji safety fingerprint from key pair (1cc7e7b)
    • repo: flush E2EE session keys on lock and sign-out (506b8ee)
    • repo: route content edits through local-first CRUD path (d220529)
    • repo: wire e2ee encrypt/decrypt client path (f27b859)
    • tasks: surface start_date end-to-end and close the date-field parity gaps (R41) (2770687)
    • mobile: recompose content-free E2EE pushes on-device (f0364a6)
    • web: chunk large imports and warn past the cap (cacdda5)
    • e2ee: activate content-column encrypt/decrypt (b8c4ba8)
    • db: add tasks.recurrence_parent_id self-FK (0073/R40) (61142df)
    • e2ee: classify refuse-write retryable, toast lock (06b0c10)
    • bucket task_dependencies + goals by membership (1b6b81e)
    • e2ee: refuse write on locked E2EE project (daacb55)
    • e2ee: reconcile locally-minted project keys on session start (ac62c4c)
    • e2ee: push sealed project key on create (best-effort) (2007a98)
    • e2ee: seal per-project data key on create (754f382)
    • mobile: universal file import in settings (7618de7)
    • mobile: add dormant e2ee identity gate (83b4ad0)
    • web: universal file-upload import UI in settings (b7397cc)
    • universal file import + ungate bulk import (00aea76)
    • web: dormant identity gate + e2ee_gate i18n (2deaab3)
    • shared: spot-check + gate retry + identity probe (daf7493)
    • shared: two-phase mint + identity gate machine (cd0351a)
    • web,mobile: add e2ee identity backup callers + onboarding factories (99f3669)
    • mobile: polish-title chip on task detail (B20) (6e88554)
    • shared: add identity mint/restore onboarding service (b82624c)
    • web: polish-title chip on task detail (B20) (e5be124)
    • shared: add BIP39 recovery-phrase module (a74908d)
    • shared: polish-title chip hook + i18n keys (B20) (3bbda12)
    • shared: add polish_title paywall code + REST schema (B20) (1938ae8)
    • web: wire similar-tasks suggestions into quick-add and inbox (2c25f74)
    • mobile: add dormant e2ee key-store adapters (93b232e)
    • db: add local-only project_keys_cache table + builders (e72a80b)
    • shared: add dormant e2ee getDataKey resolver (3e55aeb)
    • db: repoint entity reads to _decrypted views (991b31b)
    • api: add tasks.similar semantic duplicate endpoint (73a1701)
    • shared: generalize content-decrypt read model to all encrypted tables (a542bed)
    • mobile: wire react-native-libsodium provider boot for e2ee (f18217b)
    • api: add Voyage embeddings client for B22 similar-tasks (ee4920e)
    • db: add pgvector task-embedding column for similar-tasks (B22) (e3ee856)
    • scrub PII from Sentry on all platforms (12f2799)
    • api: close shareProject enum oracle (560b9a4)
    • repoint task reads to tasks_decrypted view (149104f)
    • web,mobile: stamp UI locale into Clerk unsafeMetadata at sign-up (ec7cd50)
    • db: add server-only users.activation_bootstrapped_at (8df13e9)
    • i18n: add welcome-email and sample-project starter copy (dcbe78d)
    • web,mobile: wire content-decryption boot-ready gate (dormant) (bcf78d0)
    • shared: add content-decryption read model (dormant) (cf3953c)
    • api: widen data export to full GDPR sweep (a278c38)
    • db: anonymize activity_log actor on delete (R61) (5ea7615)
    • api: cancel live billing on account deletion (cd8f0af)
    • e2ee: add attachment download decrypt path (7ae42e2)
    • shared: add E2EE seam to attachment uploads (18de53a)
    • shared: encrypt attachment fileName/mimeType on upload (b77c86d)
    • shared: add attachment blob crypto envelope (c44346d)
    • web: implement standalone blog and changelog routes and verify all package tests (81979f3)
    • ui: translate reminder presets via label bag (27b9011)
    • link /pricing from every pricing surface (ea16ac7)
    • add the /pricing FAQ (b26fbda)
    • add a standalone /pricing page (e291f26)
    • e2ee: encrypt content columns on the sync-upload boundary (2d4c714)
    • sell Pro+AI through web checkout (f330b55)
    • e2ee: server-only key storage tables and REST router (Phase 2) (c710f77)
    • shared: add libsodium E2EE crypto core (259c5f8)
  • Fixes
    • desktop: route external opens through opener plugin (4362eac)
    • mobile: avoid keyboard on identity gate shell (60dd668)
    • count down phrase clipboard, wipe on deadline (1341187)
    • e2ee: drop the Node Buffer dependency from the shared base64 codec (d25671f)
    • e2ee: report identity gate failures instead of discarding them (810addd)
    • mobile: do not run the identity gate before Clerk resolves a session (f241d45)
    • web: stop habit detail pulling the whole UI barrel (2ffb66a)
    • web,api: merge landing UX remediation and the Clerk key restore (0e98d2b)
    • mobile: pin css-tree resolution to the Hermes-safe nested copy (215180c)
    • ui,web: AA-compliant muted token and accessible names on marketing (plan 4.1-4.2) (afc08fb)
    • ui: accessible accent ink via --color-primary-text (plan 4.1) (34b192f)
    • i18n: correct platform claims on landing and features pages (7ba07c1)
    • db: bound the client task-tree walks so a cyclic parent cannot spin (c229878)
    • mobile: migrate the widget keychain item only on a positive read (f06a515)
    • mobile: revoke the widget PAT that a re-mint replaces (16c5aa5)
    • db: derive the tasks test-table DDL from the client schema (154963a)
    • api: contain prompt injection and cap inbound-mail AI spend (90578b9)
    • mobile: keep the widget PAT out of device backups (R85) (ed835db)
    • e2ee: bound REST upsert content with envelope-aware cap (67f610a)
    • mobile: restore iOS keyboard suggestions on task title (f2229e4)
    • e2ee: reconcile unbounded content contract across the dev merge (0da2925)
    • mobile: make task delete local-first to kill list delay (2fb1cb8)
    • e2ee: bound refuse-write parking so an unresolvable op cannot wedge the FIFO (d616e21)
    • mobile: latch QR match once, mirroring web panel (44d33d1)
    • keep QR scanner alive after mismatch; stabilize web camera (58bc667)
    • shared: reject empty expected key in QR match (f466bc2)
    • mobile: RoundedFill for verify emoji grid cells (f836a31)
    • api: bind OAuth callbacks to the initiating browser (R66) (a9e96c0)
    • api: narrow the extension Connect PAT to least privilege (R62) (aa6bc36)
    • shared: jitter fractional keys so offline devices never collide (R22) (d7ea459)
    • shared: collapse legacy habit-log rows on upsert (6bbaaeb)
    • shared: make habit-log upsert atomic via deterministic id (d5ef8ca)
    • api: rate-limit and generalize 401 on the signed export download (4cf736a)
    • shared: scrub Sentry request headers, cookies and query string (c885990)
    • mobile: guard calendar htmlLink with isSafeHttpUrl (R59) (117e35d)
    • mobile: fail-closed onboarding gate with bounded retry (R28) (9b93342)
    • web,mobile: ref-escape getToken in useRestMutation (R24) (673e148)
    • shared: bound tasks/upsert title + description (R58) (f0af209)
    • e2ee: guard reconcile local read against throw (6c80bfe)
    • api: guard replay apply-mine vs collab edits (b65a86f)
    • api: bound bulk-import rate + cap import ref length (4cc44f3)
    • e2ee: keep recovery-phrase clipboard wipe on unmount (3f4cd1a)
    • shared: harden e2ee identity gate mint path (2da57cf)
    • ui: prune spent undoable-action ids (9119ae2)
    • api: harden CalDAV/Apple-Calendar sync (security audit) (eeade07)
    • shared: harden e2ee recovery against a hostile server (ca8a6c3)
    • mobile: multicast cold-start deep-link holder per consumer (R25) (b059600)
    • mobile: guard local-first task-create paths against double-tap (R10) (9ba0d09)
    • ui: stop toast swipe from stealing fast row taps (R23) (fe99c1a)
    • ui: keep per-action undo slots so rapid actions don't clobber (R47) (f18ed7f)
    • shared: clear decrypt shadow on envelope→plaintext (c808fb6)
    • shared: pass AEAD AAD as string for cross-platform libsodium (b3ddb21)
    • db: make 0069 FK add migrate-safe (NOT VALID + VALIDATE) (6d38f5d)
    • mobile: stub getOptional in batch test (88c5cdb)
    • e2ee: harden attachment encrypt/decrypt seam (828da79)
    • mobile: resolve silent failures when deleting project on mobile (5abcc7b)
    • web: route Pro lifetime CTA to the app, not the sign-up funnel (90c9422)
    • web: correct pricing page's false FAQ and platform claims (a1c14b9)
    • stop claiming the free plan covers a full Todoist import (a558d58)
    • shared: drop false AI and MCP claims from pricing copy (51cb94f)
    • shared: harden E2EE crypto core per security review (b1e7e41)
  • Other
    • shared: relocate buildMemberVerifications into shared crypto (23be34e)
    • e2ee: remove legacy AES-GCM local-write scheme (0b27b18)
    • shared: lift summarizeRows into import domain (15558e1)
    • harden e2ee 5a key-store adapters (8fdf8b6)

Android 1.9.0 — 2026-07-20 (versionCode 12)

  • Features
    • web: add analytics with GDPR consent chain (74b6017)
    • add real homepage waitlist with email capture (8ba7541)
    • add page-level SEO metadata to marketing pages (e036cdd)
    • analytics: add signup-source attribution and one activation event (cce07bc)
    • mobile: show over-plan-cap freeze on projects (068ccb5)
    • i18n: add switch.* keys for /switch/[tool] page (24dd265)
    • web: rewrite hero headline to offline/encrypted framing (f41c3b4)
    • web: fill download hero with real app screenshot (248dc35)
    • web: add download-page + landing-desktop i18n keys across 5 locales (a71b419)
    • api: route web checkout/portal/subscription through BillingProvider (d113aa3)
    • db: rename Stripe billing columns to provider-agnostic + add billing_provider (68bb5d8)
    • web: add /download page with OS-aware installer picker (79fac52)
    • implement Google Play Billing, Tauri public releases, and Web Sync conflict resolution (7e63fce)
    • ui: dismissable toast messages (web + mobile) (e447a89)
    • ui: dismissable toasts — always-visible ✕ (web + mobile) + swipe-to-dismiss (mobile) (5b34ae4)
    • mobile: wire sync-recovery panel into settings (7be00d7)
    • i18n: add a11y.dismiss_toast label across locales (a110808)
    • ui: add shared sync-recovery composite (aa3c5ae)
    • mobile: keep the view toggle mounted while project detail loads (4d1ca56)
    • mobile: debounce focus loading and skeleton the stats list (f04deff)
    • mobile: gate filter edit at the route so create mode stays unaffected (afb431b)
    • mobile: gate project edit on a layout-mirroring skeleton (e4daab0)
    • mobile: skeleton the members list and drop the unused loading string (c62873f)
    • mobile: replace list spinners with skeletons on sync-conflicts and blocked-users (5d2b71e)
    • mobile: mirror notification-prefs layout with form skeletons (29a6eec)
    • mobile: show task-detail skeleton instead of spinner while loading (219bcdc)
    • ui: add FormFieldSkeleton and FormGroupSkeleton primitives (c60a6d7)
    • mobile: fill haptic coverage gaps via central facade (8cfab42)
    • mobile: central haptics vocabulary + Sound & Haptics setting (3e3fdf8)
    • mobile: illustrate + rewire empty states + migrate filter-results empty to shared primitive (6e88d88)
    • ui: add empty-state illustration kit (6 spot illustrations) (e7c4829)
    • ui: add illustration palette hook (e56a4b7)
    • ui: add illustration prop to EmptyState primitive (ec78688)
    • shared: add jittered exponential backoff primitive (3dc6550)
    • mobile: show parent title on Today subtask rows (4c1a268)
    • ui: allow a parent-only task breadcrumb (a836920)
    • mobile: open-in-calendar row on task detail (475305f)
    • web: show calendar link on task details (62f26e6)
    • api: capture calendar htmlLink and expose it per task (fe3a525)
    • db: add html_link column to calendar_event_links (7684062)
    • mcp: OAuth hardening (MCP-1 consent disclosure, MCP-2 reachability+scope backstop) (0a15dfe)
    • mcp-shared: export reachable map + McpGrantScope alias (dcddb27)
    • mcp-shared: add canonical MCP reachability/scope map (1127b2f)
    • mcp-shared: add satisfiesScope rank check (264646c)
    • web: settings billing section + prod price-id boot gate (e2669b4)
    • habits: amber skipped-day color + glyph on habit calendar (c45ab2d)
    • web: task-row dependency indicators (Blocked by / Blocking) (ca17921)
    • triage: visible focused-row action bar on web (9ab4ceb)
    • mobile: triage move-to-project chip + picker + cascade (6096c2b)
    • shared: end-of-scope key + subtree walk for triage move (fbf2dfa)
    • web: triage move-to-project action (816bdf8)
    • db: project projection on triage deck query (3505912)
    • shared: triage project-suggestion selector (400a465)
    • i18n: triage move-to-project keys (7452550)
    • web: flag not-in-app users on admin entitlement grant (c27b7d0)
    • web: rename sidebar project-tree header to Your projects (6d7bea1)
    • api: resolve admin entitlement lookup via Clerk, provision on grant (2497007)
    • web: redesign 404 not-found page — Off the route (4a3ef73)
    • mobile: refetch badge on tasks.badgeCount sync-bus (55e56ee)
    • api: admin entitlement grant/strip mechanism (0d49067)
    • mobile: open Today from Home widget tap (962c0aa)
    • web: admin entitlements grant/strip page (141599f)
    • api: admin entitlements REST router (grant/revoke/lookup/list) (9c4e09b)
    • add manual entitlement source to wire union + settings label (9acf019)
    • mobile: open fullscreen focus route from the inline timer (e783fb1)
    • i18n: add focus.open_fullscreen_a11y across locales (cd0a449)
    • ui: add expand affordance to active focus timer (f137400)
    • mobile: present focus route as fullScreenModal (834f48a)
    • db: store-demo seed scenario for App Store screenshots (4778643)
    • web: minimal support page for ASC Support URL (04f7069)
    • web: populate review-and-reflect marketing story (bdd213f)
    • web: merge humanized filter chips + edit-in-modal (4884c9d)
    • web: humanize filter chips and edit filters in a modal (516b29a)
    • mobile: browse quick actions 3x2 grid (f4f8f6c)
    • humanize filter queries into clause chips (d6a3a08)
    • mobile: add the productivity stats screen (2ea7fb8)
    • i18n: add stats screen keys, drop the legacy streak string (73ea871)
    • mobile: show filter clause chips instead of the raw query (8307cbb)
    • ui: share the velocity-bar builder between web and mobile (68c08ad)
    • ui: add an InsightCards composite (7661acd)
    • ui: add StatTiles and PriorityDistribution composites (c58b635)
    • mobile: register stats.getProductivity in the REST registry (e73ace9)
    • mobile: row-parity Create project CTA in Browse search (668206e)
    • mobile: resolve and render filter summary chips (6597d11)
    • mobile: add the filter summary chip primitive (067ba2e)
    • mobile: row-parity Create project CTA in Browse search (cecc6cb)
    • shared: humanize a VisualFilter into clause descriptors (993e468)
    • web: drop the never-lose-a-thought story (6b7a66f)
    • mobile comment mentions (pill render + autocomplete) (a3a6939)
    • mobile: thread projectId into the comment composer's mention picker (0a4c486)
    • ui: three-row mention autocomplete above the mobile composer (51d3bfb)
    • merge comment edit and delete (ca9231e)
    • comment edit and delete on web and mobile (1c9b5eb)
    • db: throw on unknown column in drizzle writes (91e66ec)
    • db: add work-together-showcase seed scenario (cbe3809)
    • ui: add web/desktop Tooltip primitive (0b401bb)
    • web: describe the sync-status indicator with a tooltip (4e3ff9d)
    • ui: show tooltip labels on the web markdown toolbar (7a60fe1)
    • ui: add tooltip and shortcut props to IconButton (9f8d2be)
    • ui: add web Tooltip primitive (50e700d)
    • web: redesign due-time picker as hour·minute columns (e182e24)
    • web: label attach/detach + inline create in task-detail sidebar (60b76c3)
    • i18n: deadline picker + relative keys across 5 locales (0c8f758)
    • shared: time-aware deadline display + parseNaturalDateParts (959763e)
    • web: reminders in compose modal (8f4800b)
    • web: compose modal parity — time, recurrence, duration, labels, month grid (4552417)
    • web: float idle task-detail focus menu in a popover (a95488c)
    • mobile: add-task repeat menu parity with task-details (f530910)
    • mobile: reuse shared recurrence builder in add-task repeat chip (bec781f)
    • web: timezone region-city cascade picker in settings (e98d413)
    • web: replace native timezone select with region-city cascade (d07a6a4)
    • mobile: thread ai-fill phase from hook into the row (24077c4)
    • mobile: render ai-fill row across 4 phases with pulse + a11y (6c11774)
    • mobile: add ai-fill row phase→descriptor map (7249837)
    • mobile: add useSparklePulse reanimated loading pulse hook (e9f1010)
    • mobile: surface ai-fill phase (loading/success/error) from hook (b20f88b)
    • shared: add AI-fill loader i18n keys across locales (1e2d27c)
    • shared: add picker.time.* i18n keys across all locales (bcc5345)
    • attachments: mobile task + comment attachment UI (e9dad7a)
    • attachments: promote view/format helpers to shared, add comment slots (cd5ff47)
    • web: task-detail attachments UI with offline-queued uploads (36e0505)
    • shared: offline upload-queue orchestrator for attachments (45c9af3)
    • db: local-only attachment_uploads upload queue table (2496a1b)
    • api: presigned GET URL for viewing attachments (cbb8d70)
    • api: mint presigned PUT URL for attachment uploads (80353ae)
    • shared: attachment MIME rendering classifier (c65d7d1)
    • mobile: task-detail duration edit (377dd98)
    • mobile: add-task duration chip (7924764)
    • mobile: duration picker sheet and preset chip (65d6dc9)
    • shared: i18n keys for duration picker (035a0c3)
    • shared: duration wins over start+due window in event derivation (788edde)
    • shared: duration presets and parse/format helpers (314e23d)
    • i18n: merge hardcoded-string sweep into dev (bc367e7)
    • i18n: catch ternary literals, localize leaks (78b65c5)
    • i18n: route shared UI copy through labels bags (13f327c)
    • web: translate hardcoded UI strings via next-intl (23830c5)
    • mobile: route hardcoded UI copy through i18n (b06557e)
    • i18n: add 9 sweep keys for JSX-expression blind spots (199791a)
    • i18n: add sweep catalog keys + fix two i18n:scan gaps (024b0b2)
    • ui: show selected state on bold label color chips (9b16486)
    • mobile: merge task-detail remote calendar selector into dev (37359e4)
    • mobile: calendar routing selector on task detail (ebc6806)
    • db: expose target_calendar_id on task-by-id queries (249c54e)
    • web,mobile: surface calendar reconnect prompt for dead credentials (8de7582)
    • api: detect dead calendar credentials and surface reauth state (5d74a50)
    • mobile: add per-day "+ Add" button to Upcoming week days (70d1d84)
    • db: add reauth state columns to calendar_connections (653cc79)
  • Fixes
    • db: add missing ledger probe for 0068 waitlist_signups (d5a96b4)
    • api: close three plan-cap holes (a5b8fc6)
    • web: honor Priority support, unify support email (252c7d7)
    • web: honor Priority support, unify support email (af8d2dc)
    • db: register analytics_events as server-only for the upload guard (5128c48)
    • i18n: lowercase brand name to "etappi" in running copy (8967b63)
    • web: swap fake testimonial for builder note (b4e903d)
    • api: merge wave1 sync-seam replay authz mirror into dev (d01fdac)
    • api: reconcile wave1 sync-seam onto dev (7ea4506)
    • db: entitlement seed source 'stripe'->'web' + doc-comment sync (d5c2fe7)
    • shared: surrogate-safe inbound calendar text clamp (R14) (2f86689)
    • api: clamp inbound calendar title/description (R14) (944fb3c)
    • mobile: null-coalesce purchaseToken for verifyAndroidPurchase (add6d82)
    • reminders: correct relative reminder sign so recompute fires before due (981992a)
    • harden sync authz, billing, and supply chain (90fff5d)
    • ui: item owns toast auto-dismiss so expiry animates out (1cdff12)
    • mobile: drop duplicate Plan-with-AI CTA from projects empty state (fe69fac)
    • sync-recovery: localize drop reasons in the recovery readout (08c614e)
    • ui: address toast-dismiss review — timer leak, fling direction, dead export (d207906)
    • mobile: guard focus screens' debounce window against wrong-state flash on REST reads (5641873)
    • mobile: silence toast haptics; centralize completion buzz (c01a9e6)
    • mobile: tighten members.tsx hook grouping to stay under the 150 LOC cap (a5a8039)
    • mobile: make Sentry crash-free rate measurable (504a95f)
    • ui: treat empty breadcrumb halves as absent (1d50906)
    • i18n: de-anglicize and correct Ukrainian locale strings (30e7892)
    • api: stop VAPID keys from gating Expo push (e7bda80)
    • ui: render markdown paragraphs in foreground (cca939f)
    • calendar: owner-scope task link + https-only htmlLink (b6c92ec)
    • realtime: constrain resolveUserIds scope to canonical RealtimeScope schema (9e59300)
    • api: close entitlement reconciliation gaps (6717885)
    • web: restore include-archived toggle on /search (e8485d1)
    • shared: fold -/_ separators in log redaction key match (88124cc)
    • db: backdate habits seed createdAt to first log day (22eaf83)
    • focus: normalize legacy tz + surface stats fetch errors (8c4d29a)
    • shared: pluralize focus.running_a11y across locales (5216b67)
    • ui: pass useAnimatedStyle deps array on web (43f9923)
    • db: store plan_grace_started_at as timestamptz (d9a97ed)
    • billing: consume resolved access on the client, harden grace UI (7b2bcff)
    • api: close the Stripe webhook idempotency crash window (3091a95)
    • api: surface resolved plan authority on users.me (6125cf6)
    • mobile: fire draft reminders after sheet closes (4d2abed)
    • mobile: label sync-conflict toast with the task title, not "tasks" (1c61131)
    • ui: rotate focus chevron on expand, match app icon (f6b9605)
    • db: backdate store-demo habits so streaks read 5 (83e9458)
    • db: author owner users row in stats-showcase seed (9449343)
    • ui: centre Tooltip anchor on cross axis (09d74b9)
    • i18n: fold suffix plurals into ICU plural messages (f9c5418)
    • i18n: fold suffix plurals into ICU plural messages (79666b7)
    • mobile: drop the duplicate colour dot from the filter header (16fc472)
    • ui: make the shared stats composites survive a phone-width column (3eea6b2)
    • format sheet dismiss label at call site (bf09452)
    • stats: compare the REST error against null, not undefined (c180041)
    • ui: let stats charts declare what is behind them (57e80e3)
    • mobile: mirror evaluator project matching in summary chips (88f39c8)
    • mobile: land ICU plurals and the Hermes Intl.Locale polyfill (e983d00)
    • mobile: polyfill Intl.Locale so ICU plurals resolve on Hermes (fabd9c8)
    • mobile: make summary chip testID a prop and pin chip colour map (7c0f251)
    • i18n: use genitive plural for uk assignee count fallback (b73ca57)
    • shared: lex all-numeric UUIDs as idents, not numbers (adc5f51)
    • i18n: render ICU plurals on mobile via i18next-icu (1cad66d)
    • mobile: free up viewport for Browse search results (b9e3fc3)
    • mobile: let Browse search match the Inbox project (cdaeea9)
    • mobile: route plan-gated filter save to the paywall (9326b88)
    • mobile: lift the label creator above the keyboard (3703fc8)
    • mobile: reveal the comment composer when the keyboard opens (67d3f2f)
    • mobile: drop the bogus keyboard offset on task detail (28ecd7b)
    • ui: float the mobile mention panel above the composer (a8b8afa)
    • ui: bound the iOS mention pill and pin the row typeface (d125faa)
    • mobile: resolve comment author names instead of labelling every comment "You" (09899f0)
    • sync comment threads to all project members, not just author (d6f23b6)
    • web: count completed tasks while collapsed (65a6190)
    • mobile: reserve FAB height in scroll insets (fe8b505)
    • ui: use tooltip as the native icon-button accessibilityLabel fallback (c072c11)
    • ui: harden tooltip dismiss + close review gaps (cb76b23)
    • mobile: unnest label hue chip Pressable (097420f)
    • i18n: plural-correct deadline relative labels (a627eb5)
    • shared: compare deadline by calendar day in triage + filter (327c305)
    • web: guard compose reminders vs orphan+race (19e7052)
    • i18n: de-calque uk 'included' phrasing (f1aafa3)
    • i18n: correct uk Russianisms and normalize loans (8af3e12)
    • i18n: de-russify and normalize uk locale strings (e25a0cb)
    • i18n: de-loan uk account + shortcuts terms (0341b41)
    • i18n: harmonize uk focus vocabulary (f378e16)
    • i18n: reframe uk deps strings to blocking (f5fcf4b)
    • mobile: lazy-import expo-document-picker (ec20d2b)
    • i18n: polish pl/de/fr landing calques (offline-first, calm) (ba86381)
    • i18n: polish Ukrainian lexical calques in landing copy (2b8a422)
    • mobile: merge ai-fill empty-state feedback and persistent hide (4815059)
    • mobile: ai-fill empty-state feedback and persistent hide (65678eb)
    • i18n: remove English calques and reconcile drifted strings in uk/pl/de/fr (2b8efd5)
    • ui: let Popover trigger own the open/close toggle (744ddc5)
    • mobile: resolve ai-fill zero-chip dead-end (60a33e0)
    • ui: decouple offline banner visual from screen-reader debounce (6cef6e3)
    • mobile: optimistic reminder preset selection (81618f7)
    • ui: portal Popover to escape stacking traps (2af6b81)
    • harden task attachments (5ce3370)
    • attachments: close replay cross-tenant read + XSS (16f8533)
    • mobile: wire compose duration + picker layout (ee62eee)
    • i18n: align en duration.remove with locales (3f118e8)
    • shared: cap task duration at 24h across boundaries (4013729)
    • mobile: pixel maxHeight for label picker list (7ef7f86)
    • mobile: keep picker search above keyboard (f73ae01)
    • mobile: derive inbox id synchronously (d30e87f)
    • mobile: theme-accent done days + hug Edit header capsule (73ef020)
    • ui: enlarge task checkbox touch targets to 44/48dp (4025dc7)
  • Other
    • shared: drop orphaned settings.subscription.source.stripe i18n label (a8886bd)
    • api,shared,mobile,web: entitlement source 'stripe'->'web' (provider-neutral wire enum) (770e844)
    • mobile: debounce loading gates on the six remaining raw-isLoading screens (f9e57a1)
    • mobile: use nativeSafeRole for task-detail loading role (82ebd7a)
    • mobile: route haptic call sites through central facade (2e4086d)
    • mobile: jitter realtime reconnect backoff (06ccb17)
    • db: split store-demo.rows into domain siblings under 150-LOC cap (5ef612d)
    • mobile: drop dead accent/wide/TileDef after grid split (87439f7)
    • ui: extract a generic BarChart from the focus stats chart (d5e6149)
    • mobile: extract root stack screens to a sibling module (bc5d2a2)
    • relocate mention logic to shared, pill render to ui (ea86dd9)
    • db: normalize prettier + split work-together seed under LOC cap (2f35f93)
    • mobile: extract applySuggestionsToEmpty from ai-fill hook (e080b41)

iOS 1.17.0 — 2026-07-20 (build 64)

  • Features
    • web: add analytics with GDPR consent chain (74b6017)
    • add real homepage waitlist with email capture (8ba7541)
    • add page-level SEO metadata to marketing pages (e036cdd)
    • analytics: add signup-source attribution and one activation event (cce07bc)
    • mobile: show over-plan-cap freeze on projects (068ccb5)
    • i18n: add switch.* keys for /switch/[tool] page (24dd265)
    • web: rewrite hero headline to offline/encrypted framing (f41c3b4)
    • web: fill download hero with real app screenshot (248dc35)
    • web: add download-page + landing-desktop i18n keys across 5 locales (a71b419)
    • api: route web checkout/portal/subscription through BillingProvider (d113aa3)
    • db: rename Stripe billing columns to provider-agnostic + add billing_provider (68bb5d8)
    • web: add /download page with OS-aware installer picker (79fac52)
    • implement Google Play Billing, Tauri public releases, and Web Sync conflict resolution (7e63fce)
    • ui: dismissable toast messages (web + mobile) (e447a89)
    • ui: dismissable toasts — always-visible ✕ (web + mobile) + swipe-to-dismiss (mobile) (5b34ae4)
    • mobile: wire sync-recovery panel into settings (7be00d7)
    • i18n: add a11y.dismiss_toast label across locales (a110808)
    • ui: add shared sync-recovery composite (aa3c5ae)
    • mobile: keep the view toggle mounted while project detail loads (4d1ca56)
    • mobile: debounce focus loading and skeleton the stats list (f04deff)
    • mobile: gate filter edit at the route so create mode stays unaffected (afb431b)
    • mobile: gate project edit on a layout-mirroring skeleton (e4daab0)
    • mobile: skeleton the members list and drop the unused loading string (c62873f)
    • mobile: replace list spinners with skeletons on sync-conflicts and blocked-users (5d2b71e)
    • mobile: mirror notification-prefs layout with form skeletons (29a6eec)
    • mobile: show task-detail skeleton instead of spinner while loading (219bcdc)
    • ui: add FormFieldSkeleton and FormGroupSkeleton primitives (c60a6d7)
    • mobile: fill haptic coverage gaps via central facade (8cfab42)
    • mobile: central haptics vocabulary + Sound & Haptics setting (3e3fdf8)
    • mobile: illustrate + rewire empty states + migrate filter-results empty to shared primitive (6e88d88)
    • ui: add empty-state illustration kit (6 spot illustrations) (e7c4829)
    • ui: add illustration palette hook (e56a4b7)
    • ui: add illustration prop to EmptyState primitive (ec78688)
    • shared: add jittered exponential backoff primitive (3dc6550)
    • mobile: show parent title on Today subtask rows (4c1a268)
    • ui: allow a parent-only task breadcrumb (a836920)
    • mobile: open-in-calendar row on task detail (475305f)
    • web: show calendar link on task details (62f26e6)
    • api: capture calendar htmlLink and expose it per task (fe3a525)
    • db: add html_link column to calendar_event_links (7684062)
    • mcp: OAuth hardening (MCP-1 consent disclosure, MCP-2 reachability+scope backstop) (0a15dfe)
    • mcp-shared: export reachable map + McpGrantScope alias (dcddb27)
    • mcp-shared: add canonical MCP reachability/scope map (1127b2f)
    • mcp-shared: add satisfiesScope rank check (264646c)
    • web: settings billing section + prod price-id boot gate (e2669b4)
    • habits: amber skipped-day color + glyph on habit calendar (c45ab2d)
    • web: task-row dependency indicators (Blocked by / Blocking) (ca17921)
    • triage: visible focused-row action bar on web (9ab4ceb)
    • mobile: triage move-to-project chip + picker + cascade (6096c2b)
    • shared: end-of-scope key + subtree walk for triage move (fbf2dfa)
    • web: triage move-to-project action (816bdf8)
    • db: project projection on triage deck query (3505912)
    • shared: triage project-suggestion selector (400a465)
    • i18n: triage move-to-project keys (7452550)
    • web: flag not-in-app users on admin entitlement grant (c27b7d0)
    • web: rename sidebar project-tree header to Your projects (6d7bea1)
    • api: resolve admin entitlement lookup via Clerk, provision on grant (2497007)
    • web: redesign 404 not-found page — Off the route (4a3ef73)
    • mobile: refetch badge on tasks.badgeCount sync-bus (55e56ee)
    • api: admin entitlement grant/strip mechanism (0d49067)
    • mobile: open Today from Home widget tap (962c0aa)
    • web: admin entitlements grant/strip page (141599f)
    • api: admin entitlements REST router (grant/revoke/lookup/list) (9c4e09b)
    • add manual entitlement source to wire union + settings label (9acf019)
  • Fixes
    • db: add missing ledger probe for 0068 waitlist_signups (d5a96b4)
    • api: close three plan-cap holes (a5b8fc6)
    • web: honor Priority support, unify support email (252c7d7)
    • web: honor Priority support, unify support email (af8d2dc)
    • db: register analytics_events as server-only for the upload guard (5128c48)
    • i18n: lowercase brand name to "etappi" in running copy (8967b63)
    • web: swap fake testimonial for builder note (b4e903d)
    • api: merge wave1 sync-seam replay authz mirror into dev (d01fdac)
    • api: reconcile wave1 sync-seam onto dev (7ea4506)
    • db: entitlement seed source 'stripe'->'web' + doc-comment sync (d5c2fe7)
    • shared: surrogate-safe inbound calendar text clamp (R14) (2f86689)
    • api: clamp inbound calendar title/description (R14) (944fb3c)
    • mobile: null-coalesce purchaseToken for verifyAndroidPurchase (add6d82)
    • reminders: correct relative reminder sign so recompute fires before due (981992a)
    • harden sync authz, billing, and supply chain (90fff5d)
    • ui: item owns toast auto-dismiss so expiry animates out (1cdff12)
    • mobile: drop duplicate Plan-with-AI CTA from projects empty state (fe69fac)
    • sync-recovery: localize drop reasons in the recovery readout (08c614e)
    • ui: address toast-dismiss review — timer leak, fling direction, dead export (d207906)
    • mobile: guard focus screens' debounce window against wrong-state flash on REST reads (5641873)
    • mobile: silence toast haptics; centralize completion buzz (c01a9e6)
    • mobile: tighten members.tsx hook grouping to stay under the 150 LOC cap (a5a8039)
    • mobile: make Sentry crash-free rate measurable (504a95f)
    • ui: treat empty breadcrumb halves as absent (1d50906)
    • i18n: de-anglicize and correct Ukrainian locale strings (30e7892)
    • api: stop VAPID keys from gating Expo push (e7bda80)
    • ui: render markdown paragraphs in foreground (cca939f)
    • calendar: owner-scope task link + https-only htmlLink (b6c92ec)
    • realtime: constrain resolveUserIds scope to canonical RealtimeScope schema (9e59300)
    • api: close entitlement reconciliation gaps (6717885)
    • web: restore include-archived toggle on /search (e8485d1)
    • shared: fold -/_ separators in log redaction key match (88124cc)
    • db: backdate habits seed createdAt to first log day (22eaf83)
    • focus: normalize legacy tz + surface stats fetch errors (8c4d29a)
    • shared: pluralize focus.running_a11y across locales (5216b67)
    • ui: pass useAnimatedStyle deps array on web (43f9923)
    • db: store plan_grace_started_at as timestamptz (d9a97ed)
    • billing: consume resolved access on the client, harden grace UI (7b2bcff)
    • api: close the Stripe webhook idempotency crash window (3091a95)
    • api: surface resolved plan authority on users.me (6125cf6)
  • Other
    • shared: drop orphaned settings.subscription.source.stripe i18n label (a8886bd)
    • api,shared,mobile,web: entitlement source 'stripe'->'web' (provider-neutral wire enum) (770e844)
    • mobile: debounce loading gates on the six remaining raw-isLoading screens (f9e57a1)
    • mobile: use nativeSafeRole for task-detail loading role (82ebd7a)
    • mobile: route haptic call sites through central facade (2e4086d)
    • mobile: jitter realtime reconnect backoff (06ccb17)

iOS 1.16.0 — 2026-07-12 (build 63)

  • Features
    • mobile: open fullscreen focus route from the inline timer (e783fb1)
    • i18n: add focus.open_fullscreen_a11y across locales (cd0a449)
    • ui: add expand affordance to active focus timer (f137400)
    • mobile: present focus route as fullScreenModal (834f48a)
    • db: store-demo seed scenario for App Store screenshots (4778643)
    • web: minimal support page for ASC Support URL (04f7069)
    • web: populate review-and-reflect marketing story (bdd213f)
    • web: merge humanized filter chips + edit-in-modal (4884c9d)
    • web: humanize filter chips and edit filters in a modal (516b29a)
    • mobile: browse quick actions 3x2 grid (f4f8f6c)
    • humanize filter queries into clause chips (d6a3a08)
    • mobile: add the productivity stats screen (2ea7fb8)
    • i18n: add stats screen keys, drop the legacy streak string (73ea871)
    • mobile: show filter clause chips instead of the raw query (8307cbb)
    • ui: share the velocity-bar builder between web and mobile (68c08ad)
    • ui: add an InsightCards composite (7661acd)
    • ui: add StatTiles and PriorityDistribution composites (c58b635)
    • mobile: register stats.getProductivity in the REST registry (e73ace9)
    • mobile: row-parity Create project CTA in Browse search (668206e)
    • mobile: resolve and render filter summary chips (6597d11)
    • mobile: add the filter summary chip primitive (067ba2e)
    • mobile: row-parity Create project CTA in Browse search (cecc6cb)
    • shared: humanize a VisualFilter into clause descriptors (993e468)
    • web: drop the never-lose-a-thought story (6b7a66f)
    • mobile comment mentions (pill render + autocomplete) (a3a6939)
    • mobile: thread projectId into the comment composer's mention picker (0a4c486)
    • ui: three-row mention autocomplete above the mobile composer (51d3bfb)
    • merge comment edit and delete (ca9231e)
    • comment edit and delete on web and mobile (1c9b5eb)
    • db: throw on unknown column in drizzle writes (91e66ec)
    • db: add work-together-showcase seed scenario (cbe3809)
    • ui: add web/desktop Tooltip primitive (0b401bb)
    • web: describe the sync-status indicator with a tooltip (4e3ff9d)
    • ui: show tooltip labels on the web markdown toolbar (7a60fe1)
    • ui: add tooltip and shortcut props to IconButton (9f8d2be)
    • ui: add web Tooltip primitive (50e700d)
    • web: redesign due-time picker as hour·minute columns (e182e24)
    • web: label attach/detach + inline create in task-detail sidebar (60b76c3)
    • i18n: deadline picker + relative keys across 5 locales (0c8f758)
    • shared: time-aware deadline display + parseNaturalDateParts (959763e)
    • web: reminders in compose modal (8f4800b)
    • web: compose modal parity — time, recurrence, duration, labels, month grid (4552417)
    • web: float idle task-detail focus menu in a popover (a95488c)
    • mobile: add-task repeat menu parity with task-details (f530910)
    • mobile: reuse shared recurrence builder in add-task repeat chip (bec781f)
    • web: timezone region-city cascade picker in settings (e98d413)
    • web: replace native timezone select with region-city cascade (d07a6a4)
    • mobile: thread ai-fill phase from hook into the row (24077c4)
    • mobile: render ai-fill row across 4 phases with pulse + a11y (6c11774)
    • mobile: add ai-fill row phase→descriptor map (7249837)
    • mobile: add useSparklePulse reanimated loading pulse hook (e9f1010)
    • mobile: surface ai-fill phase (loading/success/error) from hook (b20f88b)
    • shared: add AI-fill loader i18n keys across locales (1e2d27c)
    • shared: add picker.time.* i18n keys across all locales (bcc5345)
  • Fixes
    • mobile: fire draft reminders after sheet closes (4d2abed)
    • mobile: label sync-conflict toast with the task title, not "tasks" (1c61131)
    • ui: rotate focus chevron on expand, match app icon (f6b9605)
    • db: backdate store-demo habits so streaks read 5 (83e9458)
    • db: author owner users row in stats-showcase seed (9449343)
    • ui: centre Tooltip anchor on cross axis (09d74b9)
    • i18n: fold suffix plurals into ICU plural messages (f9c5418)
    • i18n: fold suffix plurals into ICU plural messages (79666b7)
    • mobile: drop the duplicate colour dot from the filter header (16fc472)
    • ui: make the shared stats composites survive a phone-width column (3eea6b2)
    • format sheet dismiss label at call site (bf09452)
    • stats: compare the REST error against null, not undefined (c180041)
    • ui: let stats charts declare what is behind them (57e80e3)
    • mobile: mirror evaluator project matching in summary chips (88f39c8)
    • mobile: land ICU plurals and the Hermes Intl.Locale polyfill (e983d00)
    • mobile: polyfill Intl.Locale so ICU plurals resolve on Hermes (fabd9c8)
    • mobile: make summary chip testID a prop and pin chip colour map (7c0f251)
    • i18n: use genitive plural for uk assignee count fallback (b73ca57)
    • shared: lex all-numeric UUIDs as idents, not numbers (adc5f51)
    • i18n: render ICU plurals on mobile via i18next-icu (1cad66d)
    • mobile: free up viewport for Browse search results (b9e3fc3)
    • mobile: let Browse search match the Inbox project (cdaeea9)
    • mobile: route plan-gated filter save to the paywall (9326b88)
    • mobile: lift the label creator above the keyboard (3703fc8)
    • mobile: reveal the comment composer when the keyboard opens (67d3f2f)
    • mobile: drop the bogus keyboard offset on task detail (28ecd7b)
    • ui: float the mobile mention panel above the composer (a8b8afa)
    • ui: bound the iOS mention pill and pin the row typeface (d125faa)
    • mobile: resolve comment author names instead of labelling every comment "You" (09899f0)
    • sync comment threads to all project members, not just author (d6f23b6)
    • web: count completed tasks while collapsed (65a6190)
    • mobile: reserve FAB height in scroll insets (fe8b505)
    • ui: use tooltip as the native icon-button accessibilityLabel fallback (c072c11)
    • ui: harden tooltip dismiss + close review gaps (cb76b23)
    • mobile: unnest label hue chip Pressable (097420f)
    • i18n: plural-correct deadline relative labels (a627eb5)
    • shared: compare deadline by calendar day in triage + filter (327c305)
    • web: guard compose reminders vs orphan+race (19e7052)
    • i18n: de-calque uk 'included' phrasing (f1aafa3)
    • i18n: correct uk Russianisms and normalize loans (8af3e12)
    • i18n: de-russify and normalize uk locale strings (e25a0cb)
    • i18n: de-loan uk account + shortcuts terms (0341b41)
    • i18n: harmonize uk focus vocabulary (f378e16)
    • i18n: reframe uk deps strings to blocking (f5fcf4b)
    • mobile: lazy-import expo-document-picker (ec20d2b)
    • i18n: polish pl/de/fr landing calques (offline-first, calm) (ba86381)
    • i18n: polish Ukrainian lexical calques in landing copy (2b8a422)
    • mobile: merge ai-fill empty-state feedback and persistent hide (4815059)
    • mobile: ai-fill empty-state feedback and persistent hide (65678eb)
    • i18n: remove English calques and reconcile drifted strings in uk/pl/de/fr (2b8efd5)
    • ui: let Popover trigger own the open/close toggle (744ddc5)
    • mobile: resolve ai-fill zero-chip dead-end (60a33e0)
  • Other
    • db: split store-demo.rows into domain siblings under 150-LOC cap (5ef612d)
    • mobile: drop dead accent/wide/TileDef after grid split (87439f7)
    • ui: extract a generic BarChart from the focus stats chart (d5e6149)
    • mobile: extract root stack screens to a sibling module (bc5d2a2)
    • relocate mention logic to shared, pill render to ui (ea86dd9)
    • db: normalize prettier + split work-together seed under LOC cap (2f35f93)
    • mobile: extract applySuggestionsToEmpty from ai-fill hook (e080b41)

iOS 1.15.0 — 2026-07-05 (build 62)

  • Features
    • attachments: mobile task + comment attachment UI (e9dad7a)
    • attachments: promote view/format helpers to shared, add comment slots (cd5ff47)
    • web: task-detail attachments UI with offline-queued uploads (36e0505)
    • shared: offline upload-queue orchestrator for attachments (45c9af3)
    • db: local-only attachment_uploads upload queue table (2496a1b)
    • api: presigned GET URL for viewing attachments (cbb8d70)
    • api: mint presigned PUT URL for attachment uploads (80353ae)
    • shared: attachment MIME rendering classifier (c65d7d1)
    • mobile: task-detail duration edit (377dd98)
    • mobile: add-task duration chip (7924764)
    • mobile: duration picker sheet and preset chip (65d6dc9)
    • shared: i18n keys for duration picker (035a0c3)
    • shared: duration wins over start+due window in event derivation (788edde)
    • shared: duration presets and parse/format helpers (314e23d)
    • i18n: merge hardcoded-string sweep into dev (bc367e7)
    • i18n: catch ternary literals, localize leaks (78b65c5)
    • i18n: route shared UI copy through labels bags (13f327c)
    • web: translate hardcoded UI strings via next-intl (23830c5)
    • mobile: route hardcoded UI copy through i18n (b06557e)
    • i18n: add 9 sweep keys for JSX-expression blind spots (199791a)
    • i18n: add sweep catalog keys + fix two i18n:scan gaps (024b0b2)
    • ui: show selected state on bold label color chips (9b16486)
    • mobile: merge task-detail remote calendar selector into dev (37359e4)
    • mobile: calendar routing selector on task detail (ebc6806)
    • db: expose target_calendar_id on task-by-id queries (249c54e)
    • web,mobile: surface calendar reconnect prompt for dead credentials (8de7582)
    • api: detect dead calendar credentials and surface reauth state (5d74a50)
    • mobile: add per-day "+ Add" button to Upcoming week days (70d1d84)
    • db: add reauth state columns to calendar_connections (653cc79)
  • Fixes
    • ui: decouple offline banner visual from screen-reader debounce (6cef6e3)
    • mobile: optimistic reminder preset selection (81618f7)
    • ui: portal Popover to escape stacking traps (2af6b81)
    • harden task attachments (5ce3370)
    • attachments: close replay cross-tenant read + XSS (16f8533)
    • mobile: wire compose duration + picker layout (ee62eee)
    • i18n: align en duration.remove with locales (3f118e8)
    • shared: cap task duration at 24h across boundaries (4013729)
    • mobile: pixel maxHeight for label picker list (7ef7f86)
    • mobile: keep picker search above keyboard (f73ae01)
    • mobile: derive inbox id synchronously (d30e87f)
    • mobile: theme-accent done days + hug Edit header capsule (73ef020)
    • ui: enlarge task checkbox touch targets to 44/48dp (4025dc7)
    • deploy: gate Vercel deploys behind schema migrations (fe374a1)

Android 1.8.0 — 2026-07-01 (versionCode 11)

  • Features
    • project-picker search — filtered-tree picker with gated search (mobile + web) (bdba1f8)
    • web: project-picker search — gated FilterInput + filtered-tree highlight (e6a172f)
    • mobile: project-picker search — gated FilterInput + filtered-tree highlight (8a8bd7a)
    • i18n: project-picker search strings (5 locales) (d0cc679)
    • shared: filtered-tree project-picker search core (1f5fd57)
    • mobile: merge locale-aware due-time preset labels into dev (fbe06f8)
    • mobile: derive due-time preset labels from locale hour-cycle (d562635)
    • mobile: de-emphasize "fill empty with AI" row in compose (17e4c80)
    • web: merge notifications settings restyle to match Preferences (9e97aaf)
    • web: restyle notifications settings to match preferences (ddd6b0e)
    • web: redesign settings preferences as compact auto-saving cards (15f5dad)
    • web: redesign settings modal (Direction C — unified & airy) (cc3741b)
    • db: add capture-showcase seed scenario (b71aff3)
    • web: give settings profile pane a manage-account action row (d797ec5)
    • web: always show Today section in Upcoming list (7b29d6a)
    • web: rebalance task modal type scale to 18/14/12 (2b54d26)
    • web: drag-to-reschedule tasks in the Upcoming list view (455ac2d)
    • mobile: board, project, decompose create local-first (edb9a93)
    • mobile: compose writes task local-first (b4bd1f4)
    • shared: createTask binds description + appends position (46272ef)
    • web: day-grouped collapsible Upcoming list view (4a197f9)
    • web: drop Day view from Upcoming page (f53b8c3)
    • web: disable Team sidebar link with Coming soon badge (2eb3b82)
    • web: show web + mobile together in stories (paired device frames) (085f721)
    • web: hero subheadline slogan — Organize your everyday (a7ee44d)
    • web: add stories portal i18n copy (en + de/fr/pl/uk) (43d9b32)
  • Fixes
    • deploy: gate Vercel deploys behind schema migrations (fe374a1)
    • mobile: lengthen offline-banner debounce to 8s (70c2438)
    • mobile: legible add-task empty chips (fd943ac)
    • shared: preserve UTF-16 length when folding emoji in picker filter (fe2f695)
    • ui: theme OfflineIndicator banner via Typography (1330e03)
    • mobile: close add-task modal before reminder write (c28f50a)
    • ui: white quick-add chip text, drop seconds (371f843)
    • web: merge offline indicator in-column banner into dev (5595767)
    • web: show offline indicator as in-column banner, sr-only when online (077bb2c)
    • web: color due/deadline labels via inline style not className (8cd5009)
    • shared: keep brand pun 'etappi' literal across locales (5c7bebf)
    • shared: scope top-level append to parent_id IS NULL (6806a87)
    • shared: createTask append ignores null-default slot (c977520)
    • web: soften plan-your-week shot-2 alt to fit web+mobile (c0dbf84)
    • web: habit recurrence label + segmented control (ac4d892)
  • Other
    • web: locale-aware custom tile month + memoize due-tiles (d7b2fae)
    • shared: promote day-presets math from mobile to @etappi/shared (432a7ba)
    • move pointerEvents prop to style.pointerEvents (3f1a1ef)

iOS 1.14.0 — 2026-06-30 (build 61)

  • Features
    • project-picker search — filtered-tree picker with gated search (mobile + web) (bdba1f8)
    • web: project-picker search — gated FilterInput + filtered-tree highlight (e6a172f)
    • mobile: project-picker search — gated FilterInput + filtered-tree highlight (8a8bd7a)
    • i18n: project-picker search strings (5 locales) (d0cc679)
    • shared: filtered-tree project-picker search core (1f5fd57)
    • mobile: merge locale-aware due-time preset labels into dev (fbe06f8)
    • mobile: derive due-time preset labels from locale hour-cycle (d562635)
    • mobile: de-emphasize "fill empty with AI" row in compose (17e4c80)
    • web: merge notifications settings restyle to match Preferences (9e97aaf)
    • web: restyle notifications settings to match preferences (ddd6b0e)
    • web: redesign settings preferences as compact auto-saving cards (15f5dad)
    • web: redesign settings modal (Direction C — unified & airy) (cc3741b)
    • db: add capture-showcase seed scenario (b71aff3)
    • web: give settings profile pane a manage-account action row (d797ec5)
    • web: always show Today section in Upcoming list (7b29d6a)
    • web: rebalance task modal type scale to 18/14/12 (2b54d26)
    • web: drag-to-reschedule tasks in the Upcoming list view (455ac2d)
    • mobile: board, project, decompose create local-first (edb9a93)
    • mobile: compose writes task local-first (b4bd1f4)
    • shared: createTask binds description + appends position (46272ef)
    • web: day-grouped collapsible Upcoming list view (4a197f9)
    • web: drop Day view from Upcoming page (f53b8c3)
    • web: disable Team sidebar link with Coming soon badge (2eb3b82)
    • web: show web + mobile together in stories (paired device frames) (085f721)
    • web: hero subheadline slogan — Organize your everyday (a7ee44d)
    • web: add stories portal i18n copy (en + de/fr/pl/uk) (43d9b32)
    • mobile,web: calendar picker + day-planner time-blocks (ada8d7c)
    • api: multi-calendar routing, time-blocks, per-calendar color (d428f39)
    • mobile: create labels from the add-task picker sheet (052951d)
    • ui: add avoidKeyboard prop to BottomSheetShell (811802f)
    • db: add tasks.targetCalendarId + deriveEventTime (bbe53ac)
  • Fixes
    • mobile: lengthen offline-banner debounce to 8s (70c2438)
    • mobile: legible add-task empty chips (fd943ac)
    • shared: preserve UTF-16 length when folding emoji in picker filter (fe2f695)
    • ui: theme OfflineIndicator banner via Typography (1330e03)
    • mobile: close add-task modal before reminder write (c28f50a)
    • ui: white quick-add chip text, drop seconds (371f843)
    • web: merge offline indicator in-column banner into dev (5595767)
    • web: show offline indicator as in-column banner, sr-only when online (077bb2c)
    • web: color due/deadline labels via inline style not className (8cd5009)
    • shared: keep brand pun 'etappi' literal across locales (5c7bebf)
    • shared: scope top-level append to parent_id IS NULL (6806a87)
    • shared: createTask append ignores null-default slot (c977520)
    • web: soften plan-your-week shot-2 alt to fit web+mobile (c0dbf84)
    • web: habit recurrence label + segmented control (ac4d892)
    • mobile: gate offline banner on real reachability, not sync status (0b7e8a8)
    • mobile: reserve top-bar height before Today loading skeleton (0bbc027)
    • calendar: preserve start fields in deriveEventTime, 15m no-duration fallback (e28a39b)
    • mobile: guard label create against double-submit (968c547)
  • Other
    • web: locale-aware custom tile month + memoize due-tiles (d7b2fae)
    • shared: promote day-presets math from mobile to @etappi/shared (432a7ba)
    • move pointerEvents prop to style.pointerEvents (3f1a1ef)
    • mobile: extract insertLocalLabel helper (e8e9a05)

iOS 1.14.0 — 2026-06-30 (build 61)

  • Features
    • project-picker search — filtered-tree picker with gated search (mobile + web) (bdba1f8)
    • web: project-picker search — gated FilterInput + filtered-tree highlight (e6a172f)
    • mobile: project-picker search — gated FilterInput + filtered-tree highlight (8a8bd7a)
    • i18n: project-picker search strings (5 locales) (d0cc679)
    • shared: filtered-tree project-picker search core (1f5fd57)
    • mobile: merge locale-aware due-time preset labels into dev (fbe06f8)
    • mobile: derive due-time preset labels from locale hour-cycle (d562635)
    • mobile: de-emphasize "fill empty with AI" row in compose (17e4c80)
    • web: merge notifications settings restyle to match Preferences (9e97aaf)
    • web: restyle notifications settings to match preferences (ddd6b0e)
    • web: redesign settings preferences as compact auto-saving cards (15f5dad)
    • web: redesign settings modal (Direction C — unified & airy) (cc3741b)
    • db: add capture-showcase seed scenario (b71aff3)
    • web: give settings profile pane a manage-account action row (d797ec5)
    • web: always show Today section in Upcoming list (7b29d6a)
    • web: rebalance task modal type scale to 18/14/12 (2b54d26)
    • web: drag-to-reschedule tasks in the Upcoming list view (455ac2d)
    • mobile: board, project, decompose create local-first (edb9a93)
    • mobile: compose writes task local-first (b4bd1f4)
    • shared: createTask binds description + appends position (46272ef)
    • web: day-grouped collapsible Upcoming list view (4a197f9)
    • web: drop Day view from Upcoming page (f53b8c3)
    • web: disable Team sidebar link with Coming soon badge (2eb3b82)
    • web: show web + mobile together in stories (paired device frames) (085f721)
    • web: hero subheadline slogan — Organize your everyday (a7ee44d)
    • web: add stories portal i18n copy (en + de/fr/pl/uk) (43d9b32)
    • mobile,web: calendar picker + day-planner time-blocks (ada8d7c)
    • api: multi-calendar routing, time-blocks, per-calendar color (d428f39)
    • mobile: create labels from the add-task picker sheet (052951d)
    • ui: add avoidKeyboard prop to BottomSheetShell (811802f)
    • db: add tasks.targetCalendarId + deriveEventTime (bbe53ac)
  • Fixes
    • mobile: lengthen offline-banner debounce to 8s (70c2438)
    • mobile: legible add-task empty chips (fd943ac)
    • shared: preserve UTF-16 length when folding emoji in picker filter (fe2f695)
    • ui: theme OfflineIndicator banner via Typography (1330e03)
    • mobile: close add-task modal before reminder write (c28f50a)
    • ui: white quick-add chip text, drop seconds (371f843)
    • web: merge offline indicator in-column banner into dev (5595767)
    • web: show offline indicator as in-column banner, sr-only when online (077bb2c)
    • web: color due/deadline labels via inline style not className (8cd5009)
    • shared: keep brand pun 'etappi' literal across locales (5c7bebf)
    • shared: scope top-level append to parent_id IS NULL (6806a87)
    • shared: createTask append ignores null-default slot (c977520)
    • web: soften plan-your-week shot-2 alt to fit web+mobile (c0dbf84)
    • web: habit recurrence label + segmented control (ac4d892)
    • mobile: gate offline banner on real reachability, not sync status (0b7e8a8)
    • mobile: reserve top-bar height before Today loading skeleton (0bbc027)
    • calendar: preserve start fields in deriveEventTime, 15m no-duration fallback (e28a39b)
    • mobile: guard label create against double-submit (968c547)
  • Other
    • web: locale-aware custom tile month + memoize due-tiles (d7b2fae)
    • shared: promote day-presets math from mobile to @etappi/shared (432a7ba)
    • move pointerEvents prop to style.pointerEvents (3f1a1ef)
    • mobile: extract insertLocalLabel helper (e8e9a05)

iOS 1.13.0 — 2026-06-26 (build 60)

  • Features
    • mobile: hide sync cloud icon in prod builds (d74da95)
    • mobile: remove "Back online" badge (4bee91f)
    • mobile: hide habit checklist on past calendar days (7665f57)
    • mobile: auto-hide offline banner + add "Back online" badge (d546d65)
    • pending email invitations with signup reconciliation (68db802)
  • Fixes
    • ui: anchor create-project modal above keyboard (e4ba793)
    • mobile: stop sync icon flap on 60s JWT recycle (9dde474)
    • mobile: keep add-task keyboard up on sync (5a374e1)

Android 1.7.0 — 2026-06-26 (versionCode 10)

  • Features
    • mobile,web: calendar picker + day-planner time-blocks (ada8d7c)
    • api: multi-calendar routing, time-blocks, per-calendar color (d428f39)
    • db: add tasks.targetCalendarId + deriveEventTime (bbe53ac)
  • Fixes
    • mobile: gate offline banner on real reachability, not sync status (0b7e8a8)
    • mobile: reserve top-bar height before Today loading skeleton (0bbc027)
    • calendar: preserve start fields in deriveEventTime, 15m no-duration fallback (e28a39b)

Android 1.6.0 — 2026-06-26 (versionCode 9)

  • Features
    • mobile: create labels from the add-task picker sheet (052951d)
    • ui: add avoidKeyboard prop to BottomSheetShell (811802f)
    • mobile: hide sync cloud icon in prod builds (d74da95)
    • mobile: remove "Back online" badge (4bee91f)
    • mobile: hide habit checklist on past calendar days (7665f57)
    • mobile: auto-hide offline banner + add "Back online" badge (d546d65)
    • pending email invitations with signup reconciliation (68db802)
    • mobile: compass action bar for triage swipe discoverability (4042726)
    • triage: hide add-task FAB on triage screen, lift action bar off bottom edge (efef75e)
    • triage: celebratory check-circle icon on empty state (82deef7)
    • triage: orchestrate progress + peek deck + hint + action bar in deck view (6cc0726)
    • triage: tappable action bar wired to card flingTo (today hero / tinted / ghost) (bdeb560)
    • triage: progress bar (segmented/continuous) + slim swipe-or-tap hint (ff6c171)
    • triage: stacked-card deck with two dimmed peek cards (62523dd)
    • triage: overdue-days chip + flingTo handle + drag-badge overlay on card (50d8540)
    • triage: live colored drag badge driven by gesture progress (0279c48)
    • triage: tap-parity flingTo + drag-progress derived value + reduced-motion gating (b4ee3ea)
    • triage: classifyDue overdue helper + unit tests (9b7f50c)
    • triage: i18n keys for deck redesign (progress + actions), drop deck.counter, reword hint (55065f7)
    • web region & week-start formatting parity (0b06d78)
    • thread user week start through date UI and filter (3e50e3a)
    • mobile: localize date/time renders via format locale (914aaf4)
    • mobile: read region prefs from synced users row (f11a76e)
    • mobile: unify search filter creation on the visual builder (b528ca0)
    • mobile: add Language & Region screen (4f1d740)
    • shared: add locale/week-start formatting core (P2) (81c0dd3)
    • mobile: merge rich-label + active-value search filter picker (521a31e)
    • mobile: rich labels + active-value selection for search filter picker (0d92720)
    • add synced region + weekStartsOn user prefs (schema + REST) (e4cc7f8)
    • mobile: show priority meaning in picker (b072a40)
    • mobile: localize project action + color sheet labels (a3c3c87)
    • ui: merge adaptive reminder custom button + hide dead presets (b2a9a4d)
    • ui: adaptive reminder custom-date button + hide dead presets (a217670)
    • ui: add avoidKeyboard + dismissOnScrimPress to SheetScaffold (930b547)
    • ui: square bottom-sheet top corners (8ba4ab4)
    • mobile: redesign project & task action sheets (Direction C) (dbd970f)
    • ui: rounded sheet scaffold + action-sheet primitives (67d701b)
    • mobile: add Members to project header menu (c8699c6)
    • mobile: add confirm-password field to sign-up (48adddd)
    • mobile: drive cross-screen onboarding tour navigation (84d49f2)
    • prioritize: localize inbox prioritize label set (4083e48)
    • mobile: redesign task overflow sheet into grouped icon cards (214a4ff)
    • mobile: Save/Cancel editing mode for task title & description (a60b719)
    • web: hierarchical project+section picker on compose modal (7364f08)
    • shared: add project-picker expand/collapse/section a11y strings (cd5f43d)
    • mobile: wire section selection through add-task + compose (c327c23)
    • mobile: wire task-detail project picker to sections + sub-projects (055dc7a)
    • mobile: hierarchical project-picker sheet with expandable rows + sections (d7d2951)
    • mobile: project-picker tree + expand-state hook with tests (b7434d2)
    • db: add allSectionsQuery for hierarchical project picker (b4da95f)
    • mobile: live deterministic NLP on the compose sheet (718b5bd)
    • mobile: attach sign-up errors to offending field (eb4a99c)
    • mobile: inline conflict resolution with value diff (e32fc70)
    • mobile: mirror optional serverValues in conflict entry schema (8c4d8d6)
    • sync: carry server field values in stale-write skipped[] for conflict diff (7244ee2)
    • mobile: promote task labels to their own LABELS section (a7ce9e8)
    • mobile: hide past reminders in task detail (a10b18d)
    • ui: sectioned Repeat sheet with interval and end-date (b856628)
    • ui: add Stepper primitive (native + web) (7c8efd7)
    • ui: add recurrence state model, build, parse, preview (363a3b8)
    • tasks: WHEN tiles tap-to-clear + calendar icon, block past due-times today (754401d)
    • calendar: surface add-another-calendar providers when connected (59ab560)
    • tasks: make Set-time chip discoverable on task detail (eea0f8b)
    • calendar: surface Google OAuth error on mobile connect failure (13695ae)
    • i18n: translate habits.reminders.* into uk/pl/de/fr (6c91671)
    • mobile: schedule habit reminders as local notifications (90c34a2)
    • mobile: reminder time pill on habit edit screen (31b673c)
    • i18n: add habits.reminders.* source keys (e137ba3)
    • habits: persist + sync per-item & habit-level reminder times (9cb4c67)
  • Fixes
    • mobile: guard label create against double-submit (968c547)
    • ui: anchor create-project modal above keyboard (e4ba793)
    • mobile: stop sync icon flap on 60s JWT recycle (9dde474)
    • mobile: keep add-task keyboard up on sync (5a374e1)
    • triage: use @etappi/ui Pressable in action button (a11y lint rule) (4d3cc38)
    • mobile: honor region locale in date pickers (ef933c6)
    • mobile: reuse canonical picker chrome for search filter values (6f315d0)
    • mobile: fill iOS 26 header capsule (32→36pt) (f7ed3ab)
    • ui: announce sheet header titles as accessibility headings (a822283)
    • mobile: center icon glyph in iOS 26 header glass capsule (11cd632)
    • mobile: mark sheet picker titles as a11y headers (554f750)
    • mobile: color inbox prioritize sparkle icon (cd9447b)
    • mobile: size iOS 26 header glass capsules (739c4fe)
    • ui: pair native fontWeight with font family (24f6579)
    • on-primary text on primary-filled surfaces (ed4b2fe)
    • mobile: show member name in confirm alerts (e2e1a22)
    • mobile: use on-primary ink for invite role chips and button (488de77)
    • ui: keep secondary Button readable on press (5a18feb)
    • mobile: theme calendar paywall title color (9cb8216)
    • mobile: notify subscribers when welcome completes locally (da10cdb)
    • mobile: tour spotlight measures + FAB tappable (820f5ce)
    • prioritize: empty state + AI request timeouts (cc0aa22)
    • mobile: hide inbox AI prioritize on empty inbox (742cad0)
    • onboarding: reset process-local onboarding state on sign-out (3f05435)
    • onboarding: activate mobile tour for fresh users + wire missing targets (584e045)
    • mobile: commit task description on navigate-away too (5ac5bd2)
    • mobile: commit task description on keyboard dismiss (73e497c)
    • shared: accept geofence columns in task sync schema (540a07b)
    • shared: anchor date-only due to local midnight for stable iso (7c9f7bd)
    • mobile: add gap below auth subtitle before form (e75dfc3)
    • mobile: location picker keyboard, search visibility, current-location default (0386c23)
    • mobile: theme conflict primary-button text via on-primary token (0c3a033)
    • mobile: block sign-up OTP advance on failed create (7422adf)
    • web: localize hardcoded UI strings via next-intl (a0af987)
    • mobile: gate PowerSync connection on AppState lifecycle (431ab9d)
    • api: health probe false-negative on local db (ea401e6)
    • mobile: pin auth-surface text to fixed ink in dark mode (0887cb3)
    • mobile: bound realtime reconnect loop to stop native-memory leak (0509ee5)
    • mobile: hide AI fill card until task name typed (7405a1b)
    • mobile: preserve custom date & time reminders in compose sheet (a78a0b6)
    • mobile: anchor compose sheet above keyboard (812a262)
    • ui: omit until clause in recurrence preview when no date set (fced775)
    • reminders: kill the reminder double-create at every layer (f1de5c3)
    • mobile: guard persistent reminder creates against fast double-tap (1562de8)
    • mobile: dedupe reminder presets on fast double-tap (1b068b6)
    • reminders: dedupe draft preset reminders on fast double-tap (396dfa1)
    • tasks: seed time picker at the earliest allowed time on both platforms (cce2753)
    • i18n: use single-brace count/remaining placeholders across locales (b747cdc)
    • projects: keyboard-avoid board view so add-column input stays visible (496b727)
    • mobile: add sso-callback route to stop Android +not-found flash (545470c)
    • habits: address reminder scheduler review findings (fb17f33)
    • calendar: unstick mobile Google OAuth connect flow (57f1f6d)
    • mobile: repair Google SSO redirect and gate splash reveal (cfbc787)
  • Other
    • mobile: extract insertLocalLabel helper (e8e9a05)
    • web: drop Business plan, align pricing CTAs (5b19390)
    • remove unused types + dead invite prop (b6232de)
    • mobile: notification priority picker onto bottom sheet (cfed822)
    • mobile: route group-by pickers onto canonical sheet chrome (b5928ab)
    • mobile: native back + text edit headers (a3f863d)
    • mobile: migrate project header actions to action sheet (a80a9e6)
    • mobile: migrate board column actions to action sheet (e9181c4)
    • mobile: migrate add-column dialog to bottom sheet (f5bbde2)
    • mobile: migrate save-as-template dialog to bottom sheet (8a2a7b7)
    • mobile: migrate task overflow menu to shared sheet (922412c)
    • mobile: migrate inbox group-by picker to bottom sheet (ccc926e)
    • mobile: migrate search filter-value picker to bottom sheet (833f2b6)
    • mobile: dedupe iOS 26 version check (adb1d3e)
    • mobile: migrate 3 complex batch-4 sheets onto SheetScaffold (091def4)
    • mobile: migrate 6 batch-3 sheets onto SheetScaffold (debd647)
    • mobile: migrate 6 moderate sheets onto shared SheetScaffold (30f451b)
    • mobile: migrate 6 simple sheets onto shared SheetScaffold (04b237a)
    • ui: collapse bottom-sheet shells onto SheetScaffold (f98f422)
    • mobile: scroll task detail body under sticky header (38fcbe2)
    • ui: move family task-list-row chevron to trailing edge (de3ac25)

iOS 1.13.0 — 2026-06-26 (build 60)

  • Features
    • mobile: hide sync cloud icon in prod builds (d74da95)
    • mobile: remove "Back online" badge (4bee91f)
    • mobile: hide habit checklist on past calendar days (7665f57)
    • mobile: auto-hide offline banner + add "Back online" badge (d546d65)
    • pending email invitations with signup reconciliation (68db802)
  • Fixes
    • ui: anchor create-project modal above keyboard (e4ba793)
    • mobile: stop sync icon flap on 60s JWT recycle (9dde474)
    • mobile: keep add-task keyboard up on sync (5a374e1)

iOS 1.12.0 — 2026-06-25 (build 59)

  • Features
    • mobile: compass action bar for triage swipe discoverability (4042726)
    • triage: hide add-task FAB on triage screen, lift action bar off bottom edge (efef75e)
    • triage: celebratory check-circle icon on empty state (82deef7)
    • triage: orchestrate progress + peek deck + hint + action bar in deck view (6cc0726)
    • triage: tappable action bar wired to card flingTo (today hero / tinted / ghost) (bdeb560)
    • triage: progress bar (segmented/continuous) + slim swipe-or-tap hint (ff6c171)
    • triage: stacked-card deck with two dimmed peek cards (62523dd)
    • triage: overdue-days chip + flingTo handle + drag-badge overlay on card (50d8540)
    • triage: live colored drag badge driven by gesture progress (0279c48)
    • triage: tap-parity flingTo + drag-progress derived value + reduced-motion gating (b4ee3ea)
    • triage: classifyDue overdue helper + unit tests (9b7f50c)
    • triage: i18n keys for deck redesign (progress + actions), drop deck.counter, reword hint (55065f7)
    • web region & week-start formatting parity (0b06d78)
    • thread user week start through date UI and filter (3e50e3a)
    • mobile: localize date/time renders via format locale (914aaf4)
    • mobile: read region prefs from synced users row (f11a76e)
    • mobile: unify search filter creation on the visual builder (b528ca0)
    • mobile: add Language & Region screen (4f1d740)
    • shared: add locale/week-start formatting core (P2) (81c0dd3)
    • mobile: merge rich-label + active-value search filter picker (521a31e)
    • mobile: rich labels + active-value selection for search filter picker (0d92720)
    • add synced region + weekStartsOn user prefs (schema + REST) (e4cc7f8)
    • mobile: show priority meaning in picker (b072a40)
    • mobile: localize project action + color sheet labels (a3c3c87)
    • ui: merge adaptive reminder custom button + hide dead presets (b2a9a4d)
    • ui: adaptive reminder custom-date button + hide dead presets (a217670)
    • ui: add avoidKeyboard + dismissOnScrimPress to SheetScaffold (930b547)
    • ui: square bottom-sheet top corners (8ba4ab4)
    • mobile: redesign project & task action sheets (Direction C) (dbd970f)
    • ui: rounded sheet scaffold + action-sheet primitives (67d701b)
    • mobile: add Members to project header menu (c8699c6)
    • mobile: add confirm-password field to sign-up (48adddd)
    • mobile: drive cross-screen onboarding tour navigation (84d49f2)
    • prioritize: localize inbox prioritize label set (4083e48)
    • mobile: redesign task overflow sheet into grouped icon cards (214a4ff)
    • mobile: Save/Cancel editing mode for task title & description (a60b719)
    • web: hierarchical project+section picker on compose modal (7364f08)
    • shared: add project-picker expand/collapse/section a11y strings (cd5f43d)
    • mobile: wire section selection through add-task + compose (c327c23)
    • mobile: wire task-detail project picker to sections + sub-projects (055dc7a)
    • mobile: hierarchical project-picker sheet with expandable rows + sections (d7d2951)
    • mobile: project-picker tree + expand-state hook with tests (b7434d2)
    • db: add allSectionsQuery for hierarchical project picker (b4da95f)
    • mobile: live deterministic NLP on the compose sheet (718b5bd)
    • mobile: attach sign-up errors to offending field (eb4a99c)
    • mobile: inline conflict resolution with value diff (e32fc70)
    • mobile: mirror optional serverValues in conflict entry schema (8c4d8d6)
    • sync: carry server field values in stale-write skipped[] for conflict diff (7244ee2)
  • Fixes
    • triage: use @etappi/ui Pressable in action button (a11y lint rule) (4d3cc38)
    • mobile: honor region locale in date pickers (ef933c6)
    • mobile: reuse canonical picker chrome for search filter values (6f315d0)
    • mobile: fill iOS 26 header capsule (32→36pt) (f7ed3ab)
    • ui: announce sheet header titles as accessibility headings (a822283)
    • mobile: center icon glyph in iOS 26 header glass capsule (11cd632)
    • mobile: mark sheet picker titles as a11y headers (554f750)
    • mobile: color inbox prioritize sparkle icon (cd9447b)
    • mobile: size iOS 26 header glass capsules (739c4fe)
    • ui: pair native fontWeight with font family (24f6579)
    • on-primary text on primary-filled surfaces (ed4b2fe)
    • mobile: show member name in confirm alerts (e2e1a22)
    • mobile: use on-primary ink for invite role chips and button (488de77)
    • ui: keep secondary Button readable on press (5a18feb)
    • mobile: theme calendar paywall title color (9cb8216)
    • mobile: notify subscribers when welcome completes locally (da10cdb)
    • mobile: tour spotlight measures + FAB tappable (820f5ce)
    • prioritize: empty state + AI request timeouts (cc0aa22)
    • mobile: hide inbox AI prioritize on empty inbox (742cad0)
    • onboarding: reset process-local onboarding state on sign-out (3f05435)
    • onboarding: activate mobile tour for fresh users + wire missing targets (584e045)
    • mobile: commit task description on navigate-away too (5ac5bd2)
    • mobile: commit task description on keyboard dismiss (73e497c)
    • shared: accept geofence columns in task sync schema (540a07b)
    • shared: anchor date-only due to local midnight for stable iso (7c9f7bd)
    • mobile: add gap below auth subtitle before form (e75dfc3)
    • mobile: location picker keyboard, search visibility, current-location default (0386c23)
    • mobile: theme conflict primary-button text via on-primary token (0c3a033)
    • mobile: block sign-up OTP advance on failed create (7422adf)
    • web: localize hardcoded UI strings via next-intl (a0af987)
    • mobile: gate PowerSync connection on AppState lifecycle (431ab9d)
    • api: health probe false-negative on local db (ea401e6)
    • mobile: pin auth-surface text to fixed ink in dark mode (0887cb3)
    • mobile: bound realtime reconnect loop to stop native-memory leak (0509ee5)
    • mobile: hide AI fill card until task name typed (7405a1b)
    • mobile: preserve custom date & time reminders in compose sheet (a78a0b6)
    • mobile: anchor compose sheet above keyboard (812a262)
  • Other
    • remove unused types + dead invite prop (b6232de)
    • mobile: notification priority picker onto bottom sheet (cfed822)
    • mobile: route group-by pickers onto canonical sheet chrome (b5928ab)
    • mobile: native back + text edit headers (a3f863d)
    • mobile: migrate project header actions to action sheet (a80a9e6)
    • mobile: migrate board column actions to action sheet (e9181c4)
    • mobile: migrate add-column dialog to bottom sheet (f5bbde2)
    • mobile: migrate save-as-template dialog to bottom sheet (8a2a7b7)
    • mobile: migrate task overflow menu to shared sheet (922412c)
    • mobile: migrate inbox group-by picker to bottom sheet (ccc926e)
    • mobile: migrate search filter-value picker to bottom sheet (833f2b6)
    • mobile: dedupe iOS 26 version check (adb1d3e)
    • mobile: migrate 3 complex batch-4 sheets onto SheetScaffold (091def4)
    • mobile: migrate 6 batch-3 sheets onto SheetScaffold (debd647)
    • mobile: migrate 6 moderate sheets onto shared SheetScaffold (30f451b)
    • mobile: migrate 6 simple sheets onto shared SheetScaffold (04b237a)
    • ui: collapse bottom-sheet shells onto SheetScaffold (f98f422)

iOS 1.11.0 — 2026-06-21 (build 58)

  • Features
    • mobile: promote task labels to their own LABELS section (a7ce9e8)
    • mobile: hide past reminders in task detail (a10b18d)
    • ui: sectioned Repeat sheet with interval and end-date (b856628)
    • ui: add Stepper primitive (native + web) (7c8efd7)
    • ui: add recurrence state model, build, parse, preview (363a3b8)
    • tasks: WHEN tiles tap-to-clear + calendar icon, block past due-times today (754401d)
    • calendar: surface add-another-calendar providers when connected (59ab560)
    • tasks: make Set-time chip discoverable on task detail (eea0f8b)
    • calendar: surface Google OAuth error on mobile connect failure (13695ae)
    • i18n: translate habits.reminders.* into uk/pl/de/fr (6c91671)
    • mobile: schedule habit reminders as local notifications (90c34a2)
    • mobile: reminder time pill on habit edit screen (31b673c)
    • i18n: add habits.reminders.* source keys (e137ba3)
    • habits: persist + sync per-item & habit-level reminder times (9cb4c67)
  • Fixes
    • ui: omit until clause in recurrence preview when no date set (fced775)
    • reminders: kill the reminder double-create at every layer (f1de5c3)
    • mobile: guard persistent reminder creates against fast double-tap (1562de8)
    • mobile: dedupe reminder presets on fast double-tap (1b068b6)
    • reminders: dedupe draft preset reminders on fast double-tap (396dfa1)
    • tasks: seed time picker at the earliest allowed time on both platforms (cce2753)
    • i18n: use single-brace count/remaining placeholders across locales (b747cdc)
    • projects: keyboard-avoid board view so add-column input stays visible (496b727)
    • mobile: add sso-callback route to stop Android +not-found flash (545470c)
    • habits: address reminder scheduler review findings (fb17f33)
    • calendar: unstick mobile Google OAuth connect flow (57f1f6d)
  • Other
    • mobile: scroll task detail body under sticky header (38fcbe2)
    • ui: move family task-list-row chevron to trailing edge (de3ac25)

iOS 1.10.2 — 2026-06-20 (build 57)

  • Fixes
    • mobile: repair Google SSO redirect and gate splash reveal (cfbc787)

iOS 1.10.2 — 2026-06-20 (build 57)

  • Fixes
    • mobile: repair Google SSO redirect and gate splash reveal (cfbc787)

iOS 1.10.1 — 2026-06-19 (build 56)

No user-visible changes since previous release.

Android 1.5.0 — 2026-06-19 (versionCode 8)

  • Features
    • calendar: multi-calendar support with one default push target (bd69e45)
    • mobile: resume abandoned email-code sign-up verification (043ce7b)

iOS 1.10.0 — 2026-06-19 (build 55)

  • Features
    • calendar: multi-calendar support with one default push target (bd69e45)
    • mobile: resume abandoned email-code sign-up verification (043ce7b)

Android 1.4.0 — 2026-06-19 (versionCode 7)

  • Features
    • mobile: checkmark + split-tap habit rows (b4d698a)
    • mobile: habit calendar history + habit_logs PATCH sync (61c8bfe)
    • mobile: replace habit heatmap with a month-calendar history (07c311f)
    • api: add PATCH /api/sync/habit_logs for in-place habit-log edits (a93d338)
    • i18n: add settings hub group + sub-screen header keys (e9e457a)
    • mobile: rewrite settings hub as grouped nav-row list (869ca3a)
    • mobile: add routed settings sub-screens hosting existing sections (bcf6d32)
    • i18n: route hardcoded mobile + web strings through i18n (0910bfd)
    • ui: surface habits on Today + Browse (mobile) and a Routines sidebar group (web) (bbafeff)
    • checkbox completion dwell — hold just-completed rows checked before they leave (f9f3412)
    • i18n: translate habits empty-state + Routines keys for de/fr/pl/uk (fe373b0)
    • mobile: promote Browse Habits tile to a full-width hero (c05bdec)
    • mobile: persistent 3-state habits section on Today (ce0d943)
    • i18n: add habits-today empty-card + routines keys (en source) (2c83d77)
    • mobile: dwell just-completed Today rows in place before re-bucketing to Done (643f113)
    • ui: lighten prominent primary glyphs via contrast-aware --color-on-primary-vivid (e9c2e8e)
    • mobile: wire completion dwell into vanishing lists (inbox, next actions, projects, search) (1365b46)
    • mobile: present compose as centered modal dialog (ae06105)
    • mobile: offline-durable reminders + wire reminders into compose (4814935)
    • mobile: add completion-dwell hook for checked task rows (7809e4c)
    • mobile: remove swipe-to-change-tabs gesture and edge gutters (4da73a6)
    • mobile: merge task-detail offline-safe local-first writes (858fdc0)
    • mobile: make task-detail edits local-first (offline-safe) (055d321)
    • mobile: fire task-created toast after compose create (cb158b2)
    • BETA_FREE_PROAI giveaway floor (all users → Pro+AI, reversible) (60d9b66)
    • ui: unify Add section/sub-project trigger to body 16px semibold (fdb6e7d)
    • mobile: merge collapsible Quick Actions header on Browse (c4383c3)
    • collapsible Quick Actions header on mobile Browse (ff3804d)
    • mobile: merge auth redesign — floating-card UI + brand-orange CTA (248f96d)
    • mobile: restyle welcome screen to match auth redesign (77c051e)
    • mobile: rebuild auth screens on floating-card design (636f9ce)
    • mobile: add shared auth UI components (3226e93)
    • i18n: add auth.or_continue_with social divider key (2a0192f)
    • ui: add Button.loading prop with spinner state (90e2c1b)
    • task-created 'Open' toast on mobile add-task + web compose/quick-add (92180d2)
    • mobile: show 'Task created · Open' toast after add-task save (2dc1c9f)
    • shared/i18n: add toast.task_created + toast.open keys (82708c0)
    • web,mobile: guard PowerSync-path create/edit handlers against double-submit (a23a9e9)
    • web,mobile: guard useRestMutation against double-submit (395060c)
    • shared: add useSubmitGuard re-entrancy guard hook (5495d33)
    • api: merge plan-gate 6 — dev/setPlan all paid tiers + entitlements.tier CHECK (30450e0)
    • api: widen dev/setPlan to all paid tiers + lock entitlements.tier (e4b6200)
    • mobile/paywall: redesign paywall screen (Direction C, tap-to-buy) (1f4bd34)
    • i18n: translate paywall redesign keys to de/fr/pl/uk (f562545)
    • mobile/paywall: compose new sub-components in screen shell (6ec3cbf)
    • mobile/paywall: inline restored panel + reload via reloadTick (b45e3c3)
    • web: gate activity log behind paid plan (ada49af)
    • mobile/paywall: redesign plan cards (split row, featured outline, MOST POPULAR badge) (65b23bd)
    • shared: add planHasActivityLog plan-tier helper (562428f)
    • mobile/paywall: add PaywallError + PaywallRestored panels (68ce006)
    • mobile/paywall: add PaywallUnavailable component (71b1f8f)
    • mobile/paywall: add PaywallFeaturesList component (2d6a284)
    • mobile/paywall: add PaywallHero component (7ce0a70)
    • i18n: add paywall redesign keys (en) (37e1613)
    • shared: add planIsPaid helper; use in web focus stats gate (7906b7f)
    • mobile: always play full splash reveal animation (64f62b9)
    • mobile: splash squares reveal animation (ff36b5b)
    • mobile: promote Plan with AI to solid full-width tile + brand fresh-user sparkle (bc4058d)
  • Fixes
    • mobile: sync i18n bootstrap before splash (8bd5ca3)
    • mobile: eliminate cold-start white flash before splash animation (af461ba)
    • habits: local-first create + edit so the detail screen shows saved changes (2d98a22)
    • mobile: label reminder chip "1 reminder" + bell, not ambiguous "1 set" (d07c9a5)
    • mobile: drop blank habit checklist rows before save (627b723)
    • mobile: centralize Hermes-safe id generation behind injectable newId (fca7fb5)
    • mobile: mint habit-log id via expo-crypto, not uuid (Hermes crash) (b30abaf)
    • mobile: make habit-log toggle local-first (2148821)
    • today: always render the habits section regardless of task count (e49a33b)
    • mobile: repair compose sheet create + layout (159e58c)
    • dwell: resolve completion snapshot race-free via prev-render window (5964f8b)
    • mobile: silence no-spacer-view on browse filter boundary gap (14303bd)
    • mobile: add gap between browse filter and project list (34a195e)
    • mobile: center project-row rail in leading inset (197fdcb)
    • api: merge comment-push amplification throttle (faaa3b3)
    • api: throttle comment-push fan-out to close sync-limiter amplification (554d886)
    • mobile: floor compose sheet footer at safe-area bottom inset (5f32099)
    • mobile: unfragment dashed scheduling-chip outline (22e7f0b)
    • mobile: use paddingTop for inbox top inset (2c0741f)
    • mobile: inbox subtask indent + collapse (491a064)
    • mobile: bound project header title so long names ellipsize (cd263b2)
    • mobile: merge widget extension version fix (ITMS-90473) (1373386)
    • mobile: track widget extension version from ios.version (e3b392b)
    • mobile: keep tab FAB mounted on blur, clear on unmount (e82eb0f)
    • mobile: render neutral bg while biometric pref loads (6382646)
    • mobile: tint board column with surface token instead of background (07f1baa)
    • mobile: match Browse FAB plus glyph size to other tabs (214e88b)
    • ui: raise quick-add bar contrast, add bottom inset (740d2ec)
    • mobile: wire auth text to fixed inks + brand-orange CTA (28a65e5)
    • one-Inbox-per-user dedupe + slow-query proxy data-loss fix (5245f9e)
    • api: stop slow-query proxy from breaking db.delete().where() (923faaf)
    • db: guarantee one Inbox per user (dedupe migration + unique index + adopt-existing) (77cfdbf)
    • mobile: theme add-task modal card (a1b8b58)
    • mobile: focus compose title after sheet enter (4cf3fe5)
    • shared: normalize labelIds to string[] at schema boundary (eecf005)
    • api: hand off OAuth-start auth via single-use nonce, keep JWT out of URLs (2819021)
    • repair failing local CI gates (0a19da1)
    • mobile: fire task-created toast on insert, not after reminder write (c21e8c3)
    • mobile/paywall: use useGuardedRouter for the close handler (18a7ad2)
    • mobile/biometric: correct off-by-one in PIN attempts-before-lockout counter (a07d096)
    • mobile/paywall: set transparent header at root, override headerLeft in screen (2f88cac)
    • mobile/paywall: add transparent header with X close button (f63998d)
    • mobile: restyle compose footer Cancel/Create as full-width buttons (f811e49)
    • mobile/paywall: register paywall as modal at root stack (1deab3a)
    • mobile/paywall: hide redundant modal header above hero (7c071b5)
    • mobile: merge fab follow-ups — tourTarget thread + config owner guard (7d177e1)
    • mobile: thread FAB tourTarget, guard config owner (957c7fc)
    • mobile: hoist tab FAB out of animated scenes (49d8d1b)
    • web: fit inbox placeholder to column width (b08a75b)
    • mobile: soften Plan with AI tile fill to 90% primary (9ffa951)
    • mobile: slow add-task modal slide-up to 500ms (06907ce)
    • mobile: slow tab-switch animation to 300ms (ca3695b)
    • keyboard avoidance broken on Android edge-to-edge (d79fa39)
    • mobile: keep splash up until ClerkLoaded to avoid +not-found flash (114e468)
    • ui: avoid keyboard overlap in create-project modal (097958c)
  • Other
    • mobile: use SectionLabel for task-dependencies heading (78d16b6)
    • mobile: extract CalendarMonthShell from CalendarMonth (0f22b47)
    • mobile: drop section wrappers superseded by settings hub (050e565)
    • mobile: restyle settings-row with leading icon + rounded section card (8a92f05)
    • mobile: fixed splash hold, drop sync-gated readiness (3a49cb8)
    • mobile: centralize pre-auth color palette (f1d6348)
    • web,mobile: keep submit-guarded files under the 150 LOC cap (611d0b6)

iOS 1.9.0 — 2026-06-19 (build 54)

  • Features
    • mobile: checkmark + split-tap habit rows (b4d698a)
  • Fixes
    • mobile: sync i18n bootstrap before splash (8bd5ca3)

iOS 1.8.0 — 2026-06-19 (build 53)

  • Features
    • mobile: habit calendar history + habit_logs PATCH sync (61c8bfe)
    • mobile: replace habit heatmap with a month-calendar history (07c311f)
    • api: add PATCH /api/sync/habit_logs for in-place habit-log edits (a93d338)
    • i18n: add settings hub group + sub-screen header keys (e9e457a)
    • mobile: rewrite settings hub as grouped nav-row list (869ca3a)
    • mobile: add routed settings sub-screens hosting existing sections (bcf6d32)
    • i18n: route hardcoded mobile + web strings through i18n (0910bfd)
    • ui: surface habits on Today + Browse (mobile) and a Routines sidebar group (web) (bbafeff)
    • checkbox completion dwell — hold just-completed rows checked before they leave (f9f3412)
    • i18n: translate habits empty-state + Routines keys for de/fr/pl/uk (fe373b0)
    • mobile: promote Browse Habits tile to a full-width hero (c05bdec)
    • mobile: persistent 3-state habits section on Today (ce0d943)
    • i18n: add habits-today empty-card + routines keys (en source) (2c83d77)
    • mobile: dwell just-completed Today rows in place before re-bucketing to Done (643f113)
    • ui: lighten prominent primary glyphs via contrast-aware --color-on-primary-vivid (e9c2e8e)
    • mobile: wire completion dwell into vanishing lists (inbox, next actions, projects, search) (1365b46)
    • mobile: present compose as centered modal dialog (ae06105)
    • mobile: offline-durable reminders + wire reminders into compose (4814935)
    • mobile: add completion-dwell hook for checked task rows (7809e4c)
    • mobile: remove swipe-to-change-tabs gesture and edge gutters (4da73a6)
    • mobile: merge task-detail offline-safe local-first writes (858fdc0)
    • mobile: make task-detail edits local-first (offline-safe) (055d321)
  • Fixes
    • mobile: eliminate cold-start white flash before splash animation (af461ba)
    • habits: local-first create + edit so the detail screen shows saved changes (2d98a22)
    • mobile: label reminder chip "1 reminder" + bell, not ambiguous "1 set" (d07c9a5)
    • mobile: drop blank habit checklist rows before save (627b723)
    • mobile: centralize Hermes-safe id generation behind injectable newId (fca7fb5)
    • mobile: mint habit-log id via expo-crypto, not uuid (Hermes crash) (b30abaf)
    • mobile: make habit-log toggle local-first (2148821)
    • today: always render the habits section regardless of task count (e49a33b)
    • mobile: repair compose sheet create + layout (159e58c)
    • dwell: resolve completion snapshot race-free via prev-render window (5964f8b)
    • mobile: silence no-spacer-view on browse filter boundary gap (14303bd)
    • mobile: add gap between browse filter and project list (34a195e)
    • mobile: center project-row rail in leading inset (197fdcb)
    • api: merge comment-push amplification throttle (faaa3b3)
    • api: throttle comment-push fan-out to close sync-limiter amplification (554d886)
    • mobile: floor compose sheet footer at safe-area bottom inset (5f32099)
    • mobile: unfragment dashed scheduling-chip outline (22e7f0b)
  • Other
    • mobile: use SectionLabel for task-dependencies heading (78d16b6)
    • mobile: extract CalendarMonthShell from CalendarMonth (0f22b47)
    • mobile: drop section wrappers superseded by settings hub (050e565)
    • mobile: restyle settings-row with leading icon + rounded section card (8a92f05)

iOS 1.7.0 — 2026-06-17 (build 52)

  • Features
    • mobile: remove swipe-to-change-tabs gesture and edge gutters (4da73a6)
    • mobile: merge task-detail offline-safe local-first writes (858fdc0)
    • mobile: make task-detail edits local-first (offline-safe) (055d321)
  • Fixes
    • api: merge comment-push amplification throttle (faaa3b3)
    • api: throttle comment-push fan-out to close sync-limiter amplification (554d886)
    • mobile: floor compose sheet footer at safe-area bottom inset (5f32099)
    • mobile: unfragment dashed scheduling-chip outline (22e7f0b)

iOS 1.6.1 — 2026-06-16 (build 51)

  • Features
    • mobile: fire task-created toast after compose create (cb158b2)
    • BETA_FREE_PROAI giveaway floor (all users → Pro+AI, reversible) (60d9b66)
  • Fixes
    • mobile: use paddingTop for inbox top inset (2c0741f)
    • mobile: inbox subtask indent + collapse (491a064)
    • mobile: bound project header title so long names ellipsize (cd263b2)
    • mobile: merge widget extension version fix (ITMS-90473) (1373386)
    • mobile: track widget extension version from ios.version (e3b392b)
    • mobile: keep tab FAB mounted on blur, clear on unmount (e82eb0f)
    • mobile: render neutral bg while biometric pref loads (6382646)
  • Other
    • mobile: fixed splash hold, drop sync-gated readiness (3a49cb8)

iOS 1.3.0 — 2026-06-15 (build 44)

  • Features
    • ui: unify Add section/sub-project trigger to body 16px semibold (fdb6e7d)
    • mobile: merge collapsible Quick Actions header on Browse (c4383c3)
    • collapsible Quick Actions header on mobile Browse (ff3804d)
    • mobile: merge auth redesign — floating-card UI + brand-orange CTA (248f96d)
    • mobile: restyle welcome screen to match auth redesign (77c051e)
    • mobile: rebuild auth screens on floating-card design (636f9ce)
    • mobile: add shared auth UI components (3226e93)
    • i18n: add auth.or_continue_with social divider key (2a0192f)
    • ui: add Button.loading prop with spinner state (90e2c1b)
    • task-created 'Open' toast on mobile add-task + web compose/quick-add (92180d2)
    • mobile: show 'Task created · Open' toast after add-task save (2dc1c9f)
    • shared/i18n: add toast.task_created + toast.open keys (82708c0)
    • web,mobile: guard PowerSync-path create/edit handlers against double-submit (a23a9e9)
    • web,mobile: guard useRestMutation against double-submit (395060c)
    • shared: add useSubmitGuard re-entrancy guard hook (5495d33)
    • api: merge plan-gate 6 — dev/setPlan all paid tiers + entitlements.tier CHECK (30450e0)
    • api: widen dev/setPlan to all paid tiers + lock entitlements.tier (e4b6200)
    • mobile/paywall: redesign paywall screen (Direction C, tap-to-buy) (1f4bd34)
    • i18n: translate paywall redesign keys to de/fr/pl/uk (f562545)
    • mobile/paywall: compose new sub-components in screen shell (6ec3cbf)
    • mobile/paywall: inline restored panel + reload via reloadTick (b45e3c3)
    • web: gate activity log behind paid plan (ada49af)
    • mobile/paywall: redesign plan cards (split row, featured outline, MOST POPULAR badge) (65b23bd)
    • shared: add planHasActivityLog plan-tier helper (562428f)
    • mobile/paywall: add PaywallError + PaywallRestored panels (68ce006)
    • mobile/paywall: add PaywallUnavailable component (71b1f8f)
    • mobile/paywall: add PaywallFeaturesList component (2d6a284)
    • mobile/paywall: add PaywallHero component (7ce0a70)
    • i18n: add paywall redesign keys (en) (37e1613)
    • shared: add planIsPaid helper; use in web focus stats gate (7906b7f)
    • mobile: always play full splash reveal animation (64f62b9)
    • mobile: splash squares reveal animation (ff36b5b)
    • mobile: promote Plan with AI to solid full-width tile + brand fresh-user sparkle (bc4058d)
    • mobile: drop ContextFAB from project detail screen (5a1c1f5)
    • i18n: add task.add_a11y, task.add_to_project_a11y, filters.new_a11y (20fa59d)
    • mobile: context-aware FAB on project, board, filter, habits, next-actions, triage (1e89f29)
    • mobile: wire ContextFAB on 4 tab screens, seed compose context (c1d64fb)
    • mobile: add ContextFAB chrome primitive + tests (5cf5ac5)
    • mobile: board column footer redesign (1d1a52d)
    • mobile: add SheetHandle component and handle_a11y i18n key (43afa1c)
    • mobile: hoist title input and manual keyboard tracking in compose sheet (b418784)
    • i18n,docs: visual filter builder strings + docs/features/filters.md (a007570)
    • mobile: wire filter editor nav + drop inline creator (6ba4cf4)
    • mobile: visual filter create/edit screens with live preview (4790884)
    • mobile: visual filter builder primitives (rows + sheets) (fba3477)
    • shared: visual filter model + DSL serializer + legacy parser (1e4668d)
    • mobile: name the blocking task when tapping a blocked checkbox (a1e628e)
  • Fixes
    • mobile: tint board column with surface token instead of background (07f1baa)
    • mobile: match Browse FAB plus glyph size to other tabs (214e88b)
    • ui: raise quick-add bar contrast, add bottom inset (740d2ec)
    • mobile: wire auth text to fixed inks + brand-orange CTA (28a65e5)
    • one-Inbox-per-user dedupe + slow-query proxy data-loss fix (5245f9e)
    • api: stop slow-query proxy from breaking db.delete().where() (923faaf)
    • db: guarantee one Inbox per user (dedupe migration + unique index + adopt-existing) (77cfdbf)
    • mobile: theme add-task modal card (a1b8b58)
    • mobile: focus compose title after sheet enter (4cf3fe5)
    • shared: normalize labelIds to string[] at schema boundary (eecf005)
    • api: hand off OAuth-start auth via single-use nonce, keep JWT out of URLs (2819021)
    • repair failing local CI gates (0a19da1)
    • mobile: fire task-created toast on insert, not after reminder write (c21e8c3)
    • mobile/paywall: use useGuardedRouter for the close handler (18a7ad2)
    • mobile/biometric: correct off-by-one in PIN attempts-before-lockout counter (a07d096)
    • mobile/paywall: set transparent header at root, override headerLeft in screen (2f88cac)
    • mobile/paywall: add transparent header with X close button (f63998d)
    • mobile: restyle compose footer Cancel/Create as full-width buttons (f811e49)
    • mobile/paywall: register paywall as modal at root stack (1deab3a)
    • mobile/paywall: hide redundant modal header above hero (7c071b5)
    • mobile: merge fab follow-ups — tourTarget thread + config owner guard (7d177e1)
    • mobile: thread FAB tourTarget, guard config owner (957c7fc)
    • mobile: hoist tab FAB out of animated scenes (49d8d1b)
    • web: fit inbox placeholder to column width (b08a75b)
    • mobile: soften Plan with AI tile fill to 90% primary (9ffa951)
    • mobile: slow add-task modal slide-up to 500ms (06907ce)
    • mobile: slow tab-switch animation to 300ms (ca3695b)
    • keyboard avoidance broken on Android edge-to-edge (d79fa39)
    • mobile: keep splash up until ClerkLoaded to avoid +not-found flash (114e468)
    • ui: avoid keyboard overlap in create-project modal (097958c)
    • ui: size native Skeleton fill correctly (c436b97)
    • ui: size Skeleton fill correctly + restore pulse (9706403)
    • mobile: wire compose Create button to tasks.create (3d429be)
    • mobile: always-mount compose sheet to kill open flash (511b0bb)
    • mobile: snap compose scrim instead of fading on open (2d4ec49)
    • mobile: snap compose scrim opacity to kill open flash (f14cb4e)
    • mobile: slide compose sheet in and cover keyboard gap (b55c771)
    • mobile: edit button on run screen main branch + lint escape for legacy header (4e9546a)
    • mobile: show blocked-by chip on project task rows (625c000)
    • mobile: AI plan sheet keyboard avoidance + 60s timeout + header ellipsis (7183a92)
  • Other
    • mobile: centralize pre-auth color palette (f1d6348)
    • web,mobile: keep submit-guarded files under the 150 LOC cap (611d0b6)
    • mobile: collapse compose sheet to detailed-only (c882974)

iOS 1.2.0 — 2026-06-15 (build 43)

  • Features
    • task-created 'Open' toast on mobile add-task + web compose/quick-add (92180d2)
    • mobile: show 'Task created · Open' toast after add-task save (2dc1c9f)
    • shared/i18n: add toast.task_created + toast.open keys (82708c0)
    • web,mobile: guard PowerSync-path create/edit handlers against double-submit (a23a9e9)
    • web,mobile: guard useRestMutation against double-submit (395060c)
    • shared: add useSubmitGuard re-entrancy guard hook (5495d33)
    • api: merge plan-gate 6 — dev/setPlan all paid tiers + entitlements.tier CHECK (30450e0)
    • api: widen dev/setPlan to all paid tiers + lock entitlements.tier (e4b6200)
    • mobile/paywall: redesign paywall screen (Direction C, tap-to-buy) (1f4bd34)
    • i18n: translate paywall redesign keys to de/fr/pl/uk (f562545)
    • mobile/paywall: compose new sub-components in screen shell (6ec3cbf)
    • mobile/paywall: inline restored panel + reload via reloadTick (b45e3c3)
    • web: gate activity log behind paid plan (ada49af)
    • mobile/paywall: redesign plan cards (split row, featured outline, MOST POPULAR badge) (65b23bd)
    • shared: add planHasActivityLog plan-tier helper (562428f)
    • mobile/paywall: add PaywallError + PaywallRestored panels (68ce006)
    • mobile/paywall: add PaywallUnavailable component (71b1f8f)
    • mobile/paywall: add PaywallFeaturesList component (2d6a284)
    • mobile/paywall: add PaywallHero component (7ce0a70)
    • i18n: add paywall redesign keys (en) (37e1613)
    • shared: add planIsPaid helper; use in web focus stats gate (7906b7f)
    • mobile: always play full splash reveal animation (64f62b9)
    • mobile: splash squares reveal animation (ff36b5b)
    • mobile: promote Plan with AI to solid full-width tile + brand fresh-user sparkle (bc4058d)
    • mobile: drop ContextFAB from project detail screen (5a1c1f5)
    • i18n: add task.add_a11y, task.add_to_project_a11y, filters.new_a11y (20fa59d)
    • mobile: context-aware FAB on project, board, filter, habits, next-actions, triage (1e89f29)
    • mobile: wire ContextFAB on 4 tab screens, seed compose context (c1d64fb)
    • mobile: add ContextFAB chrome primitive + tests (5cf5ac5)
    • mobile: board column footer redesign (1d1a52d)
    • mobile: add SheetHandle component and handle_a11y i18n key (43afa1c)
    • mobile: hoist title input and manual keyboard tracking in compose sheet (b418784)
    • i18n,docs: visual filter builder strings + docs/features/filters.md (a007570)
    • mobile: wire filter editor nav + drop inline creator (6ba4cf4)
    • mobile: visual filter create/edit screens with live preview (4790884)
    • mobile: visual filter builder primitives (rows + sheets) (fba3477)
    • shared: visual filter model + DSL serializer + legacy parser (1e4668d)
    • mobile: name the blocking task when tapping a blocked checkbox (a1e628e)
  • Fixes
    • mobile: fire task-created toast on insert, not after reminder write (c21e8c3)
    • mobile/paywall: use useGuardedRouter for the close handler (18a7ad2)
    • mobile/biometric: correct off-by-one in PIN attempts-before-lockout counter (a07d096)
    • mobile/paywall: set transparent header at root, override headerLeft in screen (2f88cac)
    • mobile/paywall: add transparent header with X close button (f63998d)
    • mobile: restyle compose footer Cancel/Create as full-width buttons (f811e49)
    • mobile/paywall: register paywall as modal at root stack (1deab3a)
    • mobile/paywall: hide redundant modal header above hero (7c071b5)
    • mobile: merge fab follow-ups — tourTarget thread + config owner guard (7d177e1)
    • mobile: thread FAB tourTarget, guard config owner (957c7fc)
    • mobile: hoist tab FAB out of animated scenes (49d8d1b)
    • web: fit inbox placeholder to column width (b08a75b)
    • mobile: soften Plan with AI tile fill to 90% primary (9ffa951)
    • mobile: slow add-task modal slide-up to 500ms (06907ce)
    • mobile: slow tab-switch animation to 300ms (ca3695b)
    • keyboard avoidance broken on Android edge-to-edge (d79fa39)
    • mobile: keep splash up until ClerkLoaded to avoid +not-found flash (114e468)
    • ui: avoid keyboard overlap in create-project modal (097958c)
    • ui: size native Skeleton fill correctly (c436b97)
    • ui: size Skeleton fill correctly + restore pulse (9706403)
    • mobile: wire compose Create button to tasks.create (3d429be)
    • mobile: always-mount compose sheet to kill open flash (511b0bb)
    • mobile: snap compose scrim instead of fading on open (2d4ec49)
    • mobile: snap compose scrim opacity to kill open flash (f14cb4e)
    • mobile: slide compose sheet in and cover keyboard gap (b55c771)
    • mobile: edit button on run screen main branch + lint escape for legacy header (4e9546a)
    • mobile: show blocked-by chip on project task rows (625c000)
    • mobile: AI plan sheet keyboard avoidance + 60s timeout + header ellipsis (7183a92)
  • Other
    • web,mobile: keep submit-guarded files under the 150 LOC cap (611d0b6)
    • mobile: collapse compose sheet to detailed-only (c882974)

Android 1.2.0 — 2026-06-13 (versionCode 5)

  • Features
    • mobile: drop ContextFAB from project detail screen (5a1c1f5)
    • i18n: add task.add_a11y, task.add_to_project_a11y, filters.new_a11y (20fa59d)
    • mobile: context-aware FAB on project, board, filter, habits, next-actions, triage (1e89f29)
    • mobile: wire ContextFAB on 4 tab screens, seed compose context (c1d64fb)
    • mobile: add ContextFAB chrome primitive + tests (5cf5ac5)
    • mobile: board column footer redesign (1d1a52d)
    • mobile: add SheetHandle component and handle_a11y i18n key (43afa1c)
    • mobile: hoist title input and manual keyboard tracking in compose sheet (b418784)
    • i18n,docs: visual filter builder strings + docs/features/filters.md (a007570)
    • mobile: wire filter editor nav + drop inline creator (6ba4cf4)
    • mobile: visual filter create/edit screens with live preview (4790884)
    • mobile: visual filter builder primitives (rows + sheets) (fba3477)
    • shared: visual filter model + DSL serializer + legacy parser (1e4668d)
    • mobile: name the blocking task when tapping a blocked checkbox (a1e628e)
  • Fixes
    • ui: size native Skeleton fill correctly (c436b97)
    • ui: size Skeleton fill correctly + restore pulse (9706403)
    • mobile: wire compose Create button to tasks.create (3d429be)
    • mobile: always-mount compose sheet to kill open flash (511b0bb)
    • mobile: snap compose scrim instead of fading on open (2d4ec49)
    • mobile: snap compose scrim opacity to kill open flash (f14cb4e)
    • mobile: slide compose sheet in and cover keyboard gap (b55c771)
    • mobile: edit button on run screen main branch + lint escape for legacy header (4e9546a)
    • mobile: show blocked-by chip on project task rows (625c000)
    • mobile: AI plan sheet keyboard avoidance + 60s timeout + header ellipsis (7183a92)
  • Other
    • mobile: collapse compose sheet to detailed-only (c882974)

iOS 1.2.0 — 2026-06-13 (build 42)

  • Features
    • mobile: drop ContextFAB from project detail screen (5a1c1f5)
    • i18n: add task.add_a11y, task.add_to_project_a11y, filters.new_a11y (20fa59d)
    • mobile: context-aware FAB on project, board, filter, habits, next-actions, triage (1e89f29)
    • mobile: wire ContextFAB on 4 tab screens, seed compose context (c1d64fb)
    • mobile: add ContextFAB chrome primitive + tests (5cf5ac5)
    • mobile: board column footer redesign (1d1a52d)
    • mobile: add SheetHandle component and handle_a11y i18n key (43afa1c)
    • mobile: hoist title input and manual keyboard tracking in compose sheet (b418784)
    • i18n,docs: visual filter builder strings + docs/features/filters.md (a007570)
    • mobile: wire filter editor nav + drop inline creator (6ba4cf4)
    • mobile: visual filter create/edit screens with live preview (4790884)
    • mobile: visual filter builder primitives (rows + sheets) (fba3477)
    • shared: visual filter model + DSL serializer + legacy parser (1e4668d)
    • mobile: name the blocking task when tapping a blocked checkbox (a1e628e)
  • Fixes
    • ui: size native Skeleton fill correctly (c436b97)
    • ui: size Skeleton fill correctly + restore pulse (9706403)
    • mobile: wire compose Create button to tasks.create (3d429be)
    • mobile: always-mount compose sheet to kill open flash (511b0bb)
    • mobile: snap compose scrim instead of fading on open (2d4ec49)
    • mobile: snap compose scrim opacity to kill open flash (f14cb4e)
    • mobile: slide compose sheet in and cover keyboard gap (b55c771)
    • mobile: edit button on run screen main branch + lint escape for legacy header (4e9546a)
    • mobile: show blocked-by chip on project task rows (625c000)
    • mobile: AI plan sheet keyboard avoidance + 60s timeout + header ellipsis (7183a92)
  • Other
    • mobile: collapse compose sheet to detailed-only (c882974)

Android 1.1.0 — 2026-06-12 (versionCode 4)

No user-visible changes since previous release. versionCode bump only — first end-to-end run of scripts/android-release.sh. Finalize step bug (wrong-platform write) caused a reverted commit; see release-versioning design doc followup.

iOS 1.1.0 — 2026-06-11 (build 41)

Seeded — pre-mechanism release history not backfilled.

Android 1.1.0 — 2026-06-11 (versionCode 3)

Seeded — pre-mechanism release history not backfilled.