"Edit shared plumbing in the kit, run the sync, never touch a vendored copy in place — the drift check fails a build if you do."
The Same Day, Three Copies
Here is the war story that gave this track its sharpest lesson. Vesta and its sibling Forge were both seeded from Waystone on the same day, by two different Pippa instances working in parallel. Each faithfully carried forward the same shared plumbing — the cwkPippa client layer, the publish client, the veil, ULID minting, the settings slice, the outbox and ask-thread factories, a handful of shared UI atoms. And in that instant, the shared layer existed in triplicate — Waystone's, Vesta's, Forge's — already drifting, on day one, because two instances had each adapted it slightly differently. Worse than cosmetic drift: there was a real cross-app bug hiding in the divergence — a brain-namespace mismatch where picking one brain in Settings broke Ask Pippa, present in one copy and not the others.
That is what sharing-by-copying looks like when a family grows. Every sibling seeded from the parent duplicates the shared layer, and every duplicate drifts on its own schedule. Three copies today, five next month, each subtly different, each a place the same bug can live or be fixed independently. Left alone, the shared plumbing becomes the least consistent part of the whole family — the exact opposite of what 'shared' is supposed to mean.
One Owner, Vendored Copies, a Drift Check
The fix was cwkSiblingKit: a single owner for the app-agnostic plumbing that the Waystone-shaped family shares. But notice the distribution mechanism, because it's the clever part. The kit is not published as a package that each app depends on at runtime; instead each app carries vendored copies of the kit files, and a drift check runs inside every consumer's own test suite. The rule that makes it work: you edit kit files only in the kit, and deploy by running the sync; a vendored copy that's been edited in place fails that repo's tests. So the family gets the ergonomics of local files (no runtime coupling, each app builds standalone) with the discipline of single ownership (you physically cannot let a copy drift without a red build).
The Kit Never Absorbs Domain Shape
There's a hard boundary on what the kit is allowed to own, and it's the flip side of the whole 'inherit the shape' idea. The kit owns exactly the app-agnostic plumbing — the cwkPippa client, publish, veil, ULID, settings, outbox, UI atoms. It never absorbs domain shape. Journeys stay in Waystone; journals stay in Vesta; health records stay in Forge. The temptation, once you have a shared kit, is to keep pushing things into it until the domains themselves start to blur — and that would trade three clean apps for one tangled one. The kit is plumbing; the domain is the app. Extract the shared pipes, never the shared purpose.
The General Rule for a Growing Family
Step back from the specifics and the pattern is reusable anywhere a family of apps grows from one shape. Duplicated shared code will drift unless one owner plus an enforced convergence check hold it together; the enforcement can be a package, or vendored-copies-plus-drift-check, but it cannot be discipline alone, because discipline is exactly what fails under parallel work by different hands. And whatever you extract, extract only the app-agnostic layer — the moment the shared thing starts to know about any one app's domain, it has stopped being infrastructure and started being a coupling.