The name suggested ownership the code did not have
The confusion was not about whether buttons or cards could be shared. It was about which package owned the product's visual language. packages/ui sounded like the place for every reusable interface component, but its useful boundary was much narrower: it provided MapLibre primitives that the application could consume.
The project record does not preserve enough evidence to claim a particular pull request sequence on August 24. The relevant boundary change is visible in commit f4f327e, which moved application aliases toward apps/web/src/ui and reduced the public package exports. That is the evidence this postmortem can stand behind.
The export diff made the correction concrete
This excerpt from the historical packages/ui/package.json diff shows the change in ownership:
"./globals.css": "./src/styles/globals.css", "./lib/*": "./src/lib/*.ts", "./components/*": "./src/components/*.tsx", "./hooks/*": "./src/hooks/*.ts" "./components/ui/map": "./src/components/ui/map.tsx", "./components/ui/map-source": "./src/components/ui/map-source.tsx", "./lib/utils": "./src/lib/utils.ts"The old package exposed a broad component and stylesheet surface. The corrected surface names map components and a utility explicitly. It does not export the application's buttons, cards, fields, mobile sheet, or product tokens.
The current package barrel says the same thing in code. It exports Map, markers, controls, and map overlays from packages/ui/src/components/ui/map.tsx. The product primitives live under apps/web/src/ui/core, while the application shell and mobile sheet live under apps/web/src/ui/layout.
This is the relevant part of the current barrel:
export { Map, useMap } from "./map-core"export { MapMarker, useMarkerContext, MarkerContent, MarkerPopup, MarkerTooltip, MarkerLabel, MapClusterLayer,} from "./map-markers"export { MapControls } from "./map-controls"export { MapPopup, MapRoute, MapArc, MapGeoJSON,} from "./map-overlays"Before and after ownership
The useful before/after is about ownership, not component appearance:
The implication is important. apps/web still depends on @workspace/ui, but that dependency is for map infrastructure. It does not make packages/ui the Davao Transit design system. Conversely, the fact that product components live in apps/web does not make them a finished design system. They remain application code and provisional UI until a durable shared contract exists.
What Spine and the current application are
Spine is an external design-system direction under active development. The current repository has no source import, package dependency, or completed migration that would justify saying Davao Transit already uses Spine. The honest relationship is a future integration boundary, not a current runtime dependency.
This also explains why the current UI should not be documented as permanent design-system API. The application has reusable product primitives, and the map package has reusable geographic infrastructure. Those facts are enough to assign ownership. They are not enough to freeze names, tokens, or composition as a stable cross-project contract.
What changed, and what remains open
The correction removed an ambiguity that had practical consequences: a contributor looking only at packages/ui could not tell whether a new button belonged there, whether it needed product tokens, or whether it would pull application concerns into map infrastructure. The export boundary and the source layout now answer that question more directly.
The remaining uncertainty is intentional. The repository does not establish when every product primitive will move to Spine, or whether every current apps/web/src/ui component will survive that migration. Future work should record the import boundary and the ownership decision it needs. It should not describe a provisional component as a stable design-system contract.
Before/after screenshots are unavailable for this incident. The verified before/after evidence is the export diff and the current source layout. A dependency or ownership diagram is useful here because it answers a boundary question; visual component screenshots would answer a different one.