Skip to content
C.W.K.
Stream
← C.W.K. Quests
🔩

Sibling Kit Quest

Updated: 2026-10-12

Three apps had the same plumbing by sundown — the repo that gave it one owner, refused a published package, and later split delivery by language

Two apps were seeded from a third one afternoon, by two different hands. By evening the shared layer existed three times: a byte-identical client library, the same image fitter ported twice in two different ways, three different record schemas for the same act, three drifting settings stores — and one real bug that broke a feature in every app at once, because two halves of one system had quietly disagreed about a name. This quest is about what got built in response, and about the answer it chose, which is the one no architecture blog recommends: not a package, not a monorepo, but vendored copies with a check that has teeth.

9 tracks · 48 lessons · ~10.35h · difficulty: intermediate-to-advanced

Level 0Loose Parts
0 XP0/48 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
Duplication is the one problem everybody already agrees about, which is exactly why it survives. The agreement is abstract — of course you should not have the same code three times — while every individual copy is concrete, cheap, and obviously the fastest way to ship the thing in front of you. You will start where this repo started: with a measurement. Two siblings seeded from one parent on a single day, and an inventory taken hours later showing precisely which layers had already triplicated, plus one cross-app bug that no repository's tests were looking for, because it lived between two halves nobody owned. That bug is the real argument, because it demonstrates the cost that maintenance-overhead hand-waving never quite lands: a fix has three homes, and a divergence has none. Then the decision: the apps stay separate, because their domains genuinely differ, and the shared layer gets exactly one owner. From there the quest walks the design that follows, and every step of it is a choice you could have made differently. Why the distribution model is copies rather than a published package, and why that answer is right here and would be wrong at a company. How a copy carries a birth certificate, and why the certificate must sit outside the bytes you compare. How a drift check earns teeth by running from each consumer's own test suite — and how a rule stated as a file path silently exempted the one repository that could not host that file, and why a check must also know where it stands — which machine, which checkout, which files git keeps. Then what the overdue revisit actually did: it did not migrate. It split the model by language — copies stayed where the original reasoning still held, a local path package took the layered half — because the compiler, not the consumer count, was the fact the first record had never named; and what a path package charges instead of a version. Then the seam work: injecting a column name so one schema builder serves apps that disagree about what a row is about, turning an entire feature off with a parameter rather than a fork, and the discipline of no queue module importing another, including how the written list of exceptions drifted while the manifest kept every edge whole. Then the line the kit never crosses, where the same instinct that removes duplication starts pulling domain logic in behind it, the two canonicalizations that run in opposite directions on purpose, the ruling that gave code, execution and shared state three different owners, and the facts the kit handed back to the systems that own them. Then how a duplicate actually dies: promote at the third copy, refuse to admit a second version of the same thing into the repo that exists to remove duplication, count adopters by sweeping the filesystem rather than by trusting a handoff note, write down the non-adoptions so they are never re-litigated, and retire eight copies of one release program into a single program with per-app configs. Then the invoice — what each conversion really cost, including a permission attribute whose silent loss would have removed a feature, an optional slot that broke nine consumers because it was only ever tested in the two that use it, and a move of execution priced only by real runs read back from the consuming apps. It closes on the rules that are not about code at all: policy decided once instead of per-app, a migration flag with a stated end, a dead end recorded so nobody re-walks it, and the moment four independent robot icons appeared across one family because nobody owned what a face should look like. Conceptual open-sourcing: the architecture is the deliverable, not a repository you clone.

