"The error named a file this repo does not own, has never edited, and whose last commit was hours old."
Why the Family Uses Them Anyway
The family's shared Swift lives in one package that more than a dozen apps consume with .package(path: "../SharedKit"). A path dependency means a change to the kit shows up in an app on the very next build — no tag, no version bump, no publishing step. For an audience of two people and a fleet of apps moving together, that immediacy is the point. It also comes with four failure shapes that look like something else entirely.
1. Another Session's Half-Finished Edit Breaks Your Build
A path dependency resolves to the working tree, not to a commit. A TestFlight upload died at its test step with cannot find 'decode' in scope — inside a kit file the app had never touched. A parallel session was mid-edit in the kit, and its unsaved-to-git change compiled straight into the app's build. The diagnosis takes one second: git -C ../SharedKit status --porcelain shows the file dirty. The correct response is to wait for the kit to compile and retry — never to fix or stash someone else's working tree.
2. An Archive Ships Uncommitted Kit Code
Worse than a broken build is a successful one. Between an app's test run and its archive, a kit session edited two files and had not finished a third. The archive tried to compile a kit that no commit contained, and failed only because that third file was unfinished. Had the edit been complete, the archive would have succeeded, and its build number would have named a binary nobody could reproduce. The family's upload pipeline now refuses to archive for delivery while the kit's sources differ from its HEAD, and stamps the kit commit into the build record.
3. A Consumer's Build Goes Stale and Stays Stale
A kit file gained a new type. The kit's own tests passed. A consumer app failed with "cannot find 'ProductManifest' in scope" on two builds in a row, while importing the same module successfully for six other types. The consumer's built module was older than the new source file. Do not read Package.swift first — compare two timestamps. If the consumer's module predates the kit source, it is staleness, and rm -rf .build in the consumer is the whole answer. Deleting only part of .build fails differently, because the build plan still names what you removed.
4. A Source-Compatible Change Breaks the Link
Adding a defaulted parameter to a public initializer is source-compatible — every call site still compiles. But default arguments are filled in at the call site, so the function's mangled symbol changes. Two consumers that construct the type then failed at link time with "Undefined symbols … PippaEndpoint.init(mode:host:port:)" — a symbol whose signature matched their own source exactly. They kept stale object files. swift package clean in each consumer fixed it with no source change. A clean two-package reproduction on Swift 6.3.3 recompiled the consumer and linked fine, so this is stale build state, not something every such change triggers. The tell: a compile error names a file and a line; this one names a mangled symbol and an object file. Do not revert the parameter to make it go away.