Skip to content
C.W.K.
Stream
Lesson 03 of 04 · published

The Map Has No Version Coherence

~14 min · swift, vendoring, architecture, implementation

Level 0Loose Parts
0 XP0/41 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete

What a File-to-File Map Can See

The copy-deploy mechanism is a map: one source file, one destination file, per consumer that opted in. It is exact about bodies. It is silent about relationships. If file A imports file B, the map will happily deliver Tuesday's A and last month's B to the same consumer, because each row compared cleanly against its own source.

For a leaf, that silence is correct. A generated vocabulary binding has no kit-internal imports. A pin helper that talks to a system keychain and returns a result has no kit-internal imports. The eight copies of a launcher's main file can even carry three different provenance stamps and still be harmless, as long as the bodies match — the stamp is not the body, and the files do not form a graph.

Layered infrastructure is a graph. A fence that depends on an identity type, an engine that depends on both, a store that depends on a document type that depends on a decoder helper: these are not leaves. Deliver them as leaves and the first time one file moves without the other, the failure is a compile error in one consumer, on one build, with no row in the map reporting drift. The map compared the right bytes. It compared the wrong unit.

The Compiler Is the Unit You Actually Needed

A package is one compilation. Types stay coherent because they are compiled together, from one tree, at one moment. That is a property no amount of discipline on top of a file map can reconstruct — you would be rebuilding a module system by hand, in a script whose entire job is to not know what the files mean.

So layered Swift moved. The leaves stayed. The generated catalog stayed generated, because its authority is the data file, not any Swift source; turning it into a package product would hide the copies from the guard that exists to catch a hand-written fourth table. The rule for new shared Swift is now: if it sits on a kit-internal edge — it imports another shared file, or another shared file imports it — it goes in the package. A graph root and a graph leaf travel together. If it has no such edge, the file map is still the smaller, better mechanism.

Pick the mechanism that can see the unit you actually share. Sharing a body is a file problem. Sharing a graph is a compilation problem. Using a file tool on a graph is how you get a green check and a red build, in two different repositories, attributed to two different people, about a divergence neither map row can name.

Do Not Migrate the Leaves as Housekeeping

The leftover Swift leaves are not unfinished business. They are the files for which the file map is still the right answer. Moving one into the package "to clean up" would pay a conversion cost for no coherence gain, and it would blur the rule the next author needs: graph or leaf, not Swift or not.

Migrate a leaf only when a change puts it on a kit-internal edge — it starts importing another shared file, or another shared file starts importing it. A second consumer, or two copies wanting a shared test, is the copy-mechanism's own trigger, not a reason to put a leaf in the package. Until an edge appears, the package and the map sit beside each other, and the next lesson is how they are not allowed to reach into each other.

Code

Same family, two units, the map can only see one·text
FILE MAP (one row per source file)
  kit/swift/PinHelper.swift     -> consumer A, B, C
  kit/data/brains.json
      rendered -> consumer A..N  (generated; authority is the json)

  What a row can say:   body matches, or it does not.
  What a row cannot say: Tuesday's Fence + last month's Identity
                         is a pair that will not compile.

PACKAGE (one compilation, schematic — not a file listing)
  Core/
    Identity.swift
    Fence.swift           <- Fence imports Identity
  Web/
    WebView.swift         <- WebView imports Fence
                             Core does not import Web

  What the compiler says: these files are one unit. Tuesday's fence
  cannot see March's identity, because they are not two deliveries.
  They are one tree.

THE MISTAKE THE MAP WOULD MAKE IF YOU FORCED THE GRAPH INTO IT
  deploy Fence.swift        (row green)
  forget Identity.swift     (row green — nobody asked)
  consumer A compiles       (red, in a repository the map does not see)

External links

Exercise

Inventory the shared files in one language in your system. Mark each as leaf (no kit-internal edge — it neither imports another shared file nor is imported by one) or graph (it sits on such an edge in either direction). For every graph mark, write whether your current delivery mechanism can see that edge. If it cannot, you have a silent version-coherence hole — a green check that cannot name the pair.
Hint
Search for imports whose target lives in the same shared directory, and for files that those imports point at. A graph root with no outgoing imports is still on the graph. Cross-app imports do not count; those are the consumer's problem. Same-directory edges are what the map is blind to.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.