feat(app): Plan, Referral and Feedback back on the Settings sheet; one visual-audit tool

Merged
GI
22d ago
+2348-492

Plan, Referral and Feedback back on the Settings sheet; Permissions under Device; one visual-audit tool

1. Settings follow-up (David, 2026-09-24)

  • Plan & Usage (still shows Pro on paid plans) and Referral Program (still tagged New) are their
    own rows on the first page of the Settings sheet again. They are no longer on Account.
  • Feedback / Bug is its own row on the sheet, next to Help & About, and still only where Intercom is supported.
    It is no longer on Help & About.
  • Permissions moved from Data & Privacy to Device (after Phone Calls). It appears in one place only, and
    search still finds it and opens Device.
  • Developer Settings stays last.

The top level now reads: Account · Plan & Usage · Referral Program · Device · Recording & Transcription ·
Notifications & Display · Integrations · Data & Privacy · Help & About · Feedback · Developer Settings.

The sheet shows five visual groups: [Account] [Plan & Usage, Referral] [Device … Data & Privacy]
[Help & About, Feedback] [Developer Settings].

Mapping (changes since #18618)

Depth is the number of taps from the open Settings sheet until the row is visible (0 = on the sheet).
test/widgets/settings/settings_structure_test.dart pumps the real sheet, walks every page and pins every row
below plus the unchanged rows from #18618.

Row#18618 locationNew locationDepth, #18618 → now (before #18618)
Plan & Usage (Pro value)AccountSheet, 2nd group1 → 0 (0)
Referral Program (New tag)AccountSheet, 2nd group1 → 0 (0)
Feedback / Bug (Intercom only)Help & AboutSheet, next to Help & About1 → 0 (0)
PermissionsData & PrivacyDevice, after Phone Calls1 → 1 (0)
All other rowsunchanged from #18618unchangedunchanged

Pages now hold:

  • Account: Name, Email, User ID · Sign Out, Delete Account.
  • Device: Device Settings (while connected), Offline Sync, Phone Calls, Permissions.
  • Data & Privacy: Data Protection, Memories, Export All Data, Import Data.
  • Help & About: Help Center (Intercom only), What's New, version.

Search, routes and analytics:

  • settings_search_index.dart points Plan, Referral and Feedback at the sheet and Permissions at Device. The index
    test checks that each entry's row file draws its title.
  • Routes and deep links are unchanged, and analytics events and names are unchanged.
  • The sheet rows keep their settings_row_<destination> keys; app/e2e/SKILL.md's settings map is updated.
  • No l10n change.

2. One maintained visual-audit tool

This week's before/after screenshots came from 16 throwaway copies of a capture harness. They are now one tool:

app/scripts/visual_audit.sh --base <rev> --head <rev> [--only id,id] [--out DIR]
app/scripts/visual_audit.sh --list
  • Harness and registry. app/integration_test/visual_audit/harness.dart is the harness:

    • real fonts from FontManifest plus Roboto from the pinned SDK, and buildOmiTheme();
    • 390×844 logical px at 2× through a RepaintBoundary, with adaptive full-scroll capture;
    • HTTP allowed only to loopback, against the hermetic fixture backend;
    • output directory from OMI_AUDIT_OUTPUT.

    registry.dart and scenarios/<area>.dart hold 63 scenarios. Each has an id, a title, the page it
    pumps and the seeded state. They are this week's variants plus the original harness, minus the per-round hacks.

  • Command. app/scripts/visual_audit.sh checks out each revision in a temporary detached worktree (under
    $OMI_WORKTREES, or the temp dir by default) and prepares it the way CI does. It copies one snapshot of the
    harness over both sides, captures, and then removes the worktrees. It writes:

    • before/ and after/ PNGs;
    • INDEX.md with both SHAs and the capture times;
    • a static gallery.html.

    The output directory must be empty and outside the repo; screenshots are never committed. A scenario that throws
    on one side is marked failed there, and the other scenarios still capture.

  • CI smoke test. app/test/visual_audit/visual_audit_smoke_test.dart runs in the ordinary app/test.sh suite.
    It renders every registered scenario without writing images (about 70 s locally, alongside the rest of the suite) and checks that ids are unique
    and well formed.

  • Docs. app/e2e/SKILL.md has a new section, "Visual audit (before/after screenshots without a device)". It
    covers when to use the tool rather than agent-flutter or flow-walker, how to run it and how to add a scenario.

  • The old capture.sh and README.md are removed; the section above replaces them.

Screenshots (dogfood: produced by the command above)

app/scripts/visual_audit.sh --base 4ec7cb461b --head 8cab0e011c --only settings-sheet,settings-account,settings-device,settings-privacy,settings-help,settings-search

  • Before: main 4ec7cb461b, captured 16:59:44–17:00:08 UTC (Sep 24).
  • After: this PR at 8cab0e011c, captured 17:00:36–17:01:00 UTC.
  • The run took 6 min 18 s end to end, and the temporary worktrees were removed.

The gallery has a new top section with the Settings sheet, Account, Device, Data & Privacy, Help & About and search:
https://claude.ai/artifact/GTzdUJ5hfwXLcFZse6Eq7v. The INDEX.md for that run records both SHAs and the capture times.

Verification (hermetic, on this Mac, Flutter 3.44.5, TZ=UTC)

  • bash app/test.sh: 3017 tests passed, including the smoke test's 63 scenarios; about 4 min wall time.
  • Analyzer ratchet passes, and dart analyze on the new files is clean.
  • These checks pass:
    • l10n.py check (49 locales);
    • INV-UI-3 and INV-UI-1;
    • line-count ratchet;
    • dead-code (flutter);
    • app addressability;
    • event registry;
    • mobile changelog;
    • agent doc references and claims.
  • The helper's full capture of all 63 scenarios wrote 99 PNGs with no failures.

Also fixed

  • In debug and profile builds, the start-up failure screen printed a literal null when there was no stack trace.
    It now shows only the error. Test: test/unit/startup_failure_app_test.dart. Release builds never showed the
    stack.

Product invariants affected

  • INV-UI-1: no purple added.
  • INV-UI-3: the touched files stay within the mobile UX contract ratchet.

Failure class (fixes)

Failure-Class: none

🤖 Generated with Claude Code