The Four Planes: Hermetic Domain Isolation & Supply-Chain Provenance
The Four Planes: Hermetic Domain Isolation & Supply-Chain Provenance#
A language model has no innate sense of architectural boundary. Given a working tree that mixes specifications, compiled engines, user interfaces, and host closures, it will treat every file as equally mutable context. The typical failure is not a syntax error. It is a cross-plane edge: an Infra flake edited to paper over a Membrane layout bug; a Substrate state machine relaxed to match a stale Markdown contract; a public handbook paragraph that silently absorbs a private client identifier.
Nomos treats that class of error as a topology problem, not a prompting problem. The repository graph is partitioned into four hermetic planes. The compiled Go runtime, not the model, owns the edges between them. Documentation is not copied; it is projected with SHA-256 byte parity. Execution does not occur on trunk; it occurs in disposable worktrees whose contents are hashed, gated, and—on release—bound to an Ed25519 receipt.
This chapter specifies the planes, the enforcement mechanisms, and the provenance chain that makes an agent's output auditable.
Why a Flat Graph Is Not a Substrate#
Early agentic repositories were organized by stack, team, or convenience: src/, docs/, infra/, web/ as folders inside one permission domain. Humans compensate for that mess with tribal knowledge. Models do not. They saturate the context window with unrelated files, invent import paths that compile locally and violate the intended module graph, and treat a wiki paragraph as if it were a type.
Three failure modes follow:
- Cognitive drift. Teleology, sensory UI, deterministic engines, and deployment manifests share a namespace. The model hallucinates dependencies that no human would draw.
- Split-brain documentation. Specs live in a wiki; code lives in git. After a few cycles the two disagree, and the agent grounds itself on the wrong one.
- Provenance collapse. A commit that mixes public handbook text with private ledger paths cannot later prove clean-room origin. Legal and operational audit both fail.
The design rule is therefore mechanical:
The harness under the agent must expose the same isolation topology the agent's reasoning is required to respect. If a plane boundary is not a filesystem, import, and git boundary, it is a suggestion. Suggestions are not invariants.
Nomos does not add a fifth "agent plane." The agent is a transverse operator with a budgeted token and a CapBAC step limit. The planes are the static fabric it is allowed to touch, one task at a time.
The Four Planes#
The four planes are an orthogonal basis for the engineering lifecycle: from human contract to physical host. Each plane has one ontological responsibility, one class of artifact, and a hard negative invariant (what it must never do).
INTENT why it exists; contracts, specs, SSoT
│
SUBSTRATE how state transitions; compiled Go, AST gates, worktrees
│
MEMBRANE how observers perceive it; SvelteKit, telemetry, cockpits
│
INFRA where it runs; NixOS, daemons, silicon, tunnelsThe vertical order is dependency of meaning, not a call stack. Membrane does not sit "above" Substrate in a request path. Infra does not "implement" Intent. Edges between planes are explicit, versioned, and verified. An agent task is labeled with exactly one plane namespace (INT-*, SUB-*, MEM-*, INF-*) and is refused if its diff crosses another.
Intent Plane#
Question. Why does this exist, and what must remain true?
Owns. Axioms, architecture, living specifications, formal contracts, public handbooks, schema definitions, and the Single Source of Truth (SSoT) corpus.
Artifacts. vault-intent (the Living Vault): Markdown with YAML frontmatter, RFC-class architectural notes, protocol schemas. Public material lives under vault/public/. Sovereign material lives under vault/private/ and is excluded from every public compile.
Negative invariant. The Intent plane contains no runtime execution logic. It specifies contracts. It does not implement them, render them, or deploy them.
Intent is not "docs." It is the type system of purpose. If Substrate and Intent disagree, Substrate is wrong or Intent is stale; the release gate does not care which. It refuses the transition until they match.
Substrate Plane#
Question. How does the system deterministically execute state transitions and verify invariants?
Owns. The compiled Go engine (nomos), the lifecycle state machine (TRIAGE → SPEC → PLAN → EDIT → REVIEW → SYNC → LEARN), AST analyzers, Definition of Done gates, SQLite persistence, and transient worktree sandboxes.
Artifacts. nomos-substrate (open-core engine) and, where present, nomos-sovereign-substrate (proprietary worker dispatch and telemetry mesh). Playbooks, AGENTS.md, and machine protocol schemas live inside this plane as its declarative core—not in a separate commons repository.
Negative invariant. Substrate core contains no probabilistic reasoning. The LLM is a bounded heuristic subroutine invoked by the engine with an ephemeral CapBAC token and a step budget. Verification is binary: cyclomatic complexity < 15, docstring density ≥ 10%, import boundary closures, 100% green test traces. Failure is exit 1. There is no negotiation path.
This is cognitive inversion applied to topology: control flow belongs to the compiled runtime. The model proposes diffs inside a worktree. The plane accepts or rejects them.
Membrane Plane#
Question. How does the system perceive and interface with human observers?
Owns. Human-in-the-loop cockpits, public web applications, SvelteKit surfaces, real-time telemetry, interactive simulations, browser-native audio where required.
Artifacts. sophia-membrane, nomos-sovereign-membrane, gsi-membrane, and their design-token / UX specification trees.
Negative invariant. Membrane consumes telemetry and exposes interfaces. It never mutates Substrate database records, never issues physical deployment commands, and never authors Intent contracts. A UI change that "needs" a schema change is two tasks, two worktrees, two reviews.
Infrastructure Plane#
Question. Where does compute execute, and how is the host closure maintained?
Owns. Declarative host closures, NixOS flake modules, process supervisors, GPU runtimes, backups, network tunnels, bare metal.
Artifacts. gsi-infra, host flakes, daemon units, failover endpoints, hardware inventory.
Negative invariant. Infra provides the physical substrate on which engines run. It does not define product features, business invariants, or UI behavior. An Infra change that "fixes" an application bug is a misclassified task; the bug belongs in Substrate or Membrane.
Boundary Enforcement#
A plane boundary that exists only in a slide deck will be crossed on the first long context window. Enforcement is therefore physical: filesystem layout, import graphs, git refs, pre-commit hooks, and release gates.
One task, one plane#
Backlog identifiers are plane-prefixed. SUB-1847 may touch Go packages, AST gates, and Substrate-local playbooks. It may not restyle a Svelte route or edit a NixOS module. The orchestrator (Tier 1) decomposes any request that spans planes before a Tier 2 worker is spawned. A worker that produces a multi-plane diff fails REVIEW for boundary violation, even if tests are green.
This is the same idea as a module system's visibility rules, applied to agents. Blast radius is the worktree, not the company.
Import and package closures#
Substrate AST gates close the import graph. A Go package in the engine may not import Membrane application code. Membrane may depend on published Substrate telemetry schemas, not on internal SQLite types. Infra flakes may reference build outputs; they may not vendor application logic.
The check is static. A forbidden import is exit 1 at nomos verify, identical in kind to a failing test.
Trunk is read-only to agents#
Pre-commit hooks refuse agent edits on trunk and on long-lived integration branches. The only writable git surface for a worker is an isolated worktree:
worktrees/<repo>-<task>Example: worktrees/nomos-substrate-SUB-1847. The worktree is created from a known commit, used for the EDIT/REVIEW cycle, and destroyed after SYNC or abort. Hooks on the worktree still run the plane's gates. Hooks on trunk refuse the same patch if it arrives by any path other than the two-phase release procedure.
Dual core stays inside the plane#
An earlier design split "code repos" from "docs repos" across git remotes: compiled Go in one place, contracts in another. Every change then required a multi-repository dance. The result was split-brain commits—the compiler moved, the contract did not, or the reverse.
The corrected rule:
Executable core and declarative core are dual poles of the same plane, in the same repository, reviewable in one transaction. They are not a fifth and sixth plane, and they are not a reason to fragment git.
| Plane | Executable core | Declarative core |
|---|---|---|
| Intent | Document compilers, link/reference verifiers, schema harnesses | Markdown axioms, handbooks, human contracts |
| Substrate | nomos binary, AST DoD gates, SQLite state machine |
Playbooks, schema.json, AGENTS.md |
| Membrane | Svelte renderers, canvas/audio runtimes | Design tokens, UX specs, field manuals |
| Infra | Hosts, daemons, backups, tunnels | NixOS modules, compose/network manifests, inventories |
An agent editing Substrate can verify the binary and the protocol schema in one nomos verify. That is the entire point of keeping both cores in-plane.
The Agent Is a Transverse Operator#
If the agent were a plane, it would own a layer of the stack and a class of artifacts. It owns neither. It is scheduled by the Substrate state machine, reads Intent, mutates at most one plane per task, may observe Infra and Membrane telemetry, and writes residual learning back into git notes—not into a parallel knowledge base.
INTENT ingest contracts, invariants, acceptance tests
│
▼ SPEC / PLAN
SUBSTRATE propose diffs in a worktree; pass AST + test gates
│
▼ optional observation, never unplanned mutation
MEMBRANE UI/telemetry tasks only when the task id is MEM-*
│
▼
INFRA host/flake tasks only when the task id is INF-*
│
▼ 2PC + signed receipt
SUBSTRATE merge to baseline; prune worktree
│
▼ LEARN
INTENT distill notes to refs/notes/agent (not to public SSoT)Tier 1 (orchestrator) performs strategic decomposition, plan signoff, and release sync. Tier 2 (swarm workers) are sandboxed TDD processes with no trunk credentials and no right to span planes. This is not organizational chart theatre. It is how CapBAC budgets stay meaningful: a worker token is scoped to one worktree, one plane, one step budget.
Hermetic Worktrees#
Hermeticism here means: the worker cannot see, and therefore cannot contaminate, anything outside the task closure.
Construction. From a pinned commit, create git worktree add at worktrees/<repo>-<task>. Copy or bind only the files the plane's protocol says the task may read. Private vault paths are absent from public-plane worktrees. Foreign-plane working copies are absent entirely.
Mutation. All EDIT phase writes land in the worktree. The model never receives a path to trunk. If it emits one, the apply step rejects it.
Verification. nomos verify runs in the worktree cwd. Gates include tests, AST complexity, docstring density, import closures, and—on Intent/Membrane public paths—SSoT parity and clean-room scanners.
Disposal. On abort, delete the worktree and its branch. On success, the worktree is an input to two-phase commit, not a long-lived feature branch. Lingering worktrees are a hygiene failure and are reaped by the engine.
This is the same isolation VM snapshots give CI, implemented with git's own object model so the audit trail is native: every byte the agent wrote is a git object, addressable, hash-stable, and discardable.
SSoT Projection and SHA-256 Byte Parity#
Documentation drift is a state-replication bug. Wikis replicate by human memory. Nomos replicates by compile.
The Living Vault (vault/public/) is the only writable source for public architecture, handbook chapters, and dispatches. Membrane portals do not own content. They receive a projection.
vault/public/**/*.md
│ nomos intent compile
▼
AST parse
inject provenance banner (frontmatter-safe)
write portal content stores
│
▼
SHA-256(source) == SHA-256(strip(banner, projection))
│ fail closed
▼
Membrane glob import → routes, Cmd+K index, sitemapProperties that matter:
- Single writer. A portal file edited in place is a defect. The parity gate (
nomos intent check) computes a clean SHA-256 over the semantic bytes of each document. Mismatch stopsnomos release shipat Gate 1. - Provenance banner. Projected files carry an immutable HTML comment: do not edit; mirrored from vault SSoT; source path and hash. The banner is excluded from the parity digest so the digest compares content, not the wrapper.
- No config for publishing. A new
vault/public/handbook/*.mdbecomes a route because the Membrane uses compile-time glob imports. Missing from vault means missing from production. There is no third store. - Public/private cut.
vault/private/is not an input to the CMS. Client ledgers, CRM, pricing, NDA artifacts, and employer-adjacent notes have no compile path to public membranes. Absence is enforced by path allowlists, not by reviewer memory.
Byte parity is stronger than "docs as code" slogans. It is a replica-consistency check. If it is not bitwise, it is not deployed.
Supply-Chain Provenance#
An autonomous coding system is a software supply chain that emits patches. The usual SBOM story (hash the container) is necessary and insufficient. The questions that actually arise are:
- Did this diff come from a hermetic worktree, or from a laptop checkout of trunk?
- Did public artifacts remain free of private identifiers and foreign IP?
- Can a third party verify the release without trusting a chat log?
Nomos binds those answers to git objects and signatures.
Two-phase commit and signed receipts#
Releases are not git push from a worker. They are a two-phase commit driven by the Substrate:
- Prepare. Worktree passes
nomos verify. Tree hash, test trace, gate vector, and task id are recorded. - Commit. Fast-forward (or explicit merge) to the release ref. Attach an Ed25519-signed receipt to
refs/notes/agent.
The receipt is the audit record: who/what orchestrated, which model id (if any) was invoked, token/step budget consumed, worktree commit, SHA-256 of the released tree, and the Intent documents that authorized the change. Notes travel with the object database. They are not a sidecar wiki.
Clean-room scanners#
Before public projection and before ship, AST and text scanners run on the staged closure:
- Forbidden employer marks, vendor codenames, client identifiers, and private path fragments.
- Accidental inclusion of
vault/private/material in a public tree. - Membrane or handbook files that do not match vault hashes.
A hit aborts the pipeline. The agent cannot comment the finding away. The next legal move is to delete or rewrite the offending bytes in the worktree and re-verify.
Execution locality#
Tier 2 mutation workers run on local silicon against open-weight models when the closure is proprietary. Prompts and code do not egress to a third-party trainer. This is not a privacy slogan; it is how clean-room claims remain true under disclosure. Public open-core paths may use other inference, but they still pass the same scanners and parity gates.
Persona and origin invariants#
System instructions for workers state origin as a fact to be preserved in generated text: Nomos is an original substrate, not a derivative of a prior employer's internal system. That instruction is necessary and weak. The strong controls are the scanners, the vault split, and the worktree allowlist. Prompts decay. Hash gates do not.
What provenance is not#
Provenance is not a watermark in model weights. It is not a screenshot of a passing CI job. It is a chain:
Intent document (hash)
→ task id + plane
→ worktree commit (hash)
→ verify vector (tests, AST, parity, scanners)
→ release commit (hash)
→ Ed25519 note on refs/notes/agentBreak any link and the ship gate fails closed.
Workstation Mapping#
The four planes map onto four working copies so humans and agents share the same topology:
| Plane | Workspace | Task namespace |
|---|---|---|
| Intent | …/workstations/intent/vault-intent |
INT-* |
| Substrate | …/workstations/substrate/nomos-substrate |
SUB-* |
| Membrane | …/workstations/membrane/sophia-membrane |
MEM-* |
| Infra | …/workstations/infra/gsi-infra |
INF-* |
A checkout is not a permission grant to the other three. IDE convenience must not flatten the graph the hooks exist to protect.
Invariants#
The chapter reduces to a short list. If a future change violates one of these, it is not a refactor; it is a different system.
- Four planes, no fifth. Intent, Substrate, Membrane, Infra. The agent is an operator with a budget, not a layer.
- One task, one plane, one worktree. Cross-plane diffs are orchestration failures, not cleverness.
- Dual core is in-plane. Executable and declarative artifacts of a domain share a repository and a verify transaction.
- Substrate is non-stochastic. Models propose; gates dispose.
exit 1ends the transition. - Trunk is hermetic. Agents write only in
worktrees/<repo>-<task>. Releases are 2PC plus an Ed25519 note. - SSoT is bitwise. Public membranes are projections of
vault/public/with SHA-256 parity.vault/private/has no public compile path. - Provenance is a hash chain. Scanners, parity, test traces, and signed receipts are jointly necessary. Any one missing is a refused release.
The four-plane cut does not make agents wise. It makes their mistakes local, rejectable, and attributable. That is the requirement. Everything else in the harness exists to keep those three adjectives true under automation.