02 · The engine

PRIM.A compilerfor rules.

PRIM is a deterministic runtime for written rules. Give it a grammar and a state, and it will tell you whether that state is valid, which clause it violated, and how it can be repaired back into compliance.

What it guarantees
  • Deterministic execution
  • Versioned state
  • Convergent repair
  • Structured violations
  • Explicit terminal states
Why a runtime at all

Rules exist as text.
The systems that enforce them, usually don’t.

Most software that enforces rules does so with scattered validation code, lookup tables, or institutional memory held by individual people. The rules themselves live in one place, the enforcement logic in another, and the connection between them is ad-hoc.

PRIM gives the rules an executable form. Each clause becomes a constraint class, each check the engine runs points back to the clause that wrote it, and the runtime evaluates them deterministically. A sporting code becomes a versioned library of constraints, authored clause by clause and maintained the way any regulated codebase is.

One source of truth. One place the enforcement lives.

A constraint, in code

A constraint
is a function.

Takes the state, the action, and the next state. Returns a list of violations. Never mutates. Only judges. Every constraint is a pure function of those three inputs.

Pure functions, no side effects
Hard or soft severity
JSON pointer into the offending field
Structured violations with catalog codes
domains / f1 / constraints.py
# ISC Appendix L § 3 · pit-lane speed
@dataclass(frozen=True)
class PitLaneSpeedLimit:
name: str = "pit_lane_speed_limit"
def check(self, *, state, action, next_state):
# constraints see the full transition: pre, action, post
if action.type != "record_pit_lane_pass":
return []
speed = action.params["speed_kmh"]
limit = state.data["pit_lane_limit_kmh"]
if speed <= limit:
return []
return [
Violation(
code="pit_lane_speed_exceeded",
severity="block",
category="constraint",
pointer=f"/pit_passes/{action.params['driver']}",
data={"speed": speed, "limit": limit},
)
]

A real constraint · checks transition validity, never mutates

The compiler analogy

Every concept
has an equivalent.

If you have thought about how a compiler works, you already understand PRIM. The machinery is the same, only the substrate has changed. Code becomes clauses. Types become constraints. Stack traces become structured violations with article pointers.

Compiler
PRIM
Source code
Regulatory framework
Grammar
Constraint definitions
Type checker
Constraint engine
Language plugins
Domain adapters
Error messages
Structured violations
Object hash
State identity hash
Compiled output
Auditable decisions
A violation, structured
engine_core / types.py
# What the engine returns when a state is invalid.
@dataclass(frozen=True)
class Violation:
# machine-readable code from the catalog
code: str
# human-readable, for logs
message: str
# "block" or "warn"
severity: Severity = "block"
# schema / constraint / invariant / policy / engine
category: ViolationCategory
# when in the step lifecycle it fired
phase: ViolationPhase
# JSON pointer into state: the exact "where"
pointer: Optional[str] = None
# structured details for the consumer
data: Dict[str, Any] = field(default_factory=dict)

Real type · engine_core/types.py

Not a human string.
Machine-readable.

When the engine says something is invalid, it returns the exact field that failed, the category of failure, and a structured payload the client can route. A violation is an API, not a log line.

code: the catalog entry
pointer: JSON pointer into state
category: which layer failed
phase: when in the step it fired
data: structured details for the consumer
State identity

Every state
has a hash.

States are serialised into canonical JSON (sorted keys, no whitespace) and hashed with SHA-256. Same data produces the same hash, regardless of representation. Two snapshots with identical content have identical identities.

The audit trail is a chain of these hashes. Replay any decision from any point by loading its predecessor state. Content-addressable, the way Git treats commits.

Canonical JSON serialisation
SHA-256 content addressing
Deterministic across machines
Audit reconstruction from any point
engine_core / engine.py
# canonical JSON · sorted keys, no whitespace
def _canonical_json(obj):
return json.dumps(
obj, sort_keys=True,
separators=(",", ":"),
)
# content-addressable state identity
def state_identity(state) -> str:
return sha256(
_canonical_json(state.as_dict()).encode()
).hexdigest()
# different key order, same data
a = {"phase": "race", "lap": 22}
b = {"lap": 22, "phase": "race"}
state_identity(State(data=a))
# → "a3f2b1c8d4e7..."
state_identity(State(data=b))
# → "a3f2b1c8d4e7..." # same hash

