I am Masaki Hirokawa, an artist and indie app developer. I run Gemini Lab.
Late last week, I finally pushed Beautiful HD Wallpapers v2.1.0 for Android into staged rollout. It is one title from a series that has crossed fifty million downloads since I went independent in 2013, but every release-eve still finds me quieter than usual. Today I want to write down what happened during the final hours, when I handed the diff to Gemini 3.2 and asked it to read for me.
This is less of a how-to and more of a field note. The kind of note that says: Gemini's models are progressing softly, in ways you only notice when you sit with them in the trenches of an actual release.
A Saturday at midnight, with one hour set aside on purpose
It was almost Sunday when I sat back down at my desk. The 5% rollout was scheduled for the next morning. The Android Studio build had passed. The Crashlytics dSYM setup was done. The Play Console staged rollout was drafted.
Even so, I always reserve a final hour, before any release, to walk the diff through Gemini one more time. This has been a personal rule of mine since the v1 series: I want a quiet pass from a non-human reader, just before the rollout button. Not because I distrust myself, but because tired humans see what they want to see, and silent machines do not.
I usually paste the diff for the three or four files that changed since the last tagged build, and tell Gemini something like: "Read this with crash risk and API-level differences in mind. Do not explain. Just point at what worries you." I deliberately skip context, skip line numbers, skip my own theories. The goal is to let Gemini look at the code without being pulled toward my own assumptions.
What Gemini chose to surface first surprised me
The first comment back was not what I expected.
"I do not see coreLibraryDesugaringEnabled set to true in your module Gradle. With Glide 5.0.5 and AGP 9.x, dropping below minSdkVersion 23 can produce NoClassDefFoundError for java.util.function.Supplier on devices like Android 6.0.1."
When I read that, my back went cold. After the v2.0.0 release a month earlier, my Android 6.0.1 users had been hitting a curious crash that paired RecyclerView with a NoClassDefFoundError. I had shelved it as a "weird device cluster" and kept moving. The truth is, I knew I was deferring it.
Gemini pointed straight at the deferral.
Two lines: turn on coreLibraryDesugaringEnabled in the module Gradle, add the coreLibraryDesugaring dependency. That was the entire change. Three days into the staged rollout, the Android 6.0.1 crash cluster was almost gone. Regions that had been below 99.7% Crash-free users were back above 99.95%.
The way Gemini 3.2 chose its comments has gotten quieter
What I found most interesting about this pass was that Gemini 3.2 picked its battles with a notably calmer hand than older generations.
Previous models, when asked to review a diff, would walk the whole surface. "Here is a small thing." "Here is another small thing." That kind of generous attention has its place, but at the eve of a rollout, what I actually want is "what could kill us tonight."
With 3.2, the same prompt returned exactly three remarks:
coreLibraryDesugaringEnabledmissing (lethal).- A
RecyclerView.AdapternotifyItemRangeRemovedcall followed by a read on the original list (latent risk). - A nested guard around the back-button ad gate that makes priority hard to read (maintainability).
The lethal one was first, the maintainability one was last, and the maintainability remark came with a quiet "not relevant to tonight's release." That order, that temperature — it was exactly what a release-night co-reviewer should feel like.
The defensive copy line I added at one in the morning
The second remark — the notifyItemRangeRemoved one — was actually something I thought I had fixed a week earlier. v2.0.0 had spawned an IndexOutOfBoundsException cluster that I believed I had killed with defensive list copies.
But when I gave the diff to Gemini, it noticed that another file still held the old call path. One file copied the list before mutating it; the other reached into the original. If I had not caught it that night, I would have learned about it from crash reports across another month-long delay.
I fixed it past 1:00 AM. The room was quiet, the coffee was on its third cup, my hands were tired. I gave the diff back to Gemini and asked, "Is the defensive copy pattern symmetric now?" It answered, "Yes." That was enough. I closed the laptop.
On having "a second pair of eyes" as a solo developer
You might read this and think, "Then anyone with Gemini can do this." Maybe. But what I have learned in twelve years of indie work is something slightly different.
Gemini tends to pick up the very things I have been trying to forget. The coreLibraryDesugaringEnabled flag was something I had been quietly deferring. Humans, when they are tired, learn to look past their own deferred problems. Gemini has no emotion to spend on avoidance, so it simply names what is there.
Both of my grandfathers were temple carpenters. They worked as if "moving the hands was itself a form of devotion." I do not compare my work to theirs, but having a calm reader sit beside me every release has made me feel less willing to let my own attention slip. The merit, I think, is not really Gemini's. It is that having Gemini there has made it harder for me to take a shortcut.
A small rule: do not change models inside a release window
One more practical note from the field.
I keep the model fixed for the 48 hours around a release. If I am using Gemini 3.2 for the code review pass, I stay on 3.2 for the entire release window. No swapping to 2.5 Pro halfway, no jumping over to a different model entirely.
The reason is that different models weight "what is worrying" slightly differently. Mixing perspectives during a release-night rush tends to bury the problem you actually saw, under a new model's slightly different priorities. Especially with 3.2, where the gap between "lethal" and "maintenance" is the most settled I have seen, holding one model for the whole window keeps my decisions sharp.
I have written similar observations before in Three Months with Gemini 2.5 Pro: A Solo Developer's Honest Report and Three Weeks with Gemini 3.2: A Personal Developer's Field Notes. Switching models often is not always wisdom. Sometimes a single companion across a long day is the better choice.
Closing — what I want to prepare before the next release
The 5% rollout is the first step. I plan to lift it to 25%, then 50%, watching only two numbers: Crash-free users staying above 99.7%, ANR rate staying below 0.20%. If both hold, the rollout will reach 100% next week.
After that, I move back to four iOS apps that are mid-update. Firebase Apple SDK is migrating from CocoaPods to Swift Package Manager. StoreKit 2 is replacing the legacy SKPayment flow. I expect both of those to show up in this blog soon. If you are curious about the surrounding ground, Gemini Lab has a practical guide to Gemini API Function Calling and a one-week report on Gemini CLI inside iOS app development.
If I were to suggest one book, I would point at Android アプリ開発の教科書 第2版 (Hiroaki Kaneda) — admittedly a Japanese-language reference, but the one I keep pulling from my shelf for the discipline of release thinking. It does not cover coreLibraryDesugaringEnabled. It does help me return to the right posture before a release.
Thank you for reading. If the 100% rollout lands cleanly next week, I will be back with the next chapter.