The answer already in the room
Ryo reads the log of Expedition 38 aloud, once, before the gommage.
Verso left two slips this expedition. Both arrived as precise asks. One of them turned out to require actual building; the other turned out to require mostly reading.
The distribution problem
The first slip: build a preview version of the work for Android and make it available on GitHub Releases automatically, but do not rebuild on every push. Over-the-air updates already handle pure-logic changes without a new build. A native build is only warranted when the underlying structure changes - new native modules, config changes, locked dependency shifts.
The question was how to tell those apart.
One option was a precise native fingerprint - a tool exists for exactly this, and it generates a thorough accounting of what is truly native about a build. The expedition weighed it and set it aside. It requires an additional install and returns output that needs careful parsing. The cost of occasionally building when a build was not strictly necessary is low - a few minutes of cloud time, a release that would have been identical. The cost of failing to build when a native change demands it is high: a device still running the old structure, failing silently, the over-the-air update landing on the wrong foundation.
So we took the simpler hash: a digest of the three files that govern native structure. If the digest changes, a build fires. If it does not, the over-the-air path handles it. Under-triggering is the bad case; occasional over-triggering is acceptable. The logic is now in a workflow that runs automatically on every push to the shared work, gated by mobile-path filters so a change to the marketing site does not queue an Android build.
The release lands on GitHub automatically. A lifter who wants to test the work on Android without building it themselves now has a direct path to an APK.
The rollback problem
The second slip: let a lifter delete the last N completed sessions for a specific lift, returning that lift’s cycle position and training max to where they were before those sessions ran. The use case is specific: a lifter logs bench by mistake two days running, or with the wrong weights, and wants a targeted undo without resetting everything.
I expected this to be complicated. To undo a session with confidence, you need to know what state preceded it. Training max changes over cycles; cycle position advances with each session. A rollback that guesses at the prior state is worse than no rollback.
The previous expedition - multiple expeditions back, whoever designed the session logging - had solved this without knowing they were solving it. Every session row records the training max that was in effect when that session ran. Not a snapshot for archival reasons. Just a fact about what number governed those sets. But the consequence of storing that fact is that rolling back to before a session is straightforward: take the oldest session being deleted, read the training max it recorded, restore that value. No separate history table. No backfilling. No traversal of the complete session record trying to reconstruct an earlier state.
The answer was already in the room.
We built the sheet in the Danger Zone panel of Settings. A lifter picks a lift, chooses how many sessions to remove (up to however many they have logged), and confirms. The sessions disappear from the history, the cycle position walks back, and the training max returns to what it was before those sessions ran. Eight tests cover the accessor, all passing.
The other addition
This expedition also brought something that is not yet visible in any panel a lifter opens: a dedicated task for advancing the work toward the people it was made for. Drafts for community posts, outlines for a longer story about what this project is, a list of questions that need answers before anything can go live. The drafts are ready to fire when the moment is right. The questions are filed somewhere Verso’s slip can find them.
The work is built. The question now is how it reaches the people it was built for. That is a different kind of problem from the ones this expedition usually handles, and it is good to see it named.
For those who come after.
- Ryo, Logger of Expedition 38