Canonical Machines
The canonical registry iscanonical_machine_schemas() in
meerkat-machine-schema/src/catalog/mod.rs.
MeerkatMachine and MobMachine are the two runtime kernels. Auth,
scheduling, durable jobs, and runtime delivery are auxiliary authority machines that protect
specific perimeter state. WorkGraph is an optional subsystem authority for
durable agent commitments, dependency-aware claim state, and goal attention
bindings. WorkExecutionLifecycleMachine owns the cross-system obligation for
one execution attempt without absorbing either WorkGraph item truth or Mob Flow
run truth. Its effects are realized mechanically by the Mob composition facade,
and every launch, evidence, or closure outcome returns through a typed machine
input before the binding advances.
One scoped authority sits outside the canonical registry:
MobHostBindingAuthority (catalog DSL source
meerkat-machine-schema/src/catalog/dsl/mob_host_binding_authority.rs,
production expansion meerkat-mob/src/machines/mob_host_binding_authority.rs).
It is the member host’s process-scoped, mob-keyed admission and dedup
authority for host-addressed mob commands: supervisor bind/rebind/revoke,
host-command admission, materialize admission/preflight with success-only
dedup memory, release admission with recorded-disposal replay, and the remote
turn-outcome journal. It follows the session_persistence_version_authority
precedent — one shared DSL body expanded into both crates, pinned by a
dedicated production-schema parity test
(meerkat-mob/tests/mob_host_binding_authority.rs) and by kernel tests
instead of TLC — so it carries seam-inventory dispositions like any machine
but has no poster, no generated kernel, and no entry in
canonical_machine_schemas().
Principal control-scope grants (multi-host mobs §8) follow the
ToolExecutionPolicy split. The MobMachine owns the grant lifecycle — the
operator_grant_scopes / operator_grant_expiries facts, the
GrantOperatorScopes / RevokeOperatorScopes transitions, and the in-machine
revalidation of caller-proposed revoke partitions — while scope resolution
lives shell-side in the sealed ResolvedControlPolicy
(meerkat-mob/src/control_policy.rs): private shape, one resolve() mint
path, no serde, fail-closed to the empty scope set. Expiry is data: the
machine never reads a clock; the enforcement chokepoint reads the wall clock
once per decision and passes now_ms in as a parameter, so a restored mob’s
expired grants stay expired with zero persisted derived state. Grant
durability is a runtime-metadata record (MobOperatorGrantRecord) written
only under GrantRecorded/GrantRevoked transition witnesses and replayed
on resume through the machine’s own GrantOperatorScopes input — never a
second enforcement source.
Durable-Tail Recovery Ownership
ASession is domain state, not a portable proof of persistence. It carries
the conversation, metadata, usage, and compact transcript-rewrite graph, but
no embedded persistence authority. Physical currentness belongs to the store:
- WholeBlob authority is the exact
{session_id, store_revision, blob_sha256}issued with the serialized row. - HeadCanonical authority is the exact
{session_id, store_revision, boundary_head, committed_head_token}. The small boundary head binds its message-row, rewrite, graph, component, and metadata prefixes.
RunCheckpointReceipt naming the store profile, committed base, run, exact
candidate identity, and a contiguous candidate_sequence. A later write in
the same run must present the preceding receipt; a retry must match it exactly.
The final boundary promotes the latest exact receipt rather than serializing
or applying the accumulated state again.
A shutdown race can still leave the latest candidate durable while its
runtime boundary is uncommitted. Durable is not the same as
runtime-committed, and recovery of that tail is machine-owned end to end.
Ownership splits three ways:
- The runtime store retains;
SessionDocumentMachineclassifies. Store-issued committed authority and provisional-tail authority decide what a reader may be served; a recovery candidate is never returned as an ordinary session.ClassifyDurableTailconsumes the mechanically extracted tail shape (head relation, run-id cardinality, terminal stop reason, dangling/orphan tool counts) and emitsDurableTailClassifiedwith aDurableTailRecoveryClass:CompletedCandidate,InterruptedRepairableCandidate, orAmbiguous. The classification transitions are total and disjoint over the observation. A tail carrying any dangling tool call classifiesAmbiguous: the call proves intent, not execution, so the tail is held for reconciliation rather than repaired. The candidate id binds the exact store-issued base and candidate identities, run id, and candidate sequence, so classifying one physical tail can never authorize mutating a later one. MeerkatMachineauthorizes.AuthorizeDurableTailRecoveryconsumes the exact classified candidate together with typed projections of the durable evidence: the persisted machine-lifecycle row and its current-run fact (DurableRecoveryObservedLifecycle,DurableRecoveryObservedRun— a cold recovery drives a freshly registered authority whose in-process facts are vacuously quiescent, so the persisted row is the real evidence), the highest durably committed receipt compared against the candidate’s own content (DurableRecoveryPriorCommit— a candidate the receipts already cover refuses instead of committing a phantom duplicate boundary), and the attributability of the input rows the commit would terminalize (DurableRecoveryInputEvidence). Recovery is admissible only when both the in-process and the persisted facts are quiescent (Idle,Retired, or a missing row) with no current run and no recorded terminal for the candidate’s run; every other shape refuses. Commit verdicts arrive asDurableTailRecoveryCommitAuthorized(CommitCompletedorRepairAndCommitInterrupted), carry the machine-minted boundary sequence — one past the last committed receipt for the run — and record the candidate run as the turn terminal; hold and refusal verdicts arrive asDurableTailRecoveryAuthorized(HoldIntact,RefuseRecovery) and mutate nothing. Both hold paths — ambiguous classification and unattributable input evidence — are machine-minted: no shell predicate may downgrade a commit authorization to a hold. Authorization never changes the lifecycle phase.RuntimeStorerealizes. Only the machine’s commit-authorizing effect may drive the recovery commit, and it lands throughRuntimeStore::atomic_applyas one boundary: the exact store candidate is promoted, the run-boundary receipt, input lifecycle transitions, terminal outcome, catalog projection, and outbox rows commit together. WholeBlob promotion reuses the candidate bytes already written; HeadCanonical promotion advances the committed authority to the exact physical head. Both are fenced on the observed store, lifecycle-row, and input-row identities, so a concurrent writer fails the whole boundary typed instead of being overwritten. No shell promotes or discards the tail.recover_durable_tail(&dyn RuntimeStore, &SessionId)is the only public preparation seam. The store loads an opaquePreparedDurableTailRecoverySource; recovery derives the classification, receipt facts, candidate identity, and physical CAS before sealing crate-ownedPreparedRecoveryEvidence. There is no public request constructor or caller-mintable recovery capability.
Canonical Compositions
The canonical registry iscanonical_composition_schemas() in
meerkat-machine-schema/src/catalog/mod.rs.
These compositions are not marketing concepts or public APIs. They are
contributor-facing guardrails for the runtime implementation.
Generated Artifacts
Generated and checked artifacts live in:Contribution Rules
When a change affects lifecycle, routing, admission, credential state, mob membership, or scheduling, treat it as a machine-authority change until proven otherwise. Use this checklist:- Identify the semantic owner.
- Add or update the catalog DSL if the legal states or transitions changed.
- Regenerate machine artifacts.
- Update production bridge code to call the generated authority path.
- Run the machine verification gates.
Validation
Use the Make surface:make agent-gate and CI run the relevant gates for normal development. Use the
direct targets when you are touching the catalog, generated kernels, composition
routes, or runtime bridge code.
