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

Facts Belong to Their Owner

~14 min · ownership, configuration, boundaries, drift

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

The Question the Membership Test Never Asked

The membership test asks whether a module needs to know what an app is about. A list of model names passes it easily: the list knows nothing about journeys, journals or quests. So does a list of image sizes, a timeout, a port number in an install script. None of them branches on an app's name. All of them went into the kit at one time or another, and in September and October every one of them came back out.

They came out because of a second question: is this a fact some other system owns? The model menu belongs to the assistant's settings, which decide which models each brain offers. Image sizes belong to the image engine, which knows what each model can render. A port belongs to the family's registry of members. A copy of any of those in the kit is not plumbing. It is a second owner, and two owners of one fact is the vocabulary bug from track 1 in a new place.

Six Facts Handed Back

  • Model menus. Launching a new model used to mean editing the assistant's lists and the kit's hand-kept copy, then syncing that copy to ten consumers. The copy had one reader, and that reader could not build a menu without the owner anyway. It was deleted. The owner now publishes each brain's model options alongside its configuration, and a model launch is an edit to the owner and a restart of the owner — no kit edit, no consumer sync.
  • Reviewer routes. Which tool reaches which brain for a review, with which arguments, moved to the system that owns multi-brain calls. The kit keeps a client that fetches that catalog and runs a route on the calling machine. There is no fallback table: an unreachable owner fails the round and says where it looked.
  • Image sizes and aspects. The kit's proxy, its web client and its Swift client each kept a list of sizes. All three were dropped; the image engine's catalog says, per model, which sizes and aspects exist, and the pickers show what the selected model offers.
  • Reference and count ceilings. A shared ten-image ceiling on reference images, and default caps on how many images a capture could carry, were removed. The model owns its reference limit; the provider's documented limits decide what an inline batch can hold.
  • Hidden caps on a turn. A five-minute ceiling on a whole assistant turn cut every turn past five minutes on four apps and surfaced as a network fault. An eight-megabyte budget could end a long streamed turn. A one-turn limit refused a model's own second pass at structured output. Length caps on command proposals rejected valid, wordy answers as malformed. All were dropped; stopping a turn is the user's kill switch, not a number in the kit.
  • Ports, hosts and URLs. The install and network scripts used to get ports, hosts and repository paths stamped into them as per-repository template variables. Now no template variable may carry any of those — a test refuses one — and the scripts ask the family registry at run time and find their own repository from their own location.

No Fallback Copy

Each retirement met the same temptation: keep the old list as a fallback, in case the owner is unreachable. The answer was the same every time. A fallback list is a second owner that only speaks when the first is silent, and it speaks with yesterday's facts. For the model menu, the reader could not build a menu without the owner's other data anyway, so a fallback could never have been used. For the reviewer routes, an unreachable owner is an operating-state error that should be seen, not quietly bridged with a table that drifts. The kit's own guidance now says it outright: do not re-add a list here, not even as a fallback.

A shared layer should hold no fact another system owns. Ask the owner at run time, and fail honestly when it does not answer. The membership test keeps domain knowledge out; this keeps other systems' facts out. Every list, limit and address the kit carries for someone else is a value that will be right on the day it was copied and wrong on the day the owner changes it.

What Giving Back Costs

Handing a fact back makes a coupling visible that a copy used to hide. The kit's review client is tested against a snapshot of the routing owner's catalog, and the routing owner builds part of that catalog from the kit's own brain vocabulary. When the kit added four spellings to its vocabulary, the routing owner's test went red for sixteen hours while every kit test stayed green. The fix was not to copy the catalog back. It was a kit test that holds the vocabulary and the snapshot together, and a documented two-pass order: change the vocabulary and deploy, then refresh the snapshot from the owner and deploy again.

Code

Before and after: a menu the kit kept, and a menu the owner publishes·python
# BEFORE - a mirror the kit kept by hand. Every model launch was an
# owner edit PLUS a kit edit PLUS a sync to ten consumers.
MODEL_OPTIONS = {
    "claude": ["model-a", "model-b"],
    "codex":  ["model-c"],
}

def vessel_menu(owner):
    config = owner.utility_config()          # raises if the owner is down
    return {brain: MODEL_OPTIONS.get(brain, []) for brain in config.brains}


# AFTER - the owner publishes; the kit renders what it is given.
def vessel_menu(owner):
    """No kit-side list, not even as a fallback: the menu cannot be
    built without the owner, so a fallback could never be used, and
    a copy would only ever be yesterday's answer."""
    config = owner.utility_config()          # OwnerUnavailable -> say so
    menu = {}
    for row in config.rows:
        options = row.get("model_options") or []
        pin = row.get("pin")
        menu[row["brain"]] = options or ([pin] if pin else [])
    return menu


# The same rule for topology: no template variable may carry a port,
# host, URL or repository path. A script asks the registry at run time
# and finds its own repository from where it lives:
#
#   REPO="${0:A:h:h}"                     # this script's own repo
#   eval "$(topology-helper <member>)"    # local and private-network URLs
#
# and a test fails any manifest variable that looks like topology.

External links

Exercise

Search one shared library you maintain for literal lists, limits, timeouts and addresses. For each, name the system that actually owns the fact, and check whether that system can already publish it. Retire one copy: make the library ask the owner, and make it fail with a clear message when the owner is unavailable instead of falling back to the old list.
Hint
The easiest candidates are the ones you edited the last time another system released something. If changing the owner required a change here too, the fact was never yours.

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 in — Please sign in to comment.

No comments yet — be the first.