The problem
Two people on the same trip see each day differently. ourlog gives both phones the same five photo or video prompts each day, which the app calls quests. The clips sync and pair up by quest into a shared diary, and finally a film of the whole trip with both points of view. Footage can’t be shot again, so losing a clip is the one failure the app can’t allow.
Who did what
I set the principles and the design direction. Claude Code wrote the app and its sync engine through six project agents. The agents that build and install aren’t allowed to commit, and the git-flow agent merges only after a review with no Blockers. Claude Code is co-author on 95 of 106 commits.
Constraints
- The phone is the source of truth. A failed upload, trim or sync never loses a clip.
- Mobile data matters: never download bytes already on the phone, never upload what the cloud already has.
- The app runs in a WebView, so at most two videos decode at once.
- Plain JavaScript with no bundler.
The trade-off
Sync is last-write-wins between two people, with tombstones for deletes, instead of a sync framework. It’s small enough to reason about, but it accepts that one of two simultaneous edits is lost, and it needed a fix: two phones creating the same record in the same millisecond each kept their own text, until a tie-break made both pick the same one.
Outcome
- In use by the two of us. Not on any store yet: a TestFlight and Play release is on the backlog.
- About 680
assertcalls in 45 test files. - 106 commits from June to October 2026.
How it was built
- Six agents. The two that guard data,
sync-engineerandreviewer, run on Opus. The iOS, Android, UI and git agents run on Sonnet. reviewerreports findings as Blocker, Major or Minor with a file and line, and never edits.git-flowwon’t merge unless the latest review has zero Blockers and every test passes.CLAUDE.mdlists the invariants that can never change, such as quest ids being append-only.