Content-addressable state · reproducible audit chain

The architecture

Three layers,
strictly separated.

The engine at the bottom. Orchestration in the middle. Adapters on top. Nothing leaks between them, so a new domain plugs in without touching the core, and the core ships updates without breaking any deployed domain.

01
Core engine

Deterministic execution

the type-checker and execution unit

  • Deterministic action execution
  • State validation against constraints
  • Structured violation reporting
  • State identity hashing
02
Session orchestration

Lifecycle and memory

the linker, scheduler, and transaction manager

  • Session lifecycle and phase transitions
  • Repair escalation paths
  • State versioning and mutation contracts
  • Concurrency control and audit trails
03
Domain adapters

Pluggable grammars

domain-specific compiler plugins

  • Phases, completion logic, mutations
  • Repair candidates from the catalog
  • Domain-specific invariants
  • Core stays generic; the adapter defines the field
The guarantees

What the runtime
holds true.

These are architectural guarantees, baked into the engine core. Not aspirations, not feature requests.

01

Convergent repair

Repair steps reduce the number of open violations. Each step is validated before it executes, so repair loops always terminate.

02

Explicit terminal states

Every session ends in one of a finite set of named terminal states. No ambiguous limbos, no orphaned sessions, no "unknown" as an outcome.

03

Thin clients

Clients request, display, and relay. They never carry hidden logic or guess at state. The engine is the source of truth.

A single action, validated

Watch the engine
process one decision.

Every step is logged, sourced, and reconstructable. The trace below is what the runtime emits under the hood.

engine.runtime · live
$ prim engine_core --process MIA-D001
runtime initialised · deterministic mode
14:38.044incident received car 87 · collision
14:38.121loading regulation ISC Art. 12.4.1.f
14:42.015evidence validated 4 sources confirmed
14:44.227penalty options enumerated 4 catalog matches
14:46.812precedent lookup 3 comparable cases
14:51.105decision issued MIA-D001
14:51.106audit trail appended
14:51.107all constraints satisfied
$
What plugs in

Any field
with a written framework.

The engine does not care what the rules say, only that they are written down. Trip planning is where the engine was stress-tested; motorsport is where it first meets the world. The others are proofs the pattern generalizes.

Sport governance

Officiating decisions, penalty validation, precedent tracking across rotating panels. Motorsport is the first we’re building.

Trip planning

A multi-day itinerary built step by step against a real movement graph, activity registry, and fatigue budgets. Each proposed step is a transition the engine validates. The most built-out PRIM adapter to date.

Financial compliance

Transaction validation, threshold monitoring, and jurisdictional rule enforcement against written policy.

Emergency response

Protocol step validation, escalation rules, and policy enforcement under time-critical constraints.

Scope

Precise boundaries.
Neither more nor less.

The engine is designed for a specific shape of problem. Knowing what it is not is as important as knowing what it is.

PRIM is
  • A deterministic runtime
    that validates actions against a grammar
  • A constraint checker
    returning structured violations with JSON pointers
  • A domain-agnostic core
    with pluggable adapters per field
  • A versioned state machine
    with content-addressable identity hashes
  • An audit-first system
    built for regulatory governance
PRIM is not
  • Not a rules engine
    no scripting DSL, no forward-chaining inference
  • Not a constraint solver
    no optimisation, no SAT or SMT backend
  • Not a workflow engine
    validates the actions humans or systems propose, does not orchestrate them
  • Not a database
    persistence is the host’s job; PRIM runs in-process
  • Not a probabilistic model
    no weights, no training, no hidden state

See the engine
in motorsport, first.

Sport governance is where PRIM meets the world first. Motorsport is the first we’re building.