# Do It or Dodge It: a Gemma on my phone either shrinks the task or writes the excuse

> Source: <https://dev.to/chestly_ace/do-it-or-dodge-it-a-gemma-on-my-phone-either-shrinks-the-task-or-writes-the-excuse-9ad>
> Published: 2026-10-26 01:08:33+00:00

*This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady](https://dev.to/challenges/hacktoberfest-week3-2026-10-19)*

You know the task. The email you have been meaning to send, the form with one box you can't fill in, the thing that has sat at the top of your list for two weeks. It is not hard. It is just *big enough to avoid*.

**Do It or Dodge It** is an Android app with exactly one idea: when you add a task you are avoiding, you get two honest buttons.

Either way the app notices. It learns which kinds of tasks *you* tend to dodge, shows you a risk score with a one-line reason ("You dodge admin tasks 70% of the time"), and uses that score to pace the nudges: a task you usually dodge gets more of them, closer together.

All of it runs on the phone. After a one-time model download there is no server, no account and no network use.

The APK is on the [releases page](https://github.com/chestlyace/Do-it-Or-Dodge-it/releases). It needs Android 11 or newer, a 64-bit ARM phone and 4 GB of RAM or more.

An Android app that runs entirely on your phone. You add a task you are avoiding, then pick one of two buttons:

The app learns which tasks you tend to dodge, shows a dodge risk with a one-line reason, and uses it to pace the nudges. It all happens on the phone. After a one-time model download there is no server, no account and no network use, and your tasks never leave the device.

Built for…

**Stack:** Flutter and GetX on Android; **Gemma 4** (E2B and E4B) running on the phone through LiteRT-LM via [`flutter_edge_ai`](https://pub.dev/packages/flutter_edge_ai); `drift` for the local SQLite database; `flutter_local_notifications` and `workmanager` for nudges and background jobs; and a dodge predictor written in plain Dart.

The interesting engineering is in making a small model *dependable*. The app gives Gemma four jobs: `shrinkTask`, `helpWithStep`, `writeExcuse` and `nudgeWording`. Each one asks for JSON in a fixed shape, and I validate the reply in code instead of trusting it:

If a reply fails, the app retries once with a stricter instruction that says exactly what was wrong. If it fails again, it shows the model's raw text and the reason. It never crashes, and it never pretends.

On first launch the app reads the phone's RAM and free storage and recommends a model: E2B (about 2.6 GB) for most phones, E4B (about 3.7 GB) at 8 GB of RAM or more. The file comes from Hugging Face's public `litert-community` repositories, **pinned to a commit** and checked against its SHA-256 before the app will use it. The download runs in a foreground service, resumes if interrupted, and can be limited to Wi-Fi.

The model loads only when you first tap Do It or Dodge It, and is released when the app goes to the background, so 3 GB of weights don't hold your RAM while you're elsewhere. If the GPU can't load it, the app retries on the CPU:

```
try {
  model = await _runtime.load(options);
} catch (e) {
  if (options.backend == ModelBackend.cpu) rethrow;
  model = await _runtime.load(options.copyWith(backend: ModelBackend.cpu));
  fellBackToCpu.value = true;
}
```

The nudges are plain local notifications, so firing one never needs the model. Each message is written once, stored and reused. Low, medium and high risk tasks get 2, 4 or 6 nudges a day, never between 21:00 and 09:00 by default, and each one names only the next undone step, never the whole task. A daily background job plans the next day, and nudges come back after a restart.

The theme fit the product by accident. A big task becomes a sequence of things you can do in a minute, delivered at a pace set by how likely you are to dodge it.

The risk score is a small logistic regression written in plain Dart and trained on your own outcomes: a few hundred rows at most, retrained after every task you finish or dodge. For your first twenty outcomes it uses a simple rule instead (how often you have dodged that category), because a model trained on five examples is just a guess in a nicer font.

The full tables are in [`docs/benchmarks.md`](https://github.com/chestlyace/Do-it-Or-Dodge-it/blob/main/docs/benchmarks.md).

**Check that your library is alive before you plan around it.** I planned the whole app around `flutter_gemma`. When I added it, pub.dev said it was discontinued, and its last release pointed everyone to `flutter_edge_ai`. I switched before writing code against it. The move also showed me that the on-device engine needs Android 11 and a 64-bit ARM phone, so my minimum Android version changed. Better to learn that at the start than on release day.

**Don't assume a model is locked.** I had decided users would need a Hugging Face token because "Gemma is gated". Checking the actual files showed the Gemma 4 LiteRT builds are public and Apache 2.0. That removed a whole class of problem: no token in the app, nothing to leak.

**Features can leak the answer.** My first design for the risk score used the number of steps Gemma produced as a feature. But only tasks you *do* get steps, so the model would have "learned" that steps mean done, true only because of which button you pressed, and every new task would have looked risky. Now the features are saved at the moment you choose, before any steps exist, and I wrote the limitation down instead of hiding it.

**Edge cases hide in plain sight.** A "last call" nudge is supposed to be the final one before the deadline. With a date-only due date and quiet hours starting at 21:00, no nudge ever landed close enough to the deadline to count. The fix was to define it as the last nudge that fits, not one within a fixed gap.

**Tests that drive the real screens find real bugs.** Running them at twice the normal text size found two layouts that overflowed (a button hidden in the add-task sheet, and the counts cut off in History) and a confirmation message that appeared somewhere you could not see it.

This is the part the app could not exist without.

The laziest feature is one you never see: while your phone charges, a background job quietly writes nudge text and a general excuse for your open tasks, so tapping **Dodge It** shows one instantly. The app does its thinking while you sleep.
