A File the Kit Could Not Own
By November the kit delivered shared text in two shapes. A whole file, vendored with a birth certificate on its first line, for Python and TypeScript. A local package, for the layered Swift half. Both shapes assume the same thing: the file belongs to the kit, and the consumer's job is to hold an exact copy of it.
Then a rule set turned up that had to be identical in every repository and lived in a file no repository could give away. The family's monitoring app held eighteen warnings open about uncommitted paths, seventeen of them on one compute Mac, and not one of them was work at risk. They were Python bytecode, packaging residue, files a coding assistant writes into a project folder for one machine's sessions, and editor state. On the workbench Macs those paths were hidden by a per-user global ignore file. The compute Mac and a lab account had no such file, and the code fan-out carries a checkout's untracked files along with it, so the same checkouts read as dirty there and clean everywhere else. A checkout has to read the same on every Mac, and a per-user file cannot promise that.
The obvious repair is to vendor .gitignore like any other shared file. It fails at once, because half of every .gitignore is that repository's own. One repository tracks its built frontend on purpose, so a family rule ignoring build output would hide files it ships. Two Swift apps keep a source folder named Target, and on a case-insensitive disk a rule for target/ matches it. A whole-file copy would delete those choices; leaving every repository to paste the shared rules into its own file is the triplication this quest started with.
Own the Span, and Nothing Else
So the deployer learned a third shape, the managed block. A manifest entry names a block, and the kit owns exactly the lines from # >>> <name> to # <<< <name> inside a file the consumer owns:
- Deploy replaces the span where it stands, or appends it once when the file has none. Every line outside the markers is kept byte for byte.
- Check compares the span alone and reports
DRIFT, orMISSINGwhen the file has no block. A rule the repository adds outside the markers is never drift. - Broken markers are refused. If the file does not hold exactly one begin marker followed by one end marker, the deployer exits with an error and leaves the file alone. Replacing a guessed span would delete the repository's own rules, which is the one thing this shape exists to avoid.
- There is no header line. The source is the block whole, markers included, and the begin marker itself names the kit source. Line 1 of the file belongs to the consumer — unless the file was empty, the block is appended below the repository's own lines — so the certificate travels inside the span it describes.
A repository that needs an exception writes it below the end marker. In an ignore file a later pattern wins over an earlier one, so the repository gets the last word without ever editing the kit's span. The order of the file does the work a fork would otherwise do.
What Goes Inside, and What Stays Out
Only names that are junk in every stack go in the block: bytecode and tool caches, packaging residue, dependency trees, operating-system litter, one Mac's editor state. A name some stack tracks on purpose — build output, a release folder — stays in that repository's own section, because the block's whole claim is that it is right for everyone.
The block also does one thing in the other direction. It un-ignores the coding assistant's project settings file, because that file carries hooks and is part of the repository's contract, while it ignores what one Mac's sessions wrote beside it: permission grants, preview-server entries, scratch checkouts. With that, status reads the same whether or not a machine also ignores the folder globally. The kit itself took the block the same evening and, for the first time, committed its own project settings — a file the global ignore had been hiding from its own history.
The Check Found a Lie on Day One
For an ignore file, a byte comparison of the span is not the whole question. A rule that matches a tracked file does nothing for that file — git keeps tracking it — and it silently drops the next new file created beside it. So the check also asks git which tracked files the block would call junk, and reports each one as TRACKED BUT IGNORED. Either the path really is junk and should be untracked, or the rule is wrong for the family and should leave the block.
It found one on the first run. A repository had committed a per-machine preview-server entry that pointed at a different repository's development server. Nobody would have looked for that, and no byte comparison could have seen it: the span was identical, and the lie was in what the span meant for that tree.