Nothing to Publish, Everything to Build
The path package removed two things on purpose: a publish step and a version number. This track has argued that both were costs with no counterparty in this family, and that argument still holds. But a version number does one more job that is easy to forget until it is gone. It lets a consumer decide when to take a change. A pinned consumer can sit on last month's types until it is ready.
A path consumer cannot. It compiles the kit directory as it sits, so every change to a public type reaches every consumer at that consumer's next compile, whether that compile is a deliberate upgrade or an unrelated bug fix someone happened to start that afternoon. That is exactly the coherence the package was adopted for. It is also a bill, and the bill arrives at the consumer, not at the kit.
Within a month of the split, three different shapes of that bill had arrived, and none of them was visible to the kit's own suite.
Three Breaks Nobody's Suite Saw
- A case added to a public enum. The kit's JSON value type gained a case for unsigned integers. The kit's tests passed, the build matrix passed, and every consumer that declares the package in its own package manifest built cleanly. A phone app built from a separate project file had a model with an exhaustive switch over that enum, and it stopped compiling at its next build. The repair was not only the switch. It was a rule: search every consumer for both spellings of a pattern match on that type, and build the project-file consumers too, not just the package-manifest ones.
- A public type named like an app's own type. Inside an app, the app's own declaration shadows the kit's, so nothing complains. In that app's test target, which imports both the app and the kit, the two names collide and the tests stop compiling. The kit's Markdown model was therefore placed under one top-level namespace before it shipped, after a search of consumers' test folders found an app that already had a type with the flat name.
- A product that brings a capability with it. The media product contains camera code. A phone app that links it — even for a different type in the same product — must declare why it uses the camera, or the store rejects the build by email after the release pipeline has already printed its success line. Three apps hit this on one day.
Each of these is a compatibility question that a published package would have forced someone to ask at publish time, with a changelog and a major-version bump. Without a version, nobody is forced to ask it. Somebody has to choose to.
The Growth Numbers, and What They Imply
In mid-September the package had nine products and fifty-three Swift files. A month later it has thirteen products and one hundred and nine files, roughly twenty-four and a half thousand lines, and its own suite has grown from about three hundred and seventy tests to roughly nine hundred. Products stay split by platform so that an app links only what its surfaces need — a phone composer does not link a web view to get a path fence.
The number that matters for the bill is not the product count. It is the number of consumer kinds: package-manifest consumers, project-file consumers, watch targets, test targets that import both an app and the kit. Each kind exposes a different class of break, and the kit's own suite is, by construction, none of them.