Documentation Index
Fetch the complete documentation index at: https://docs.rkat.ai/llms.txt
Use this file to discover all available pages before exploring further.
Meerkat Dogma Commentary
Status: Draft companion commentary Primary doctrine:docs/architecture/meerkat-dogma.md
Purpose
The dogma states the law. This commentary explains how to apply it without turning the law into theater. The commentary is not softer doctrine. It is practical doctrine: examples, repair shapes, review questions, and guidance for resolving tension between rules. If the primary dogma says no, this document does not make it yes. It explains how to redesign the work until the answer can become yes.How To Read This Book
Read every chapter through the same question:Where does the semantic fact live?Most Meerkat architecture failures are variations on one sin: a fact has an official owner and an unofficial owner. The unofficial owner is usually a helper, surface, cache, provider adapter, SDK parser, recovery path, or compatibility field introduced for convenience. The unofficial owner is almost always easier to write. That is why it is dangerous. This book uses these terms consistently:
- Authority: the named owner of semantic truth.
- Shell: code that performs mechanics around an authority.
- Projection: a rebuildable, read-only view of authority-owned truth.
- Mirror: a duplicate compatibility shape. Mirrors are temporary debt and require Highest Dogma Authority approval plus expiry.
- Surface: a transport, UX, SDK, host, or product skin over an authority.
- Seam: a typed boundary where ownership, policy, effects, or evidence pass between authorities or between authority and shell.
Resolving Tension Between Rules
Dogma rules do not form a priority list where lower rules can be sacrificed. When two rules appear to pull in different directions, the design is missing a seam, owner, or type. Use this order:- Name the semantic fact.
- Name the current owner claimed by the design.
- Name every other path that can create, alter, recover, infer, or surface that fact.
- Decide which path is the authority. Delete, lower, or project the rest.
- If multiple rules still pull, add a typed seam that preserves both truths instead of collapsing them.
- If compatibility is demanded, require Highest Dogma Authority approval, expiry, drift tests, and proof that compatibility cannot affect behavior.
- If the system cannot explain failure, staleness, or recovery, fail closed.
| Tension | Wrong Resolution | Correct Resolution |
|---|---|---|
| UX wants a friendly shortcut; authority wants a typed handle | Let the surface synthesize the handle | Let the surface accept friendly syntax, then resolve through the canonical owner |
| Provider has a native concept; runtime wants provider agnosticism | Branch on provider strings in shared runtime | Add a typed provider-extension seam or keep the concept inside the provider crate |
| Read performance wants denormalization; authority wants one source of truth | Let the index become fallback truth | Define the index as a projection with source, rebuild trigger, staleness rule, and non-authority boundary |
| Old clients need a field; dogma forbids mirrors | Keep the legacy field forever | Add a temporary compatibility mirror with approval, expiry, drift test, and no behavior influence |
| Optional feature wants shared discovery | Put feature skills, hooks, routes, and schemas in a global package | Keep assets in the owning feature crate/package; let globals mechanically discover declarations |
| A task failed after emitting partial evidence; caller expects success | Return success and log the failure | Model or surface the partial failure truth through the canonical terminal path |
| A shell can observe something the machine cannot | Let the shell update semantic state | Convert the observation into a typed input or declare the machine incomplete |
Chapter 1: Authority Is Singular
Thesis
A Meerkat fact has one throne. Every semantically meaningful fact must have exactly one canonical owner. Not one preferred owner and several helpful replicas. Not one runtime owner and a surface override. Not one machine truth and one recovery truth. One owner. This rule is first because every other rule depends on it. Generated machines cannot own canonical change if helpers also own transition legality. Surfaces cannot be thin if they reconstruct lifecycle. Provider seams cannot hold if shared runtime branches on provider folklore. Stores cannot be mechanical if recovery metadata becomes terminality truth. The question is not where the fact is convenient to compute. The question is: who has the right to say what is true? If that answer is unclear, the design must fail closed.What The Rule Forbids
Rule 1 forbids shared authority over meaning. It forbids helper-local lifecycle truth: a runtime task, waiter, cache, or loop deciding that a session is running, cancelled, failed, detached, completed, or recoverable when the owning machine has not said so. It forbids surface authority: CLI, REST, RPC, MCP, SDKs, WASM bindings, browser hosts, or examples inventing session status, defaults, result classes, admission rules, auth behavior, provider selection, or terminal outcomes. It forbids store authority drift: event stores, projectors, snapshots, indexes, receipts, and recovery paths inferring canonical state from stale projection rows, convenience summaries, or legacy metadata. It forbids provider authority leaks: provider mechanics deciding shared runtime semantics through native field names, stop reasons, error strings, stream chunk shapes, or request conventions. It forbids policy split-brain: profiles, catalogs, provider adapters, CLI flags, SDK defaults, auth helpers, and runtime builders each deciding pieces of model capability, auth freshness, trust, tool permission, retry behavior, or defaults. It forbids mob ambiguity: supervisors, rosters, bridges, flows, peer transports, and message routers each maintaining their own truth about membership, delegation, handoff, peer identity, task ownership, or barrier completion. It forbids tool ambiguity: tool dispatch, builtin tools, skills, hooks, memory, and policy checks each deciding admission or capability without lowering into one typed owner. Most of all, it forbids “the same fact, but optimized over here.” Optimization may create projections. It may not create a second sovereign.Violation Examples
Provider Stream As Terminal Authority
A runtime loop marks a run completed because the provider stream ended cleanly, while the machine still has pending tool operations. The stream observed evidence. It did not own terminality. Correct shape: the provider path lowers stream completion into typed evidence. The machine or terminal handoff protocol decides whether the run completed, failed, remained pending, or needs cleanup.SessionService As Parallel Lifecycle
SessionService keeps an internal status enum that can disagree with
MeerkatMachine.
The service may host, persist, and route sessions. It must not become a
parallel lifecycle authority.
Correct shape: the service projects machine-owned lifecycle or submits typed
inputs to the machine. It does not decide lifecycle phase itself.
Projector As Recovery Authority
A projector writeslast_status = "failed" and recovery later trusts that
field to decide whether a session is terminal.
The projector created a read model. Recovery turned it into authority.
Correct shape: recovery uses declared machine snapshots, transition journals,
events, or migrators. The projector remains rebuildable and non-authoritative.
SDK As Default Owner
An SDK sees a missing model field and silently chooses a default provider. A user-facing convenience fabricated model policy. Correct shape: defaults come from the owning profile, catalog, facade, realm config, or explicit public contract. SDKs expose absence, mismatch, or server truth. They do not invent it.Mob Transport As Roster Owner
A mob bridge considers a worker detached because its transport disconnected, while the roster still considers the worker assigned. Transport liveness is evidence. Assignment truth belongs to the roster, composition, or handoff protocol. Correct shape: the transport submits typed disconnect evidence. The mob authority decides whether the member is detached, reconnecting, retired, failed, or still assigned.Correct Solution Shapes
Start by naming the fact. Do not name the module first. Examples:- session lifecycle phase
- tool admission
- provider capability
- mob worker membership
- realm trust
- terminal result class
- async operation truth
- public session identity
- input adapter
- effect executor
- projection
Review Questions
- What exact fact is being asserted?
- Who is allowed to change it?
- Can two modules answer this question differently?
- Is this a machine fact, profile fact, catalog fact, store-contract fact, auth fact, mob-composition fact, or public-contract fact?
- Is any helper, cache, waiter, task, callback, surface, SDK, or test fixture maintaining a local copy that can affect behavior?
- Does recovery rebuild authority from canonical events, snapshots, or migrators, or from projection folklore?
- Does a provider-native field leak into shared runtime meaning?
- Does a surface lower into the shared runtime path, or reconstruct semantics because that was easier?
- Can stale data change admission, defaults, terminality, identity, trust, routing, or policy?
- If the owner disappeared, would another component quietly pretend to know the truth?
Tension Notes
Rule 1 and Rule 2: naming the owner is not enough. If the owner is a machine, canonical change must go through generated machine authority. Handwritten reducers are not implementation detail. They are rival authority. Rule 1 and Rule 3: stores and projections can look authoritative because they are durable or queryable. Durability is not sovereignty. A store owns persistence guarantees; the machine owns meaning. Rule 1 and Rule 4: ownership must be typed. A convention, string prefix, optional field, path shape, or provider-native name is not an owner. Rule 1 and Rule 5: optional features own their own assets. A global bundle that hosts feature truth is a second owner. Rule 1 and Rule 6: surfaces may be friendly, but they must not become clever. User syntax can differ from internal machinery only if lowering returns to the canonical owner. Rule 1 and Rule 7: provider-specific crates may own provider-native translation. They do not own Meerkat semantics. Shared runtime receives typed facts, not provider folklore. Rule 1 and Rule 8: terminality is where split authority becomes most dangerous. A timeout, dropped stream, cancelled task, provider error, or failed tool must lower into one terminal authority. Rule 1 and Rule 9: generated artifacts must constrain the real authority path. A generated schema that describes one truth while production follows another is documentation theater.Maxims
- One fact, one owner.
- Evidence is not authority.
- A projection that decides behavior is a usurper.
- Convenience defaults are policy in disguise.
- If two paths can disagree, the architecture is already lying.
Chapter 2: Generated Machines Own Canonical Change
Thesis
Canonical machine state changes only through generated machine authority. This rule is the operational form of “machines own semantics.” It is not enough for a machine model to exist, or for production code to vaguely resemble it. If handwritten code can decide the same transition, mutate the same state, or classify the same terminal outcome, the machine is decoration. Generated authority owns the semantic core:- what states exist
- which inputs are valid
- which transitions are legal
- what canonical state mutation occurs
- which semantic effects are emitted
- which terminal class follows from machine truth
What The Rule Forbids
Rule 2 forbids any handwritten path that becomes a second reducer. A reducer is any code that looks at current semantic state plus an event and decides the next semantic state. It does not have to be namedreduce. It may
be a helper, actor method, RPC handler, recovery routine, test harness,
callback, retry loop, status mapper, or provider adapter. If it decides
canonical state, transition legality, terminality, or semantic effects, it is a
reducer.
Forbidden patterns include:
- directly setting canonical machine fields from handwritten code
- matching on lifecycle state and manually advancing to another lifecycle state
- maintaining a shadow transition table in an actor, handler, or helper
- duplicating machine states in local enums, booleans, maps, or status structs
- deciding that a transition is legal because a shell-local condition says so
- emitting semantic effects that the owning transition did not produce
- classifying terminal results through ad hoc branches instead of generated or machine-derived classifiers
- recovering state from projection fields, compatibility metadata, or local cache truth
- making a test pass by forcing machine state instead of driving the machine through legal inputs
If removing the handwritten shell would remove semantic truth, generated authority is incomplete.
Shell Classification And Typed Inputs
The shell is allowed to decide when to call the machine. It may receive raw evidence and classify it into a typed machine input. Legitimate shell classification:- a JSON-RPC request arrives; the handler maps it to a typed runtime command
- a task exits; the owner records raw completion evidence and submits typed feedback
- a provider stream yields a chunk; the adapter maps it to typed observation data
- a timer fires; the scheduler routes a typed timeout input
- a store loads a snapshot; recovery submits declared replay, restore, attach, or migrator inputs
Handoff Protocols
Many semantic transitions do not finish inside one synchronous function call. A machine may authorize work, emit an effect, and depend on an owner to realize that effect asynchronously. That seam is dangerous because the shell is tempted to decide what happened later. A handoff protocol closes the seam. Correct shape:- The machine transition emits an effect.
- The effect declares a handoff protocol when later owner feedback is semantically meaningful.
- The composition names the realizing owner, allowed feedback inputs, correlation fields, and closure policy.
- Handwritten owner code performs the IO or async work.
- Owner feedback returns through generated protocol helpers.
- The generated machine or composition path classifies the result and advances canonical state.
Violation Examples
Direct Lifecycle Mutation
A runtime task exits and handwritten code setsphase = Completed, emits a
success event, and clears waiters.
The shell observed a task fact, then invented lifecycle and terminal truth.
Correct shape: the shell submits typed completion evidence through generated
input or handoff feedback. The generated transition decides whether the session
completed, failed, cancelled, or remains obligated.
Shadow Transition Helper
An actor hasadvance_flow_run() with a handwritten match over Pending,
Running, Waiting, Succeeded, and Failed, while the catalog also defines
flow lifecycle.
The helper is a parallel reducer, even if its branches look reasonable.
Correct shape: convert each meaningful stimulus into generated machine input:
dependency satisfied, branch failed, quorum reached, retry exhausted, or owner
feedback received. Local maps become projections or private mechanics updated
from generated transitions.
String Terminal Classifier
An RPC handler maps internal status strings to public result classes:"done"
becomes success, "stopped" becomes cancelled, "error" becomes failure.
Terminal classification escaped the machine and became surface folklore.
Correct shape: use generated terminal classifiers or machine-derived typed
result classes. The surface may format the result; it must not decide it.
Recovery From Projection Truth
Recovery reads a denormalizedlast_status field from a read model and seeds
canonical state as running, detached, or completed.
A projection became authority.
Correct shape: recover from declared snapshot, journal, replay, or migrator
contracts. For transient runtime facts, observe the live fact and submit typed
attach, detach, or rebind input through generated authority.
Correct Solution Shapes
Add a machine input when the shell is classifying a real semantic event that the machine cannot currently express. Add a handoff protocol when a machine-owned effect crosses into async owner work and later feedback matters. Promote cross-machine truth into a composition when no single machine owns the full semantic fact. Acceptance, execution, consumption, barrier satisfaction, and terminal result alignment often live at composition seams. Convert local state into a projection when it exists for speed, lookup, formatting, or transport. A projection must name source truth, rebuild trigger, staleness policy, and use boundary. Move provider-specific mechanics behind provider seams. Native request and response forms are boundary facts, not shared runtime semantics. Generate the classifier when handwritten code maps machine outcomes to terminal classes. Exhaustiveness matters. Default arms and “unknown means success” are architectural sins. Strengthen tests around the authority path: illegal inputs fail closed, handoff feedback cannot bypass the protocol, and recovery reaches the same truth as live execution.Review Questions
- What canonical fact changes here?
- Which generated machine, composition, or handoff protocol owns that change?
- Is handwritten code mutating canonical state directly?
- Is this function deciding transition legality, or merely routing typed evidence?
- Does any local enum, boolean, map, status field, or cache duplicate machine state?
- Does terminal classification come from generated or machine-derived code?
- If this is async work, where is the handoff protocol and generated feedback helper?
- If the shell classifies raw input, what typed input does it lower into?
- If no typed input exists, why is the model considered complete?
- Could recovery replay this path without hidden shell-local truth?
- Would deleting this handwritten helper delete meaning, or only mechanics?
Tension Notes
Rule 2 and Rule 1: for machine facts, singular authority means generated authority. If there is tension between a convenient helper and the machine, the helper loses. Rule 2 and Rule 3: shell mechanics and projections are allowed only while they remain mechanical. The shell observes and routes; the machine decides. Rule 2 and Rule 4: a generated machine input is only authoritative if it carries typed truth. String classifiers and optional owner context smuggle handwritten semantics back into the path. Rule 2 and Rule 8: terminal classifiers must be generated or machine-derived. Fault evidence may come from shell code, but fault meaning belongs to the machine or protocol. Rule 2 and Rule 9: if the generated machine does not govern the production transition, fix production or fix generation. Do not preserve a hand-authored mirror and call it compatibility.Maxims
- The shell may bring evidence; only the machine may pronounce meaning.
- If no typed input exists, the model is incomplete.
- A handwritten reducer is a second source of truth wearing a helper’s cloak.
- Async work may leave the machine; semantic closure must return through protocol.
- Generated authority is not documentation. It is the law.
Chapter 3: Shells, Stores, and Projections Are Mechanical
Thesis
Shells, stores, and projections are allowed to move truth, preserve truth, and display truth. They are not allowed to create truth. Rule 3 exists because many architectural failures enter through “just a cache”, “just recovery”, “just a read model”, “just local state”, or “just compatibility metadata.” These components feel harmless because they are not the central machine. That is exactly why they are dangerous. They sit near authority, often run during exceptional paths, and can quietly become authority when the real owner is absent, slow, stale, or inconvenient. A mechanical component does not decide what happened. It carries evidence to the owner that can decide.What The Rule Forbids
This rule forbids any shell, store, projection, cache, receipt table, local registry, waiter map, recovery helper, or compatibility field from becoming an undeclared owner of semantic truth. It forbids:- deriving lifecycle phase, terminality, policy, trust, ownership, or recovery outcome from stored or projected convenience fields
- treating stale projection state as permission to continue, terminate, retry, recover, or accept input
- using local fallback state as a substitute for canonical session, runtime, provider, peer, or machine state
- letting read models make behavioral decisions instead of serving queries and presentation
- recovering canonical state from denormalized views, indexes, SDK shadows, compatibility metadata, or provider-shaped artifacts
- allowing shell code to patch up missing authority by inventing defaults, inferred ownership, or synthetic outcomes
- allowing compatibility metadata to outlive its expiry or influence behavior
Violation Examples
Projection Becomes Authority
A session list projection storesstatus = "completed" for fast UI display.
Later, REST checks that projected status to decide whether cancellation is
legal.
The projection may display completion. It may not decide transition legality.
Correct shape: REST sends a typed cancellation input and lets the authority
accept or reject it. The projection remains a read model.
Store Creates Recovery Truth
A recovery path loads the most recent snapshot, notices a terminal-looking event, and marks the run complete without replaying through the declared transition, snapshot, journal, or migrator contract. The store preserved bytes, not meaning. Correct shape: recovery restores authority through the contract that owns recovery semantics, or fails closed.Stale Read Model Changes Behavior
A worker checks an eventually consistentactive_sessions index before
dispatching a tool call. If the session is absent, the worker drops the call as
“session gone.”
Eventual consistency is acceptable for query latency, not semantic disposal.
Correct shape: the worker uses the canonical session/runtime owner to validate
dispatch. The index may help find candidates, but absence from the index cannot
prove semantic absence unless that exact boundary is owned and declared.
Local Fallback Registry Masquerades As Canonical
A surface keeps a local map from request IDs to session handles. When the shared runtime cannot resolve a handle, the surface falls back to its local map and continues. The local map is correlation state. It cannot override canonical handle authority. Correct shape: the local map correlates in-flight requests. If canonical resolution fails, the surface reports failure or re-enters the declared authority path.Compatibility Metadata Drives New Semantics
A legacy event fieldlegacy_terminal = true exists for old clients. New
recovery code reads it to decide whether a run reached terminal state.
Compatibility metadata has crossed into authority.
Correct shape: legacy fields are temporary, read-only compatibility mirrors
with expiry and approval. New behavior reads canonical terminal fact from the
owning machine or event contract.
Correct Solution Shapes
Every projection must declare:- source truth
- rebuild trigger
- staleness policy
- allowed use boundary
Review Questions
- What semantic fact is this shell, store, or projection carrying?
- Who owns that fact before this component sees it?
- Can this component change behavior when local state is stale, missing, or wrong?
- Is recovery restoring machine-owned truth, or reconstructing meaning from residue?
- Is this read model used only for query/presentation, or does it decide transitions, defaults, admission, terminality, or policy?
- What is the projection source truth, rebuild trigger, staleness policy, and allowed use boundary?
- Is local fallback state private mechanics, or can it escape as canonical truth?
- Is compatibility metadata being read by new code to decide behavior?
- If the projection vanished, would the system lose performance and display quality, or semantic correctness?
Tension Notes
Rule 3 and Rule 1: do not ban projections; prevent projections from owning meaning. Rule 3 and Rule 2: stores persist and restore machine-owned truth only through declared machine, snapshot, journal, or migrator contracts. Storage durability is not transition authority. Rule 3 and Rule 5: global feature registries and indexes are projections of feature-owned declarations. They do not own optional capability truth. Rule 3 and Rule 6: surface-local request maps, SDK shadows, browser caches, and CLI state must remain private mechanics. Rule 3 and Rule 8: stale indexes, dropped waiters, missing receipts, and recovery guesses must not become terminal outcomes. Rule 3 and Rule 9: generated or not, an artifact constrains production truth only if it is the authority path. Otherwise it is a projection, and projections must stay in their lane.Maxims
- A projection may answer “what should I show?” It may not answer “what is true?”
- A store preserves authority; it does not become authority.
- Stale data may be visible. It must not be decisive.
- Local fallback state is private plumbing until a named authority owns it.
- Compatibility metadata is not memory. It is debt with an expiry date.
Chapter 4: Truth Is Typed, Identity Is Canonical
Thesis
A semantic fact is not real in Meerkat until it has a type, an owner, and a canonical identity path. Strings, paths, provider fields, JSON shapes, optional values, and naming conventions may carry evidence. They must not carry law. If code needs to distinguish completed from detached, trusted from merely known, reachable from absent, OpenAI from Anthropic, skill A from another skill with the same name, or member identity from runtime incarnation, that distinction belongs in a named type. Folklore scales badly. Once meaning lives in string prefixes, missing fields, provider-native names, or “everyone knows this path means X”, every surface and helper starts carrying a private copy of the architecture. Typed truth is the antidote. Canonical identity is the boundary.What The Rule Forbids
Rule 4 forbids using unowned representation as semantic authority. Forbidden patterns include:- parsing model, provider, realm, peer, skill, session, or operation meaning from string prefixes
- treating enum variant names, display labels, log messages, or error text as machine-readable truth
- letting provider-native request or response fields drive shared runtime behavior
- using path layout, file names, command names, or URL shape as lifecycle or ownership truth
- accepting generic JSON where
kind,type, or an ad hoc field secretly determines behavior - inferring trust, completion, detachment, reachability, or ownership from convention
- using
Option<T>when the real question is which owner supplies the fact - exposing raw infrastructure identifiers as public control handles when the caller needs a domain handle
- treating provenance as decorative audit text instead of typed evidence bound to an owner
Violation Examples
Provider Folklore In Shared Logic
Bad:Public Handles That Are Really Infra IDs
A public API exposes a raw session UUID as if it were enough to express resume or archive behavior. If session meaning is realm-scoped, backend-scoped, tenant-scoped, or authority-scoped, the handle is incomplete. Correct shape:Skill Identity By Name Alone
load_skill("email-extractor") is not canonical if multiple sources can
provide that name.
Correct shape:
Optionality Hiding Ownership Uncertainty
Bad:JSON kind As The Real Contract
Bad:
Correct Solution Shapes
Use newtypes for semantic primitives. If two values must never be confused, they need different types even when both wrapUuid, String, or usize.
Option<T> only when
absence has exactly one harmless meaning. Do not use it for inherit vs disable
vs explicit, known vs unknown, unresolved vs forbidden, or unauthenticated vs
anonymous allowed.
Treat provider-native data as evidence, not shared semantics. Provider-specific
fields may be preserved, audited, and lowered inside provider-owned code. They
must not become shared runtime conditionals.
Review Questions
- What semantic distinction is this code making?
- Is that distinction represented as a type, or inferred from representation?
- Who owns the meaning of this identifier?
- Is the handle complete enough to resolve the owner without ambient context?
- Could two authorities produce the same visible name?
- Could the same raw id mean different things in different realms, generations, providers, or sources?
- Is an
Option<T>hiding inherit, disable, unresolved, unknown, forbidden, or defaulted? - Is provider-native data crossing into shared runtime behavior?
- Is provenance typed enough to support audit, replay, recovery, and drift detection?
- Would a new surface or SDK be forced to copy a convention to behave correctly?
Tension Notes
Rule 4 and Rule 1: types do not create authority by themselves. A typed duplicate of an unowned fact is still a duplicate. Name both the type and the authority. Rule 4 and Rule 2: adapters may classify raw input into typed observations. They may not make canonical state changes because they have a nice enum. Rule 4 and Rule 3: a projection should be typed, but typing does not let it decide behavior. Rule 4 and Rule 5: optional feature names, capability ids, skill ids, hook ids, and route ids must be typed. Global strings are where composability hides collisions. Rule 4 and Rule 6: friendly names are allowed only as projections over canonical handles. UX sugar must resolve through the owner. Rule 4 and Rule 7: provider-native fields must become typed provider-owned facts before shared code sees them. Rule 4 and Rule 8: error strings are especially tempting folklore. Do not parse terminality out of text. Rule 4 and Rule 9: generated contracts must preserve domain types. FlatteningSkillKey into "source/name" or policy enums into nullable strings
reintroduces folklore at the boundary.
Maxims
- If it matters, name it in the type system.
- A string may carry evidence; it must not carry law.
- A public handle must resolve its owner without guessing.
Noneis not a policy.- Provenance that cannot be checked is decoration.
Chapter 5: Composability Is Feature-Owned
Thesis
Meerkat is built from composable capabilities, not from a monolith with a bag of optional decorations. An optional feature owns more than its Rust functions. It owns the feature’s skills, tools, hooks, manifests, routes, schemas, docs fragments, migrations, fixtures, policy extensions, generated artifacts, and public affordances. Those assets are part of the feature’s semantic boundary. If a capability can be enabled by Cargo feature, runtime module, product edition, mobpack, plugin, provider, or host environment, then the capability’s assets must travel with the owning crate or package. Global packages may discover the feature. They may not become the place where the feature secretly lives. This rule exists because Meerkat is meant to be recomposed. A feature that leaves skills in core, schemas in a surface, docs in a global package, and policy in a side registry is not composable. It is scattered.What The Rule Forbids
Rule 5 forbids global-package gravity. It forbids:- optional feature skills placed in a global
meerkat-coreor global skills package - feature-specific hooks, tools, fixtures, routes, or schemas owned by a surface crate because that surface exposed them first
- global manifests hand-authoring feature truth instead of discovering feature-owned declarations
- SDK indexes, MCP catalogs, CLI help, REST route tables, or product manifests becoming the source of truth for optional capability availability
- optional feature docs that describe behavior not shipped, tested, or versioned with the feature
- core crates absorbing feature policy because the feature needs a shared vocabulary
- generated files for an optional feature emitted into a global location with no owner, freshness rule, or feature-gated drift test
- tests and fixtures for optional behavior living outside the owning feature so the feature can be removed while its expectations remain
Violation Examples
Scheduler Skill Hidden In Core
An optional scheduler feature ships its Codex/Claude skill, hook manifest, wire route declarations, fixtures, and policy knobs by adding them to a globalmeerkat-core skills package because global discovery already scans there.
The scheduler has lost composition ownership. Installing core now smuggles in
scheduler semantics, disabling scheduler leaves stale assets behind, and future
features will copy the same global dumping ground.
Correct shape: the scheduler crate/package owns the scheduler skill, hook and
tool declarations, schemas, docs fragments, fixtures, migrations, and policy
extension points. The global skills package or platform registry discovers the
scheduler-owned declaration mechanically when the scheduler feature is present.
Without the scheduler feature, those assets do not exist.
CLI Route Table Owns Mobpack Feature Truth
A CLI command table hand-lists routes and help text for optional mobpack features. The mobpack crate has a different manifest, and the REST surface has a third copy. The optional feature now has three owners: CLI, REST, and mobpack. Correct shape: mobpack owns a typed feature declaration. CLI, REST, MCP, SDKs, and docs consume generated or checked projections from that declaration.SDK Package Ships Disabled Feature Types
The TypeScript SDK exposes scheduler-specific methods and generated types even when the scheduler capability is not present in the runtime build. Calls fail late or silently degrade. The SDK has made an optional capability look universal. Correct shape: SDK capability surfaces are generated from feature-owned declarations and runtime capability negotiation. Absent feature means absent or explicitly unavailable API, not optimistic universal syntax.Provider Feature Assets In Shared Runtime
An optional provider extension contributes prompt templates, native tool schemas, auth policy, fixtures, and docs by editing shared runtime files. The provider extension cannot be removed cleanly, and shared runtime now knows provider-native semantics. Correct shape: provider extension assets live in the provider or feature crate. Shared runtime sees only typed extension seams and mechanically discovered capability declarations.Correct Solution Shapes
Use feature-owned declarations:- capability id and version
- owning crate or package
- exposed skills, tools, hooks, routes, schemas, docs fragments, fixtures, and generated artifacts
- required extension seams and feature flags
- availability conditions
- policy extension points
- drift tests and generation commands
SchedulerCapability, a discovery trait, or a typed route
shape. The scheduler crate owns scheduler behavior, skills, schemas, docs,
fixtures, and policy. Shared vocabulary is the socket, not the appliance.
Tests must follow the same boundary. Feature tests, smoke fixtures, and e2e
expectations that assert feature semantics live with the feature or are
generated from feature-owned declarations. Cross-feature integration tests may
compose feature packages, but they do not become the owner of either feature.
Review Questions
- Is this capability optional by feature flag, package, runtime module, provider, product profile, plugin, or host environment?
- Which crate or package owns the capability?
- Are every skill, hook, tool, route, schema, fixture, migration, doc fragment, generated file, and policy extension owned there?
- Is any global package hosting feature assets instead of projecting them?
- Is any surface declaring feature availability from local tables?
- Can the feature be enabled, disabled, versioned, tested, and removed with its owning package?
- If a global registry exists, what generator or drift test proves it is a projection?
- Does the SDK expose feature-specific APIs only when the feature is present or explicitly negotiated?
- Is shared core defining vocabulary, or has it absorbed feature semantics?
- Would deleting the feature crate leave stale skills, docs, schemas, tests, or policy behind?
Tension Notes
Rule 5 and Rule 1: composability is ownership applied to packages. If a feature’s assets live elsewhere, ownership has split. Rule 5 and Rule 2: generated machine inputs and feature-owned declarations must agree. Do not hand-author a global feature manifest beside generated machine truth. Rule 5 and Rule 3: global registries are projections. They may speed discovery; they may not decide feature availability from stale or local state. Rule 5 and Rule 4: capability ids, feature ids, skill ids, hook ids, and route ids must be typed. Stringly global names create collisions and hidden coupling. Rule 5 and Rule 6: surfaces may expose a composed product shape. They must not move feature ownership into CLI, REST, MCP, SDK, or WASM packages. Rule 5 and Rule 7: provider-specific optional features still belong behind provider or feature seams. Shared runtime receives typed declarations, not native provider assets. Rule 5 and Rule 8: feature-specific faults and terminal outcomes must be owned by the feature’s machine, handoff protocol, or declared contract, not a global dispatcher. Rule 5 and Rule 9: global indexes, generated catalogs, and product manifests must be derived from feature-owned declarations and protected by drift tests.Maxims
- Optional feature assets live with the optional feature.
- Global discovery is allowed; global semantic ownership is not.
- Core owns seams, not every capability that plugs into them.
- If disabling a feature leaves its skill behind, the feature was never properly optional.
- A product bundle composes features; it does not confiscate them.
Chapter 6: Surfaces Are Thin Over The Shared Runtime
Thesis
A Meerkat surface is a translation boundary. It is not a second runtime. CLI, JSON-RPC, REST, MCP, SDKs, WASM, browser hosts, examples, and product binaries may make Meerkat easier to call, read, embed, and ship. They may not decide what Meerkat means. The same session, turn, model, tool, auth, mob, comms, fault, and terminal semantics must survive every surface projection. The surface may speak HTTP, JSON-RPC, MCP tools, CLI flags, Python objects, TypeScript promises, Rust traits, or browser callbacks. Those are dialects. The law beneath them is shared runtime authority or an explicitly declared standalone substrate. If a surface needs behavior that no shared runtime seam can express, add the missing typed seam. Do not implement the behavior locally.What The Rule Forbids
Rule 6 forbids surface-owned semantic authority. It forbids:- surface-local session lifecycle state that competes with
SessionServiceorMeerkatMachine - separate create, resume, interrupt, cancellation, external-event, or commit semantics per surface
- CLI flags, REST handlers, RPC methods, MCP tools, SDK methods, or browser callbacks that infer terminality locally
- SDK defaults that fabricate required facts such as realm, model, auth, runtime mode, persistence, or capability truth
- MCP host tools that bypass typed public control planes and expose raw agent-side dispatchers
- REST or RPC adapters that call directly into agent execution when product path requires runtime admission
- examples that teach direct construction as ordinary public path when correct path is runtime-backed
- duplicated bootstrap, executor, materialization, config, auth, or provider setup when a shared helper exists
- standalone fallback behavior that silently emulates runtime-backed behavior without the runtime owner
- browser/WASM surfaces that market unavailable filesystem, TCP, stdio MCP, shell, or persistent realm behavior as present
--resume, route
POST /sessions/{id}/turns, receive sessions/create, expose meerkat_resume,
or offer session.turn() in an SDK. That classification must lower into typed
shared runtime operations. The surface parser may choose the door. It may not
become the house.
Violation Examples
CLI As Hidden Runtime
rkat resume opens persistence, reconstructs a session, applies its own
resumed phase, and calls agent execution without the runtime-backed binding
path.
Correct shape: CLI syntax lowers into the canonical execution family. Friendly
commands are UX conveniences over shared session/runtime operations.
REST As Direct Execution Loop
POST /sessions/{id}/external-events directly wakes an agent task or drains an
inbox because that is simpler than entering runtime admission.
Correct shape: REST accepts HTTP, validates the request, and queues a typed
runtime-backed external event. It does not invent a second event loop.
SDK As Optimistic Mirror
A Python or TypeScript SDK creates a localSession object, defaults missing
status to completed, hides unknown events, or guesses capabilities from
package version.
Correct shape: SDK objects wrap canonical session identity and generated or
versioned contracts. Unknown events remain unknown, version mismatch is
explicit, and convenience methods project runtime facts.
WASM As Secret Product Emulation
The browser runtime uses in-memory state but presents itself as sharing durable realms, filesystem config, stdio MCP servers, shell tools, or native persistence. Correct shape: WASM/browser mode is explicit: browser-safe substrate, browser-safe providers and tools, in-memory or declared storage, and no hidden native affordances.Correct Solution Shapes
Runtime-backed product surfaces should follow:initialize, capability responses, SDK feature flags,
and generated protocol artifacts must agree.
Review Questions
- Does this surface enter the same runtime-backed path as its peers?
- If it is standalone, is that mode explicit and limited?
- Which shared helper does this bootstrap, executor, request-lowering, or response-projection logic use?
- Is any surface handler deciding lifecycle phase, terminality, retryability, auth truth, model capability, or persistence truth locally?
- Are CLI flags, HTTP routes, RPC methods, MCP tools, SDK methods, and WASM exports only syntax over typed operations?
- Are defaults owned by the correct profile, realm config, request contract, or runtime seam?
- Does cancellation mean the same thing across surfaces where the capability exists?
- Are unknown events, statuses, and version mismatches surfaced honestly?
- Do examples teach the public path, or canonize an escape hatch?
- Would deleting this surface leave runtime semantics intact?
Tension Notes
Rule 6 and Rule 1: a surface may own presentation state, transport state, and user interaction flow. It may not own runtime facts. Rule 6 and Rule 2: a surface may parse raw input and classify protocol operations. Meaningful classification must lower into typed machine input, composition route, or service contract. Rule 6 and Rule 3: surface caches, SDK objects, UI state, stream buffers, and list views are projections. They may improve responsiveness. They may not decide behavior when stale. Rule 6 and Rule 4: friendly names are projections over canonical handles. If a CLI alias, SDK object id, MCP parameter, browser key, or REST path segment becomes authority, type it and resolve it through the owner. Rule 6 and Rule 5: surfaces may expose composed optional capabilities. They must not host feature-owned skills, hooks, routes, schemas, docs, or policy. Rule 6 and Rule 7: surfaces may expose provider selection and provider parameters, but provider meaning belongs behind catalog, profile, provider, and auth seams. Rule 6 and Rule 8: HTTP disconnect, WebSocket close, JSON-RPC cancellation, MCP tool failure, SDK abort, and browser unload must lower into explicit runtime or standalone fault semantics. Rule 6 and Rule 9: generated schemas, SDK types, OpenAPI, RPC catalogs, MCP tools, and docs must describe the production path, not a parallel surface-local interpretation.Maxims
- A surface may translate. It may not decide.
- Friendly syntax is holy only after typed lowering.
- Standalone is a mode, not a fallback.
- Shared behavior belongs in shared helpers.
- If CLI, REST, RPC, MCP, SDK, and WASM disagree, at least one is lying.
Chapter 7: Providers and Policy Stay Behind Their Owning Seams
Thesis
Meerkat is one runtime that can speak through many providers. The provider is a backend coordinate, not a second architecture. Provider-specific mechanics belong behind provider-owned seams. Shared runtime, sessions, tools, memory, mobs, surfaces, SDKs, and public contracts may carry typed provider identity and typed provider-extension payloads, but they must not learn provider folklore. They must not parse native response shapes, infer capabilities from model-name trivia, or decide policy from raw provider strings. Policy is not ambient. Capability truth, defaults, auth freshness, tool availability, provider params, web-search behavior, and model-specific operational defaults must flow from declared owners:ModelProfile, the model
catalog, realm auth bindings, AuthMachine, facade/factory composition, and
typed provider-extension seams.
Switching from Anthropic to OpenAI, Gemini, or a self-hosted alias must not
change Meerkat architecture. It should only change typed facts resolved by the
owning seams.
What The Rule Forbids
Rule 7 forbids provider-specific branches in shared code unless the branch is owned by a typed catalog, profile, or provider seam. Forbidden patterns include:- runtime code that checks
provider == "openai"and changes semantic behavior directly - surface code that parses
gpt-*,claude-*, orgemini-*to infer capabilities - provider-native request or response structs escaping into session history, tool logic, mob orchestration, memory, hooks, SDKs, or public contracts
- provider adapters deciding shared policy such as tool visibility, retry class, auth lifecycle, default timeout, or terminal outcome
- raw
provider_paramsbecoming authority in shared runtime - public APIs that expose provider-native fields as if they were Meerkat concepts
Option<T>policy overrides whereNoneambiguously means inherit, disable, unset, unknown, or use provider default- auth freshness checks in CLI, RPC handlers, SDK defaults, or provider adapters
- resume or model hot-swap paths that keep stale policy from previous model/provider/auth identity
- exact self-hosted aliases being overridden by prefix inference
- hooks rewriting effective provider params after the owning factory/profile seam has composed them
Violation Examples
Prefix Folklore As Capability Truth
Bad:ModelProfile. Unknown provider/model pairs
fail closed or require explicit catalog registration.
Provider Branch In A Surface
Bad:Provider Adapter Owns Policy
A provider crate checks session config, model profile, and runtime settings to decide whether to inject web search. The provider crate has become a policy composer. Correct shape: the facade/factory composes effective provider-tool policy from config,ModelProfile, session metadata, and explicit overrides. The provider
crate receives an already-composed request plan and performs native request
shaping.
Auth Failure Becomes Adapter Authority
A provider adapter sees HTTP 401 and marks a session as requiring reauth. Provider transport error mutated session/auth truth. The adapter usurpedAuthMachine.
Correct shape: the adapter returns typed auth evidence, such as
ProviderAuthError::Unauthorized. The auth lease path routes evidence to the
binding-scoped AuthMachine.
Raw Provider Params In Shared Runtime
Shared runtime readsprovider_params["reasoning_effort"] == "high" to
increase budget.
A provider-native JSON key is driving shared runtime behavior.
Correct shape: provider params are ingress or provider-extension payloads.
Shared runtime may carry them opaquely after validation, but must not interpret
native keys. If a value affects shared behavior, promote it into a typed
Meerkat concept with an owner.
Dynamic Identity With Static Policy
A session starts on Claude, derives tool visibility and web-search defaults, then resumes with an OpenAI model while keeping old derived provider policy. Correct shape: persist user intent and explicit overrides. Recompute derived policy whenever model, provider, auth binding, session, realm, owner, or catalog identity changes.Correct Solution Shapes
Provider crates own native mechanics:- request serialization
- response parsing
- native streaming protocol
- provider retry affordances as evidence
- provider auth challenge interpretation as typed evidence
- provider-specific image/backend request shaping
- provider-native parameter validation at the provider extension seam
AuthMachine owns auth lifecycle. Provider runtimes may consume resolved
leases. Provider adapters may return typed auth evidence. Refresh, expiry,
transient failure, permanent failure, reauth requirement, and release belong to
the binding-scoped auth machine.
Policy composition belongs at seams with full identity context: selected model,
resolved provider, ModelProfile, realm and auth binding, session identity,
explicit user overrides, config defaults, runtime mode, and provider-extension
payloads.
Overrides must preserve the difference between inherit, disable, set,
unsupported, and unavailable. Plain optionality is not policy.
Review Questions
- What provider-specific fact is being used, and who owns it?
- Is this code inside a provider crate, typed provider-extension seam, or shared runtime?
- Is shared code branching on provider strings, model prefixes, native field names, or native response shapes?
- Does
ModelProfileor the catalog already own this capability/default? - If this is new capability/default, should catalog/profile ownership expand?
- Are provider params validated before use?
- Are provider params opaque to shared runtime after validation?
- Does this override distinguish inherit, disable, and set?
- What happens if model/provider/auth binding changes during resume, hot-swap, or mob member construction?
- Is derived policy recomputed from new identity?
- Does
AuthMachineown auth lifecycle, or is a surface/provider/helper caching auth truth? - Does exact self-hosted alias resolution happen before prefix inference?
- Is provider-native data stored as canonical Meerkat state?
- If a provider-specific concept must cross a boundary, is there a typed seam and drift test?
Tension Notes
Rule 7 and Rule 1: provider mechanics may belong to provider crates, but shared capability and policy facts belong to catalog/profile/auth/factory seams. Do not let both own the same fact. Rule 7 and Rule 2: auth lifecycle is not a provider callback. Provider callbacks produce evidence.AuthMachine owns auth state change.
Rule 7 and Rule 3: provider-native forms are projections at the boundary. They
may be useful for IO, diagnostics, or interop, but must not seed canonical
session truth during recovery.
Rule 7 and Rule 4: provider strings, model prefixes, and JSON keys are not
enough. Use typed provider identity, model identity, AuthBindingRef,
ModelProfile, validated extension payloads, and typed policy overrides.
Rule 7 and Rule 5: optional provider features own their feature-local assets
behind provider or feature seams.
Rule 7 and Rule 6: surfaces may expose friendly provider syntax. They must
lower it into shared runtime seams.
Rule 7 and Rule 8: provider failures become typed Meerkat faults. Transport
timeout, rate limit, auth failure, malformed response, dropped stream, and
provider cancellation are not interchangeable.
Rule 7 and Rule 9: provider crates are authority boundaries. Dependencies from
shared runtime or surfaces into provider-specific internals are dogma alarms
unless explicitly part of a typed seam.
Maxims
- Provider names are coordinates, not law.
- Policy follows identity or it lies.
- Raw provider params may enter through the gate; they may not govern the house.
- Auth failure is
AuthMachineevidence, not adapter authority. - If a provider branch lives outside its seam, prove the owner or delete the branch.
Chapter 8: Terminality and Faults Are Explicit
Thesis
Terminality is semantic truth. Faults are semantic evidence. They are not incidental control-flow details. A Meerkat run may be driven by loops, futures, provider streams, transports, stores, projections, callbacks, and recovery code, but those paths must not invent their own endings. The same condition must lower to the same terminal authority no matter where it is detected. The forbidden lie is not only “everything succeeded.” It is also “nothing happened”, “the caller does not need to know”, “the test path is close enough”, and “we logged it, therefore we handled it.”What The Rule Forbids
Rule 8 forbids parallel terminal paths. A timeout caught in a provider adapter, agent loop, and SDK transport must not produce three different result classes. It forbids false success. A run that was cancelled, partially streamed, abandoned by a dropped receiver, recovered from stale state, or completed without verified authority must not be reported as successful completion. It forbids turning hard failure into soft control. A warning may steer behavior; it may not stand in for terminal outcome. A retry delay may schedule the next attempt; it may not mean progress. A dropped channel may end delivery; it may not mean the event was observed. It forbids fault handling by side effect. Logging, metrics, best-effort cleanup, swallowed panics, defaulted wire fields, and silent reconnection are evidence at most. They are not semantic outcomes unless the owning machine, protocol, or contract says they are. It forbids hidden divergence between production and tests. Tests may use smaller budgets and fake providers, but they must preserve the same terminal semantics, ownership, schema behavior, cancellation obligations, and backpressure policy as production.Violation Examples
Cancellation Cuts Through A Transition
A session loop races the main run future against interrupt handling. The interrupt arm wins and the run future is dropped while a transition is between two awaited writes. The caller receivesinterrupted, but machine state now
contains half of the abandoned transition.
Correct shape: state-mutating async paths are cancel-safe, guarded by rollback,
or wrapped in explicit transition state that can resume, compensate, or
terminally fail.
Partial Provider Output As Success
A provider stream yields content chunks, then the connection dies. The adapter returns partial text as a normal assistant message because the old path expects a response. Correct shape: partial output is evidence. It is truthful success only if the authority explicitly models partial terminal success.Lagged Event Channel As Transport Annoyance
A REST or RPC event channel lags, drops events, logs the lag, and continues. If observers rely on those events to reconstruct lifecycle or terminal outcome, the drop is semantic. Correct shape: dropped observations have declared consequence: reject, replay, resync, degrade, or mark the observer stale.Schema Default As Recovery
A schema reader accepts malformed tool arguments by defaulting them tonull.
The system has replaced one semantic fact with another.
Correct shape: missing args, malformed args, and empty args are different typed
outcomes when they matter.
Panic Recovery Without State Repair
A panic is caught and converted into internal error after transition code has already mutated state. Correct shape: panic recovery restores pre-state, marks a partial-transition state, or crashes loudly before corrupt state is observed.Correct Solution Shapes
Unify terminal paths. Define terminal outcome at the machine, composition, handoff protocol, or public contract that owns the run. Make success carry proof. A success result means the canonical authority reached a successful terminal state and required effects, observations, or persistence obligations were satisfied. Separate soft and hard control. Use typed steering for warnings, hints, retry recommendations, degraded modes, and budget pressure. Use typed terminal outcomes for cancellation, timeout, rejection, exhaustion, corruption, authorization failure, and unrecoverable drift. Make cancellation a first-class obligation. Any state-mutating async path that can be dropped must be cancel-safe, guarded by rollback, or wrapped in explicit transition state. Define backpressure where the queue is introduced. Bounded queues need named capacity, overflow policy, and semantic consequence: block, reject, drop newest, drop oldest, compact, or degrade. Unbounded queues need extraordinary justification. Put timing into profiles and contracts. Deadlines, retry budgets, stale leases, idle timeouts, keepalive intervals, and provider request limits must be owned timing policy, not magic durations in leaves. Model external drift. Providers, auth systems, stores, leases, response caches, sockets, and remote sessions can change outside Meerkat. The next interaction must not pretend internal state remained fresh. Treat schema skew as terminal or migration event. Version mismatch, unknown fields, malformed payloads, missing required facts, and stale persisted data must either migrate through declared migrators or fail closed. Specify cascade routes. Every seam error in a composition needs a failure route: retry, back off, compensate, fail dependents, isolate member, degrade surface, or terminate parent. Keep test modes semantically isomorphic. Tests may accelerate clocks and fake IO, but they must preserve outcome classes, queue behavior, schema strictness, cancellation model, and failure routes.Review Questions
- What is the one canonical terminal outcome for this condition?
- Can the same condition be detected in another task, callback, transport, SDK, provider, recovery path, or test harness?
- Does success prove completion, or merely absence of local error?
- What happens if cancellation occurs between every pair of awaits?
- What happens when the receiver is slow, gone, or lagged?
- Where are deadlines and retry budgets owned?
- What external state can drift while Meerkat is idle?
- What happens to old persisted data and new wire payloads when schemas diverge?
- Can adversarial input force excessive memory, ambiguous identity, malformed defaults, or panic paths?
- If this fails inside a composition, who else fails, retries, compensates, or continues?
- Do tests exercise the same terminal and fault semantics as production?
Tension Notes
Rule 8 and Rule 1: terminality belongs to the same authority that owns lifecycle truth. If a helper knows the run is over but the machine does not, the helper is attempting to become authority. Rule 8 and Rule 2: fault handling may require new machine inputs or states. Do not patch around a missing timeout, cancellation, or partial-output transition in handwritten code. Rule 8 and Rule 3: stores and projections may report replay failure, drift, or staleness. They must not invent recovered truth. Rule 8 and Rule 4: faults need typed identity. Closed, gone, lagged, cancelled, expired, rejected, and failed are not interchangeable strings. Rule 8 and Rule 5: optional features must own their own feature-specific fault semantics and fixtures. Rule 8 and Rule 6: surfaces may choose how to display a fault. They may not reclassify it. Rule 8 and Rule 7: provider-native failures must be translated at the provider seam into typed Meerkat outcomes. Rule 8 and Rule 9: public contracts must expose real production fault semantics. A schema that omits cancellation, partial completion, backpressure failure, or version rejection is lying.Maxims
- One condition, one ending.
- Success must prove itself.
- A logged fault is not a handled fault.
- Cancellation is a transition, not an interruption.
- Tests may be faster than production; they may not be a different world.
Chapter 9: Contracts, Crates, and Generation Are Ratchets
Thesis
Meerkat declared architecture must tighten reality, not decorate it. A public contract, crate boundary, generated file, schema, SDK type, formal spec, or governance ledger is not a comment. It is an architectural ratchet: once introduced, it must make drift harder, ambiguity smaller, and production behavior more constrained than before. A generated artifact that does not govern the production path is theater. A crate boundary that does not preserve ownership is camouflage. A compatibility field with no expiry is rot with a friendly name. The question is never merely whether a contract exists. The question is: does this contract bind the production authority path, and does CI prove it cannot drift?What The Rule Forbids
Rule 9 forbids hand-authored semantic mirrors. A semantic mirror is any duplicated representation of a meaningful fact that can drift from its owner: a second status enum, a legacy wire field that still feeds behavior, a handwritten SDK type that decides defaults differently from the server, a documentation table used as a catalog, or a generated schema that describes a path production does not actually use. Rule 9 forbids generated artifacts that merely describe intent. Generated artifacts must constrain production. If OpenAPI, RPC catalogs, SDK types, machine specs, generated kernels, formal models, or governance ledgers can go stale without failing a test, they are stage props. Compatibility mirrors are forbidden unless all of these are true:- the mirror is temporary
- the mirror is read-only
- the mirror is derived from a named authority
- the mirror has a declared owner
- the mirror has a freshness rule
- the mirror has an enforced drift test
- the mirror has an explicit expiry condition
- the mirror has explicit Highest Dogma Authority approval
- the mirror cannot feed decisions, defaults, recovery, terminality, acceptance, or public authority
meerkat-core gains filesystem or network
authority, the core contract has been corrupted. If a facade quietly creates a
new semantic owner, composition has become concealment.
Finally, it forbids false progress. Adding a type, schema, manifest, generated
file, SDK helper, compatibility flag, or governance row while leaving old
ambiguity alive is not improvement. It widens the blast radius.
Violation Examples
Generated Contract That Does Not Govern Production
The repo commits RPC schemas, SDK types, or OpenAPI output, but the server accepts methods through a separate handwritten router that can diverge. The generated artifact is not a ratchet. Correct shape: production router, public schema, SDK types, and docs derive from the same authoritative catalog or mechanically checked projections. CI regenerates artifacts and fails on diff.Catalog Machine Verified, Production Machine Forked
The catalog DSL defines a canonical machine and feeds schema generation and model checking, while production carries a separatemachine! body for the
same conceptual machine.
Formal verification covers one body; production executes another.
Correct shape: one authoritative machine body per canonical machine. Production
modules are generated from the catalog or expand catalog-owned source. Drift
checks compare schema and generated output, not just names.
Legacy Field Without Expiry
A public response keepsold_status for backwards compatibility. New code
still reads it, and there is no breaking-release gate, contract version, date,
owner, or removal test.
The field became permanent authority by inertia.
Correct shape: if the old field must remain temporarily, it is derived
read-only from canonical status, approved by the Highest Dogma Authority,
documented with expiry, covered by drift test, and forbidden from feeding
behavior.
Contract Crate Becomes Behavior Crate
meerkat-contracts starts computing runtime policy, selecting provider
defaults, validating machine transitions, or embedding provider behavior
because wire types were nearby.
The crate boundary inverted.
Correct shape: meerkat-contracts defines stable wire vocabulary, schema
surfaces, error codes, and versioning. Runtime policy lives in runtime, facade,
profile, auth, or composition seams.
Ambiguity Moved Instead Of Removed
A bug says terminal states are ambiguous. The fix addsTerminalStatusV2 while
leaving status, phase, and completed: bool active. Different surfaces pick
different fields.
The change increased ambiguity.
Correct shape: introduce the new canonical type with a migration plan that
retires or mechanically derives old forms. If old wire fields must exist
temporarily, they are expiry-bound mirrors and cannot affect behavior.
Correct Solution Shapes
Use authority-derived generation:- catalog DSL generates machine schemas, formal specs, and production machine modules
- typed RPC catalog generates method schemas, SDK wrappers, and server registration checks
- OpenAPI is emitted from the same REST route contract production registers
- SDK types are generated from
meerkat-contractswire types or checked schema - governance ledgers are generated from typed registries and fail when ownership rows are missing or stale
meerkat-coreowns shared contracts and trait vocabulary; it must not gain network or filesystem authority.meerkat-contractsowns public wire shapes, schemas, error codes, and contract versioning; it must not become runtime policy.meerkat-runtimeowns the runtime control plane andMeerkatMachinepath.meerkat-sessionowns session service implementations; it must not become runtime authority.- provider crates own provider-native mechanics; they must not export provider folklore as shared truth.
- surface crates own transport and UX; they must not own meaning.
- facade crates compose; they must not hide new authorities.
Review Questions
- What production authority path does this contract describe?
- Is the artifact generated from that path, or hand-authored beside it?
- Can production behavior drift without failing CI?
- What rerun-and-diff or schema parity gate protects this artifact?
- If this is hand-authored, why is it not a semantic mirror?
- Is this a projection, compatibility mirror, or new authority?
- What is the source truth for this projection?
- Can stale projection data affect behavior?
- Does every compatibility mirror have Highest Dogma Authority approval?
- Does every compatibility mirror have date, contract version, or breaking-release expiry?
- Does any legacy field feed decisions, defaults, recovery, terminality, acceptance, or public authority?
- Does this crate own the concern being added to it?
- Are public SDKs and schemas derived from the same contract production uses?
- Does this change remove ambiguity, or add another representation beside the old one?
- If a future maintainer edits the wrong place, what test fails?
Tension Notes
Rule 9 and Rule 1: contracts, crate boundaries, generated artifacts, and ledgers must preserve singular ownership. Rule 9 and Rule 2: it is not enough to generate specs from a machine catalog if production executes a separate handwritten body. Rule 9 and Rule 3: permanent read models are projections. Compatibility mirrors are external-client debt with approval and expiry. Rule 9 and Rule 4: a generated bad contract is still bad. Generation ratchets the chosen model; it does not sanctify the wrong abstraction. Rule 9 and Rule 5: generated indexes and product manifests for optional features must derive from feature-owned declarations. Rule 9 and Rule 6: generated surface schemas must describe shared runtime-backed behavior, not parallel surface-local interpretation. Rule 9 and Rule 7: when provider portability is impossible, use a typed provider-extension seam. Do not smuggle native fields into shared logic. Rule 9 and Rule 8: public error codes, terminal statuses, cancellation results, retry classes, and recovery outcomes must be generated from or checked against the authority that owns fault semantics.Maxims
- If it does not constrain production, it is not a contract.
- A generated artifact without a drift gate is theater.
- A permanent duplicate is either a projection or a violation.
- Compatibility mirrors require a fuse and the Highest Dogma Authority’s blessing.
- Every new artifact must reduce ambiguity, or it has failed.