Tracks

  1. 01🌆Three Copies by Sundown

    0/5 lessons

    The measurement that bought a repository

    Nobody argues for duplicated code, which is why arguing about it never fixes anything. This track starts with an inventory instead: two apps seeded from a third in one afternoon, and a list taken hours later of exactly which layers already existed three times. Then the part that turns a tidiness complaint into an architecture decision — a bug no existing test in any repository was looking for, because it lived in the disagreement between two halves that nobody owned — and the test that catches it, once written, fits inside a single app. The track closes on the ruling that followed (the apps stay separate; the shared layer gets one owner), the single question that decides which side of that line a module falls on, and the later measurement that flipped one written example without touching the question.

    Lesson list (5)Quiz · 5 questions→
  2. 02📦Vendor, Don't Package

    0/4 lessons

    The distribution model, and why the obvious answer was refused

    Once a shared layer has an owner, it needs a way to reach its consumers, and the industry has one answer: publish a package and pin a version. This track walks through why that answer was examined and declined for this particular family — private repositories that ran as loopback siblings on one machine when the decision was written, and that now keep one family layout on every Mac in the fleet — and what was chosen instead: copies, deployed by a script, each carrying a provenance header naming its source and the commit it came from. It covers what the copies buy (every repository still builds from its own checkout, every update is visible in the consumer's own history), what they cost, and the discipline that keeps this from being an excuse: the decision was recorded together with the conditions under which it should be reversed. The next track is what happened when those conditions fired.

    The sibling kit's manifest open in an editor: a comment defining every entry as a kit file mapped to its per-repo vendored target, with paths relative to the kit root and to each consumer root and a note that a repo left out of a file's targets simply never receives it — and under it the consumers block, the kit itself first and then sibling after sibling, each pointing at a plain relative directory beside it.
    No registry and no package index — the whole distribution model is one file naming who gets what.
    Lesson list (4)Quiz · 4 questions→
  3. 03⚖️Two Mechanisms

    0/5 lessons

    The revisit that split the model by language

    The reversal condition fired. Consumer count had passed the written trigger by a wide margin, and the overdue revisit did not migrate everything to a package. It split. Python and TypeScript stayed vendored copies, because nothing about those languages had changed the original reasoning. Layered Swift became a local path package, because the compiler — not the count — was the thing vendored files could not express. This track walks the split, the discipline that keeps it from decaying into a new identity — we package now — and the running cost a path package charges instead of a version: every public change arrives at every consumer's next build.

    The sibling kit's manifest open in an editor: a comment that every entry is a kit file mapped to a per-repo vendored target, and under it the consumers block listing sibling directories. The picture is the copy map — the same image as the previous track. The second mechanism this track teaches is not in the picture.
    The picture is still the copy map. The compiler's path package is the other half of this track, not a second image.
    Lesson list (5)Quiz · 5 questions→
  4. 04🦷A Check With Teeth

    0/5 lessons

    What makes a copy stay a copy

    Vendored copies without enforcement are exactly the situation the shared repository was created to end, so the check is not the optional half of this model — it is the half that makes the other half defensible. This track builds it: strip the volatile provenance line, substitute per-repository template variables before comparing rather than after, refuse to deploy a placeholder that nobody supplied a value for, and — the part that turns a script into a rule — run the whole thing from each consumer's own test suite, so a hand-edited copy fails that repository's tests until the edit is reverted or made upstream. It then reaches the failure that taught the rule's real shape: a rule stated as a file path silently exempted the one consumer that could not host that file. And it ends where the check stands — which machine, which checkout, which files git keeps, which commit a header names — because four later greens were each correct about the wrong tree.

    Lesson list (5)Quiz · 5 questions→
  5. 05🔧Parameterize, Never Fork

    0/6 lessons

    How one implementation serves apps that disagree

    Sharing code between applications that are genuinely different requires a technique, not just a decision. This track is the seam catalog: the shim, where each app binds shared machinery to its own constants in a handful of lines it owns; the injected column name, which lets one schema builder serve workshops that disagree about what a row is even about; the parameter that turns an entire feature off for an app that deliberately does not have it; the discipline of no queue module importing another, with its first recorded exception and what that exception cost; how the written list of exceptions still said one while the code grew four edges — five today, one of them still unrecorded — and the manifest rule that kept every edge shipping whole anyway; and the two shapes of extension point — a value you pass in, and a slot the app fills with whatever it wants — including the case where a slot absorbed an entire interactive surface without the shared component changing at all.

    Lesson list (6)Quiz · 6 questions→
  6. 06🚧The Line the Kit Never Crosses

    0/6 lessons

    Where the instinct that removes duplication starts doing damage

    A repository that holds shared code exerts a constant pull. Every time two apps need something similar the cheapest move is to put it in the shared place, and each individual instance of that is defensible — which is exactly how a plumbing layer becomes a framework nobody can leave. This track walks the boundary from both sides: the mirror rule that keeps domain code out, the two name canonicalizations that run in opposite directions on purpose and must never be merged, one data file rendered into three language bindings so that no vocabulary is ever hand-mirrored, and the reason a shared client is deliberately thin — because the sequence it would otherwise reimplement lives at its owner. Then the other half of sharing, which is not code at all: the written wire contracts that let a thin client stay thin. It closes on two later boundaries — code, execution and shared state given three different owners, with a service allowed only for state that must be singular, and the facts the kit handed back to the systems that own them.

    Lesson list (6)Quiz · 6 questions→
  7. 07⚰️How a Duplicate Dies

    0/6 lessons

    Promotion, merging, and counting by sweeping

    Extraction is not a single event, and the interesting part is not the first one. This track is about the ongoing practice: when a pattern has earned promotion (usually the third copy, with a named exception for the case where waiting is more expensive than moving early), what to do when a parallel convention has grown to the point where promoting it would put two versions of the same thing inside the repository that exists to remove duplication, how to count adopters when a handoff note and the filesystem disagree, why the things you deliberately decided NOT to unify have to be written down with their reasons, and why a ledger of who uses what is a different document from a manifest of what is deployed where — including the day that ledger silently lied because a column was added and the rows were not. It ends on a different kind of duplicate: eight copies of one release program, each missing a different guard, retired into one program with per-app facts in a config and differences in named hooks.

    Lesson list (6)Quiz · 6 questions→
  8. 08🧾The Price of Converging

    0/6 lessons

    What each adoption actually cost, measured rather than assumed

    Consolidation is usually argued in the abstract and paid for concretely, one application at a time. This track is the invoice. It covers converting cheapest-first and writing down what the first one cost so the rest are estimates instead of hopes; the app that had to delete three settings controls while the identical question cost the next three apps nothing; the permission attribute whose silent removal would have taken a feature with it; the optional slot that broke nine consumers because it was only ever verified in the two that use it; the deploy-order rule for a family that is not versioned APIs but siblings deployed together — loopback siblings on one machine when the rule was written, one family layout on every fleet Mac today — where a half-deployed window manufactures false confidence; and the most expensive conversion of all, a move of execution whose invoice arrived from the consuming apps' own run journals rather than from any test.

    Lesson list (6)Quiz · 6 questions→
  9. 09👤The Rules That Are About People

    0/5 lessons

    Policy, defaults, and the things a check cannot hold

    The last track is about the parts of a shared layer that are not code problems. Deciding a policy once, with the owner, instead of letting each app answer it differently and calling the difference architecture. Declaring a migration flag with a stated end and a kept count of who is left, so it does not quietly become a permanent choice — and the measurement that showed the count is the half that decays. Recording a dead end — an approach that satisfies every measurement and still reads wrong to the person using it — so nobody re-walks it. The day four independent robot icons appeared across one family because nobody owned what a face should look like, and the fix that was a default rather than a rule. And finally what a shared-plumbing repository actually buys, what it costs, and the honest test for whether you need one at all.

    Lesson list (5)Quiz · 5 questions→
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign in — Please sign in to comment.

No comments yet — be the first.