The Two Bad Answers
With the inventory on the table and the cross-app bug fresh, there are two answers that present themselves immediately, and both are worse than they look.
Merge the apps. One codebase, one deploy, no duplication by construction. It solves the stated problem completely and creates a bigger one: three domains that genuinely disagree now have to share a data model, a navigation structure, and a release cadence. A travel app organizes everything around a journey with a start and an end. A journal deliberately has no container at all — its whole identity is an open timeline. A health log refuses terminal states because a reading is never a verdict. These are not skinnable variants of one program. Merging them would trade a duplication problem for a modeling problem, and modeling problems do not have a script that fixes them.
Do nothing and be disciplined. Agree that the shared files must be kept in sync by hand, and rely on everyone remembering. This is the option that was in effect on the day of the measurement, and the measurement is what it produced.
The Ruling
The call, made the same day the inventory was taken: the apps stay separate, because their domains are genuinely different. The shared plumbing gets exactly one owner — a repository whose entire job is to hold the code that is identical across siblings by design, and to deliver it.
Notice how narrow that is. It is not "share what happens to be similar". Similar-looking code in two apps is often two correct answers to two different questions, and forcing them together produces a parameter-riddled function that serves neither. The scope is code whose correct shape does not depend on what the app is about — which is a much smaller set, and a much more defensible one.
The Mirror Rule, Stated at Birth
A repository that holds shared code exerts a constant pull. Every time two apps need something similar, the cheapest move is to put it in the shared place, and each individual instance of that is defensible. The end state, reached one defensible step at a time, is a framework: something every app must be built around, that knows what apps are about, and that nobody can change without changing all of them.
So the rule was written in the same breath as the repository's purpose, pointing the other way: domain code never migrates into the kit. Plumbing in, domain never out of its app. The sibling architecture documents already forbade the apps from copying each other's domain spines — one of them says outright that the journey/day axis must not be copied over unexamined — and a shared repository is exactly the backdoor that would let that happen without anyone noticing they were doing it.