Definition, instance, domain
The control plane keeps three things apart, and each has its own owner: the definition, the instance and the domain. Keeping them separate is what lets one control plane run against many repositories, and it is also what stops a run's traces from becoming a second source of truth beside the definition.
The definition
The definition is what the control plane is. It is versioned, checked, and shipped with the package, and every part of it is a declared file:
| Part | Where | What it declares |
|---|---|---|
| Registry | registry/regulators/*.json | one record per regulator |
| Identity seed | identity/*.md | the four S5 files every instance starts from |
| Profiles | profiles/*.json | what a unit type may use and where it may write |
| Policies | policies/*.json | budgets and model routes, recovery, routing, and interaction |
| Workloads | workload/*.json | the unit types, with their profiles and their checks |
| Evals | evals/*.json | suites with declared arms and ablations |
| Contracts and fixtures | contracts/, fixture*/ | the examples the package runs against itself |
| Settings | settings.json | the Pi settings a unit's session runs under |
regulator check validates all of it together. It confirms that every profile a workload names exists, that every tool a profile grants is declared with its effect, that a contract-less unit type runs under a read-only profile, that every registry record cites tests that exist and states a limitation, and that no review date has passed. The check runs under pnpm check, so the definition cannot drift from the code that enforces it without the check failing. The definition reference documents each file.
A change to the definition is a pull request. The identity seed has one more way to change. An identity decision accepted in an instance can be promoted into the seed with regulator identity promote, and every later init then starts from the promoted version.
The instance
An instance is one repository running under one definition at one revision. regulator init creates it, and the instance layout lists what it holds. Two kinds of state live there. They sit in different stores, and neither is inferred from the other.
Execution state is the units, the attempts, the leases, the budgets consumed and the worktrees. It lives in the orchestrator's store, and only the loop writes it.
Regulatory state is the trace, the signals, the obligations, the evidence, the verdicts, the memory and the effect journal. It lives in append-only logs and the event store. The regulators write it, and the loop reads it to decide what a unit may do next.
Nothing in .regulator/ is configuration, and a person edits none of it by hand. What a person declares about an instance (the writable and protected prefixes, and who initialized it) lives in the manifest, which init writes and which the profile grant and the closeout read. The manifest also pins the definition's revision. An instance initialized under an older revision shows definition-drift in doctor until a person reads the upgrade note and runs the next unit.
The repository's own files say nothing to the harness. Its .pi/ directory, its AGENTS.md, its extensions and its skills never configure a unit's session. That is the trust rule: the project is the domain, and the domain does not configure its regulator.
The domain
The domain is the repository: the code, the tests, the ledger, whatever the workload is about. Units change it in worktrees, on branches, and the loop reintegrates what verified. The harness reads the domain as evidence at a revision, through the host checks, and never as state. Two files are the exception, and they are the domain's only harness-owned content. The first is regulator/identity/, the instance's copy of the S5 files, which is committed and protected by the write gate, the bash snapshot-and-restore and the identity-untouched check. The second is the .regulator/ line in .gitignore. Protecting identity explains those layers and the one path that changes an identity file.
Why the split matters
- A run's trace under
.regulator/can be deleted, and the definition still says exactly what the control plane does. - Two repositories under the same definition behave the same way. They differ only in what their manifests declare.
- The eval harness can run the same suite against a fixture under different arms, because an arm is a definition-level choice (which extensions load, which checks run, whether identity is seeded) and never a property of an instance.
- Promotion has a direction, from instance to definition. A person does it, with a rationale, and commits it in the definition's repository. Nothing flows the other way by itself.