Skip to content

Low-Level Design

Vinxi Kernel — Low-Level Design

Port-by-port LLD. For every port: the interface contract, its semantic invariants, the adapter options with honest pros/cons, the design considerations still live, and a worked example from one of the four acceptance scenarios (Trafficure, NetworkAccess, IT-ops, SmartMarket). Consolidates everything adjudicated to date: the five-plane model, the log family, ResolvedValue/fusion, Statement-as-evidence, P0 and P23, kernel-owned branch semantics, and the Lean-first build discipline. Contracts are written in a TypeScript-flavored IDL for readability; the kernel implementation language is orthogonal to the contract.


0. How to read this document

Each port carries a tier. Tier 1 (kernel-critical) ports are load-bearing from the first commit — the seam cannot exist without them. Tier 2 (secondary / read-model) ports matter but can start as trivial adapters. The test for every contract is unchanged: swapping the adapter must be invisible to userland. Where a contract is stated, it is the whole surface — an adapter exposing more (raw SQL, native client handles) is leaking, and the leak is a bug.

Three phrasings from the adjudication govern everything below:

The log is truth of history. The Process plane is truth of action. The World plane is truth of coherent current interpretation. The Serving plane is truth of nothing.

The token is not permission. The token is proof that policy was asked. The seam is still authority.

Ports are permanent; adapters move.


1. The plane model (final)

Five planes, replacing the earlier three. Process and Serving were previously fused as “operational”; World and Serving were fused as “analytical.” Unfused:

Apps / Agents / Workflows / Dashboards ← userland
Generated Reality SDK / MCP ← P18/P19
GOVERNED SEAM
Query │ Act │ Assert │ Call │ Subscribe │ Schedule
┌──────────────┬─────────┴─────┬──────────────────┐
│ │ │ │
PROCESS PLANE DRIVER PLANE QUERY ROUTER POLICY PLANE
authorize + emit/actuate read routing P12·P13·P14·P15
commit Acts (P16·P17) (over Serving/
(P1 + outbox) World/P4/P11)
│ │
└──── outbox ──┴──────────────┐
TRUTH PLANE ← P2 (log family)
StatementLog │ DecisionLog │ CallLog │ SchemaLog │ PolicyLog
MATERIALIZATION PLANE ← P8 (+P7 batch)
stream consumers · fusion · indexers
┌────────────────────────┼────────────────────────┐
│ │ │
WORLD PLANE SERVING PLANE ANALYTICAL STORES
resolved reality low-latency reads lakehouse/history
ResolvedValue, search/geo/graph snapshots, as-of
branch overlays (P23) caches (P1/P5) (P3·P4·P11)

Plane-to-port mapping and the one rule per plane:

PlanePortsRule
ProcessP1 (+P0 for schema Acts)A decision commits with its outbox record in one transaction, or not at all.
TruthP2Append-only, typed by log kind; nothing is ever edited.
WorldP23Never store a naked scalar; store ResolvedValue.
ServingP1 reads, P5Authoritative for nothing; wipe-and-rebuild is a supported operation.
MaterializationP8, P7Deterministic, idempotent, checkpointed; separate from the query path.

The transactional outbox is the named seam between Process and Truth — the bridge that makes “committed” and “recorded” one atomic fact instead of a dual-write. Losing that named seam is how the no-dual-write guarantee silently dies; it is called out in P1 and P2 both.


2. Conventions and shared types

Every port contract below draws on this shared vocabulary. These types are kernel-owned (they are the shape the kernel understands); their meanings are userland-owned.

// ---- identity & addressing -------------------------------------------
type RealmId = string // a bounded slice of reality
type BranchId = string // "main" is canon
type EntityRef = { realm: RealmId; type: string; id: string }
type TraitRef = string // e.g. "road.speed"
type ActorRef = { kind: "human" | "agent" | "service"; id: string }
type OrderToken = bytes // monotonic commit order, minted by P1
type ValidTime = Instant // when true in the world
type SystemTime = Instant // when recorded by us
// ---- Statement: an evidence claim ------------------------------------
// Cross-cutting record shape. NOT an eighth primitive, and NOT merely the
// payload of an Assert: an Assert usually carries one, an Act may produce
// them as effects, a Call may return them from the external world.
interface Statement {
subject: EntityRef
predicate: TraitRef
value: TraitValue // typed by the trait's kind
validTime: ValidTime
assertedAt: SystemTime
provenance: Provenance // source + trust; branch if simulated
confidence?: number // source-supplied, 0..1
correlationId?: string // ties round-trips together
}
type Provenance =
| { kind: "driver"; driver: DriverRef; trust: TrustLevel }
| { kind: "actor"; actor: ActorRef; trust: TrustLevel }
| { kind: "derivation"; job: DerivationRef }
| { kind: "simulated"; branch: BranchId }
// ---- ResolvedValue: what the World plane stores -----------------------
interface ResolvedValue<T> {
value: T
uncertainty?: Interval // e.g. ±6
settledness: "SETTLED" | "CONTESTED" | "STALE" | "BLIND"
derivedFrom: StatementRef[] // the evidence
policy: FusionPolicyRef // which fusion produced it
asOf: SystemTime
}
// ---- Act outcome: the honest union ------------------------------------
type ActOutcome =
| { kind: "Committed"; order: OrderToken; events: EventRef[] }
| { kind: "Denied"; reasons: PolicyReason[] }
| { kind: "Pending"; approval: ApprovalRef }
// ---- Capability: proof that policy was asked ---------------------------
type Capability<A extends ActionType> = Token // signed, scoped, attenuable,
// offline-verifiable (P14)

Notation: Stream<T> is an ordered, resumable subscription; every mutating method takes a Capability even where elided for brevity; every method is implicitly scoped by RealmId and, where meaningful, BranchId.


3. Tier-1 ports — contract, truth, and state

P0 · Ontology Registry — tier 1, upstream of everything

The declared reality itself: entity types, trait kinds and value types, actions, events, policies, capability vocabulary, fusion policies, retention classes, driver manifests, branch behavior. It is P0 because every other port’s behavior is parameterized by schema — P1’s record types, P4’s trait kinds, P23’s fusion policies, P18’s generated SDK all read from here.

interface OntologyRegistry {
current(realm: RealmId): OntologySnapshot
at(realm: RealmId, v: SchemaVersion): OntologySnapshot
// A schema change IS an Act — no privileged admin side channel.
propose(cap: Capability<SchemaChange>, change: SchemaChange): ActOutcome
checkCompatibility(change: SchemaChange): CompatReport
watch(realm: RealmId): Stream<SchemaEvent> // P18 & P8 subscribe
projectIR(realm: RealmId, v?: SchemaVersion): RealityIR
}
type CompatClass = "ADDITIVE" | "NARROWING" | "BREAKING"

Invariants: the trait-kind vocabulary (numeric · geo · temporal · graph-edge · categorical) is closed and kernel-owned; everything above it is open. propose writes to the SchemaLog (P2) and commits the new version transactionally via P1 — the registry is a client of the Act path, and so is any Ontology-Manager UI or schema-authoring agent: same door, author-blind. NARROWING changes require a migration plan; BREAKING requires an explicit epoch.

Adapters: Postgres (Lean and most deployments — schema volume is tiny, transactional integrity is what matters) · FoundationDB (only when co-located with a P1-on-FDB for single-transaction schema+state epochs). This port almost never needs a scale adapter; its load is trivial, its correctness is total.

Consideration: schema reads are on every hot path, so adapters must support an aggressively cached snapshot with watch-invalidation; the contract’s watch exists precisely so caches never poll.

SmartMarket example: onboarding Varun Beverages is a sequence of propose calls — defineEntityType("Distributor"), defineTrait("distributor.monthly_offtake", kind: numeric, valueType: Cases), defineAction("ReassignTerritory", capability: TerritoryOps). Each returns Committed, lands on the SchemaLog, and triggers projectIR → a regenerated TypeScript SDK. A new reality is instantiated without a deploy — which is the whole SmartMarket axis (schema plasticity) satisfied through the ordinary governed path.


P1 · Transactional State Store — tier 1, the Process plane

Where a decision becomes actual. Holds current typed records for fast authoritative reads and executes the commit that welds state-change and truth-record together.

interface StateStore {
txn<T>(realm: RealmId, branch: BranchId, f: (tx: Tx) => T): Promise<Committed<T>>
read(ref: EntityRef, opts?: { branch?: BranchId; consistency?: "strict" | "cached" }): Record
scan(index: IndexRef, range: Range, opts?): Stream<Record>
rebuild(from: TruthPlane): RebuildHandle // Serving-side wipe-and-rebuild
}
interface Tx {
get(ref: EntityRef): Record | null
put(ref: EntityRef, record: Record): void
del(ref: EntityRef): void
appendOutbox(fact: OutboxFact): void // SAME transaction — the invariant
orderToken(): OrderToken // minted at commit
}

Invariants: put + appendOutbox are atomic — this is the transactional outbox, the Process↔Truth seam, and the reason no dual-write exists anywhere in the system. The OrderToken minted here is the global commit order that the Truth plane inherits (Postgres: LSN-derived sequence; FDB: versionstamp). Geo and graph lookups are index mechanisms driven by trait kind: the store indexes an H3/S2 cell or an adjacency key because the schema says geo/graph-edge, never because it knows what a manhole is. Link-kind adjacency is double-entry: the forward and inverse keys land in the same txn (§27.1) — reverse traversal, referential actions, and inbound-cardinality checks are all reads against the inverse half.

AdapterProsConsProfile
Postgres + Citus + PostGISRichest geo on earth; universally operable; LSN ordering; outbox is a tableWrite-scale ceiling; sharding is real work at Jio scaleLean, Air-gap
FoundationDB + Record LayerSerializable ACID at scale; versionstamp = free global order; ordered keyspace serves graph/geo cells nativelyRecord Layer is a build investment; unusual ops profile; geo is cells-only (no OGC ops)Scale
TiKVRaft KV, simpler ops than FDBNo typed-record layer; you build morealt-Scale
CockroachDB / YugabyteDistributed SQL ergonomics; geo-partitioningHeavier; PostGIS-litealt-Scale

Considerations: the locked decision is Postgres first — for NetworkAccess, PostGIS is too useful to abandon early, and FDB graduates in only when write contention, sharding need, and team ops-readiness are all proven, not predicted. Cross-aggregate consistency is explicitly not this port’s job: one txn spans one aggregate; anything wider is a saga over P2 (the atomicity fork stands).

NetworkAccess example: completeWorkOrder(WO-4711) executes as one txn: read the work order, verify state machine, put the completed record + updated splice-closure inventory, appendOutbox(WorkOrderCompleted{...}), commit → OrderToken 0x81f3…. The technician’s app reads the completed state immediately (read-your-write from this plane); the rest of the company learns of it via Truth→Materialization, milliseconds later.


P2 · Truth Plane — the log family — tier 1

Not one log: a family of append-only logs with distinct retention, access markings, and replay semantics. Refined from the earlier single “effect log.”

type LogKind = "Decision" | "Statement" | "Call" | "Schema" | "Policy" | "Driver"
interface TruthLog {
append(kind: LogKind, fact: Fact, order: OrderToken): Ack // via outbox relay
consume(kind: LogKind, group: ConsumerGroup, from: Offset): Stream<Fact>
tail(kind: LogKind, filter?: Filter): Stream<Fact> // feeds Subscribe
archive(kind: LogKind, to: BlobStore): ArchivePolicy // tiered, immutable
replayRange(kind: LogKind, range: [Offset, Offset]): Stream<Fact>
}
LogCarriesReplayed?Retention posture
DecisionLogActs (with capability, actor, outcome)yes — the branch-replay sourceeffectively forever
CallLogboundary crossings + receiptsnever — factslong; audit-grade
StatementLogaudit-grade evidence onlyneverlong
SchemaLogontology changesyes (schema replay)forever
PolicyLogpolicy & grant changesyesforever
DriverLogconnector health, mapping failuresneveroperational

The critical routing rule: high-volume sensor assertions do not pass through here — they go to P4. The StatementLog holds only evidence that needs decision-grade audit (an operator’s manual override reading, a survey measurement backing a compliance claim). Where exactly that line sits — which Statements earn the log versus the time-series path — is a live fork, flagged in §8; the contract supports both routes so the line is policy, not plumbing.

AdapterProsConsProfile
RedpandaKafka API, one binary, tiered storage to P6licensing posture to check per dealScale, Air-gap
NATS JetStreamtiny footprint, simple, already in-houselower throughput ceiling; weaker ecosystemLean, edge
Kafkathe ecosystemJVM + ops weightalt-Scale
Pulsarnative tiering, multi-tenantoperationally complexniche

Trafficure example: a signal-timing change is an Act → DecisionLog. The Google speed feed is Asserts → P4, never here. The Call that pushed new timings to the city’s ATCS controller lands on the CallLog with its receipt. Three truths, three homes, one ordered spine for the parts that replay.


P3 · Lakehouse / Snapshot Store — tier 1

Canonical persisted history of the World plane’s tables plus the snapshot/clone machinery. Provides the mechanism for branching; the semantics of a branch are the kernel’s (see P23 and §5).

interface SnapshotStore {
write(table: TableRef, rows: RowSet): CommitId
merge(table: TableRef, keyed: RowSet): CommitId // upsert
snapshot(table: TableRef): SnapshotId // on every commit
readAsOf(table: TableRef, at: SnapshotId | SystemTime): Scan
clone(base: SnapshotId): CloneRef // copy-on-write
expire(policy: RetentionPolicy): void // horizon is policy
evolveSchema(table: TableRef, change: SchemaChange): void
}

Invariants: snapshots are system-time checkpoints — valid-time lives inside Statements/ResolvedValues, so honest as-of-the-world queries are bitemporal reads over content, not just snapshot picks. Snapshot expiry bounds cheap as-of range; past the horizon is P2 replay — the horizon is a declared retention class in P0, not a storage default.

AdapterProsConsProfile
Iceberg + Nessieopen format; snapshots free; catalog-level branch mechanism maps well under kernel branchesNessie is another service; must stay mechanism, not semanticsall profiles
Iceberg + Polarisgovernance-forward REST catalogbranching less centralalt
Delta Laketoolingless engine-openalt
Hudiupsert/CDC-optimizedecosystem narrowermutation-heavy niche

Consideration (locked): Nessie must not define what a branch is. A kernel branch = base snapshot pointer + statement overlay + branch-local act log + call stubs + merge policy; clone is one leg of that. If the branch concept ever becomes “a Nessie ref,” the kernel has leaked its most differentiating semantics into an adapter.

IT-ops example: before a Proxmox cluster migration, clone the site’s current-state snapshot; the migration is rehearsed as a branch (§6.3) and the clone costs metadata, not a copy of the datacenter.


P4 · Assert / Time-Series Store — tier 1

The high-volume declaration path: bitemporal, idempotent, off the decision spine.

interface AssertStore {
append(stmt: Statement): Ack // idempotent on (subject,predicate,validTime,provenance.source)
appendBatch(stmts: Statement[]): Ack
lastValue(subject: EntityRef, predicate: TraitRef, asOf?: ValidTime): Statement | null
window(subjects: EntitySet, predicate: TraitRef, w: Window, agg: Agg): Series
evidence(subject: EntityRef, predicate: TraitRef, range: TimeRange): Statement[] // feeds fusion
retention(traitClass: RetentionClass): void
}

Invariants: writes are gated on the cheap authorization question — is this source authorized over this trait (an authority lookup against P12/P13, not a full action-policy evaluation). Last-writer-wins per (subject, predicate, source); for cardinality-N link traits both the idempotence and LWW keys extend with the element target — (subject, predicate, target, source), statement-per-edge with polarity, never statement-per-set (§27.2). Conflict across sources is not resolved here — that is fusion’s job (P23/P8), and this store’s evidence method is what fusion reads. Both time axes are first-class columns.

AdapterProsConsProfile
ClickHousebillions of rows, windows, materialized views; doubles as OTel sinknot transactional; ops care at small scaleScale, Air-gap (and Lean when volume is real)
TimescaleDBPostgres-familiar; one less system in Leanceiling well below city-scale sensor loadLean (low volume)
Druid / Pinotsub-second servingheavy opsniche
QuestDBfastest ingest per nodesmall ecosystemedge/niche

Trafficure example: Google asserts road-882.speed = 42 @ 15:00:00 (arrives 15:00:02 — validTime ≠ systemTime, the bitemporal case), TomTom asserts 48, a camera-analytics driver asserts 30. Three idempotent rows, three sources, zero decision-log entries — and a fusion input set waiting for P23.


P23 · World Projection Store — tier 1, the World plane

The port that answers the question the earlier design never asked: what is a trait’s value when reality is contested, multi-sourced, and decaying? Never a naked scalar; always a ResolvedValue.

interface WorldStore {
resolve(subject: EntityRef, predicate: TraitRef,
opts?: { branch?: BranchId; asOf?: SystemTime }): ResolvedValue
entity(ref: EntityRef, opts?): ResolvedEntity // all traits resolved
putResolved(subject, predicate, rv: ResolvedValue): void // ONLY P8 writes here
scanBySettledness(realm: RealmId, s: Settledness): Stream<TraitInstance>
staleness(realm: RealmId, olderThan: Duration): Stream<TraitInstance> // STALE/BLIND detection
overlay(branch: BranchId): BranchOverlay // branch-local resolved deltas
rebuild(from: TruthPlane & AssertStore): RebuildHandle
}

Semantics: fusion policies are declared in P0, executed in P8, stored here — the law again (userland declares trust_weighted_speed_v3; the kernel runs it; the kernel never knows it’s about speed). settledness is a queryable kernel property: SETTLED (sources agree within policy tolerance), CONTESTED (they don’t), STALE (evidence older than the trait’s freshness class), BLIND (no evidence at all). An agent — or a signal-timing optimizer — checks settledness before acting on a number; that check is what makes autonomous action over fused reality honest rather than reckless. Branch overlays hold branch-local resolutions so a simulation fuses its own injected statements without touching canon.

Adapters are per-plane materializations of the same logical store: Postgres tables/materialized views (Lean) · FDB Record Layer for point-resolve + ClickHouse for resolved-history (Scale) · Iceberg tables (the analytical materialization all profiles share) · DuckDB (edge/in-branch). This port is the reason P1 and P3 stopped carrying semantic weight they were never contracted for.

Trafficure example (continuing P4’s): fusion under trust_weighted_speed_v3 yields road-882.speed → { value: 41, uncertainty: ±7, settledness: CONTESTED, derivedFrom: [google, tomtom, camera], policy: twsv3 }. The dashboard renders 41 with a contested badge; the signal-timing agent, seeing CONTESTED, requests fresher camera evidence instead of acting — behavior impossible when the world stored speed = 42.


4. Tier-1 ports — materialization, compute, and governance

P8 · Stream Materializer — tier 1, the Funnel role

interface Materializer {
register(p: ProjectionSpec): ProjectionHandle
// ProjectionSpec: consume(LogKind[] | AssertStream) → derive(P1 index | P23 | P4 rollup | P5)
checkpoint(h: ProjectionHandle): Offset
replayFrom(h: ProjectionHandle, o: Offset): void
rebuild(target: StoreRef): RebuildHandle // wipe-and-rebuild any Serving/World store
fusionRun(policy: FusionPolicyRef, scope: EntitySet): void // executes P0-declared fusion → P23
}

Invariants: deterministic and idempotent per projection (same input range ⇒ same output — required for rebuild to mean anything); checkpointed offsets; strictly separated from any query path (the Object-Storage V1→V2 lesson: the indexer and the reader never share a process or a scaling knob).

AdapterProsConsProfile
Custom Rust/Python consumerstrivial to reason about; no cluster; fastest startyou own checkpointing/backpressureLean — locked first choice
Flinkstateful, exactly-once, maturea full distributed-systems taxScale
ArroyoRust, SQL streaming, lightyoungeralt-Scale, Air-gap
RisingWavematerialized views in SQLa database with opinionsalt

Locked decision: custom materializers first; Flink graduates in when projection state (large joins, windows across millions of keys) outgrows hand-rolled code — a threshold you observe, not predict.


P9 · Function Sandbox — tier 1

interface Sandbox {
compile(source: Module): CompiledModule
instantiate(m: CompiledModule, verbs: VerbTable, limits: ResourceLimits): Instance
run(i: Instance, input: Bytes): Output
}
// VerbTable — the ONLY imports a module receives. There is no other world.
interface VerbTable {
query(q: Query): Result
act(cap: Capability, action: ActionInvocation): ActOutcome
assert(stmt: Statement): Ack
call(cap: DriverCapability, req: Intent): Receipt
subscribeAck(e: Event): void
schedule(t: TimerSpec): TimerRef
}

The contract is “no ambient authority, mechanized”: a module cannot open a socket, read an env var, or touch a file, because those imports do not exist. Prompt injection against an agent running here has nothing to inject into — the only expressible actions are governed ones.

AdapterProsConsRole
WASM (Wasmtime, Component Model)capability-clean by construction; ms cold-start; TS/Rust/Python targetsruntime maturity gaps (threads, some libs)default for functions & agent logic
Firecracker microVMarbitrary code, strong isolationheavier, slower start, needs egress disciplinedrivers & heavy jobs
gVisorcontainer-compatiblesyscall-coverage caveats; still ambient-ishalt for drivers
Trusted worker + strict seamzero new infraisolation is organizational, not mechanicalLean interim only, retired on schedule

The Lean interim is legitimate only with a retirement date: internal trusted workers whose every effect already crosses the seam, replaced by WASM before any customer- or agent-authored code runs.


P10 · Workflow Engine — tier 1

interface WorkflowEngine {
start(def: WorkflowRef, input: Bytes, opts: { branch?: BranchId }): RunId
signal(run: RunId, s: Signal): void
// activities are verb calls; ALL non-determinism lives in Calls,
// so replay = re-run orchestration + feed recorded Call receipts
history(run: RunId): Step[]
retryPolicy(def: WorkflowRef, p: RetryPolicy): void
}

The determinism contract matches the verb model exactly: Acts replay, Calls are fed from record — which is also precisely what durable-execution engines require, so the architecture and the engine constraint agree by construction. Adapters: DB-backed jobs / DBOS (Lean — most early workflows are simple) · Temporal (Scale — real signals/timers/sagas) · Restate (lighter durable execution, Air-gap-friendly).

NetworkAccess example: a fiber-cut restoration workflow — Subscribe(AlarmRaised)Query affected circuits → Act(createWorkOrder)Call(dispatch SMS via gateway) → wait signal(technicianAccepted) → … Every step a verb; a crash mid-flow resumes from history with the SMS Call served from its receipt, not re-sent.


P12–P15 · The authority stack — tier 1

Four ports, one acquire():

// P12 · ReBAC
interface RelationshipStore {
writeRel(r: Relation): void // (doc: RelObj, "owner", user)
check(s: SubjectRef, permission: string, r: ResourceRef): Decision
expand(r: ResourceRef, permission: string): SubjectSet
reverseLookup(s: SubjectRef, permission: string): ResourceSet
watch(pattern: RelPattern): Stream<RelChange>
}
// P13 · ABAC
interface PolicyDecision {
decide(p: Principal, a: ActionRef, r: ResourceRef, ctx: Context): { effect: "PERMIT"|"DENY"; reasons: Reason[] }
}
// P14 · Capability tokens
interface CapabilityMint {
mint(actor: ActorRef, action: ActionRef, resource: ResourceRef,
window: Duration, caveats: Caveat[]): Capability<any>
attenuate(c: Capability, extra: Caveat[]): Capability // sub-agent delegation
verify(c: Capability, ctx: Context): VerifyResult // OFFLINE-capable
}
// P15 · Identity
interface Identity {
authenticateHuman(oidc: OIDCAssertion): ActorRef
authenticateWorkload(svid: SPIFFEIdentity): ActorRef // agents live here
}

acquire(action, resource) at the seam = P15 authenticate → P12 check (relationship) → P13 decide (context) → P14 mint. invoke re-verifies the token and re-runs the fast context predicates — two touchpoints, deliberately, against TOCTOU. Attenuation is the multi-agent authority answer: capability shrinks monotonically down a delegation tree.

Adapters: SpiceDB (Scale) / OpenFGA (Lean) — custom ReBAC is rejected permanently, highest-blast-radius code, solved problem. Cedar for ABAC (formally analyzable; OPA acceptable where it’s already fleet-standard). Biscuit for tokens in every profile — offline verification is what makes air-gapped capability checks exist at all; short-lived signed JWTs are a Lean on-ramp only if attenuation isn’t yet needed. Keycloak/Zitadel + SPIFFE/SPIRE for identity — the workload half is non-optional, because agents are Actors and Actors must be attestable.

SmartMarket example: an analyst agent holds Capability<ReadSalesReality> attenuated to region = "North". It spawns a sub-agent for a drill-down and attenuates further to distributor ∈ {D-113…}. The sub-agent physically cannot query outside that set — not because its prompt says so, but because verify fails the caveat.


P16–P17 · The boundary — tier 1

// P16 · Egress — the Call chokepoint
interface Egress {
crossing(cap: DriverCapability, req: Intent): Receipt
// enforces which driver holds which external capability; rate-limits;
// writes the CallLog fact (request digest + receipt) unconditionally
}
// P17 · Driver contract
interface Driver {
manifest(): DriverManifest
emit(): Stream<Statement> // inbound streaming → Asserts, never Events
bulkLoad(job: BulkIngestSpec): BulkHandle // high-volume onboarding, bypasses per-row seam
actuate(cap: DriverCapability, i: Intent): Receipt
resolve(ext: ExternalRef): EntityRef // external ID ↔ entity mapping
health(): Stream<Statement> // → DriverLog
}
interface DriverManifest {
boundResourceClass: string
authority: "EXTERNAL_SOR" | "KERNEL_SOR" | "PEER_SOR"
direction: "EMIT" | "ACTUATE" | "EMIT_AND_ACTUATE"
actuationMode: "SYNC" | "ROUND_TRIP" // ROUND_TRIP ⇒ correlationId reconciliation
mapping: MappingRef // → P0: source schema → entity/trait binding
trustLevel: TrustLevel
rateLimits: RateSpec
credentialScope: CredentialRef // injected, never ambient
}
interface BulkIngestSpec {
source: DatasetRef // raw-landed staging table in P3
mapping: MappingRef // the P0-declared column→trait binding
validate: "reject" | "quarantine" // value-type constraint failures at admission
emitAs: "assert" // bulk lands as Asserts through P8, not the per-row seam
}

authority is the conflict-resolution key: EXTERNAL_SOR → the kernel mirrors, never overrides (Google’s speeds); KERNEL_SOR → writeback drives the external system (our inventory pushed to a legacy NMS); PEER_SOR → field-level ownership map, the genuinely hard case. ROUND_TRIP actuation submits an intent now and reconciles a later receipt (webhook → driver emit → correlationId match closes the loop) — the pattern that makes slow external systems honest.

Adapters: Egress — Envoy (Scale) / custom Rust proxy (Lean, Air-gap). Ingest — Debezium for DB CDC, custom driver SDK for everything bespoke (and for air-gap, where it’s the default).

IT-ops example: the Proxmox driver manifests as EXTERNAL_SOR / EMIT_AND_ACTUATE / ROUND_TRIP. It emits VM inventory as Asserts; a Call to create a VM returns Receipt{correlationId} immediately, and the VM’s actual appearance arrives later through emit, matched by correlation — at which point the World plane’s desired-vs-observed gap for that VM closes.

Data ingestion & staging — datasets as userland, not substrate

The Foundry instinct is to make datasets the substrate the ontology sits on. Here it is inverted: Statements are the substrate; a dataset is a high-volume Assert source. A pipeline ingesting SAP is a driver emitting Statements across the boundary — the same shape as a CCTV feed, just batched and schema-mapped. So no new plane and no dataset-management product; the pieces distribute across ports you already have:

  • Mapping (external schema → ontology) is a P0 artifact — a MappingRef binding source columns to typed Traits, versioned, changed by an Act. The same registry that projects the SDK drives ingestion mapping (the “HyperAuto” idea as declaration, not a bespoke tool).
  • Transformation pipelines (clean/join/enrich/derive) are P7 batch jobs, pure userland, reading raw-landed data and writing derived tables to P3. Raw and intermediate datasets are P3 lakehouse tables — a medallion (raw → cleaned → derived) — and are explicitly not World-plane truth; they are staging. Only the P8 materializer promotes validated rows into World, as Asserts.
  • Bulk vs streaming. A trickle of CDC changes is the streaming emit path. A 500M-row initial load must not go through the per-Assert seam row-by-row: it lands as a P3 dataset, is mapped and validated via P0, and emits Asserts in batch through P8 (bulkLoad). This is the difference between onboarding in hours vs weeks.
  • Validation rides the Assert admission path for free: a value the ontology’s value-type constraints forbid (negative speed, an out-of-enum status) is rejected or quarantined at the boundary (declarative constraints); effectful checks are P9 functions. Foundry’s dataset “health checks,” relocated to where types already live.
  • Lineage is not a subsystem — it is a query over the Truth plane. Every Statement carries derivedFrom + provenance; every ResolvedValue records its fused sources; trace derivedFrom backward and you have per-value lineage, finer than dataset-to-dataset flow, and inseparable from the security graph.

The governing rule — and the reason this stays clean: raw landed data is outside the governed universe until mapped. A messy half-mapped SAP dump sits in staging under coarse ingestion-level markings; it becomes reality only when the materializer turns validated rows into Asserts against typed entities. So it cannot leak into a dashboard, because it is not reality yet — it is raw material. This keeps the invariant intact: everything inside the seam is typed, resolved, and governed.

What we deliberately do not build: a closed dataset-management product with its own catalog, permissions, and transformation studio. The catalog is P0, permissions are the seam, transformations are P7 jobs. The moment datasets get a parallel security model, there are two answers to “who may see what” — exactly the fragmentation the kernel exists to kill.

NetworkAccess example: an operator’s legacy inventory (Oracle, 200 tables) onboards via bulkLoad — landed to P3, mapped in P0 to Cable/Joint/Splice entities, geometry validated against the geo kind at admission, emitted as Asserts under an EXTERNAL_SOR manifest so the kernel mirrors rather than overrides until the operator designates the kernel as SOR for a field.


P18–P19 · Contract & transport — tier 1

// P18 · SDK projection — the Conjure lesson, made dynamic
interface SDKProjector {
project(ir: RealityIR, target: "ts" | "python" | "rust"): SDKPackage
projectMCP(ir: RealityIR, scope: CapabilityScope): MCPManifest // agent tool surface
publish(pkg: SDKPackage, registry: RegistryRef, v: SemVer): void
diff(a: RealityIR, b: RealityIR): SDKChangeReport // drives semver
}
// RealityIR carries: entity/trait/value types, actions, events, policy vocabulary,
// capability types, driver manifests, fusion policies, retention classes, branch behavior.

The generated SDK is non-negotiable (locked): value types project as branded types with smart constructors, Actions as typed functions taking Capability parameters and returning ActOutcome, Events as handler payloads, the MCP manifest as the agent’s entire tool surface — so a hallucinated tool doesn’t fail at runtime, it fails to exist. The SDK remains the seam’s shadow: the kernel re-checks everything.

P19 transport: Connect/gRPC (one contract, browser + backend, streaming for Subscribe) — the pick in all profiles; plain REST/OpenAPI acceptable for low-stakes Lean clients. FastAPI-style hand-written APIs are rejected as the primary surface: they are precisely the hand-authored contract the projector exists to eliminate.


P21 · Deployment — tier 1 (it gates half the market)

interface Deployment {
publishDesiredState(env: EnvRef, bundle: SignedBundle): void // Sigstore-signed
reconcile(env: EnvRef): DriftReport // spoke pulls; never pushed
channels(): { STABLE: Criteria; CANARY: Criteria; RELEASE: Criteria }
transferOffline(bundle: SignedBundle, media: MediaRef): void // the air gap
}

Pull, not push: a hub computes desired state; per-site spoke controllers reconcile signed bundles — across a wire or across a courier. Adapters: Argo CD/Flux (connected) → Apollo-style hub/spoke with signed bundles (Scale + Air-gap). Provenance note: the hub/spoke pull model and signed-bundle air-gap transfer are documented Apollo patterns; finer details sometimes cited around it (e.g., fixed-interval node recycling) are inspiration from secondary sources, not verified design facts, and are treated as such.


5. Tier-2 ports — compact contracts

P5 · Searchindex(doc: EntityDocument) / search(q: SearchQuery): Hits / rebuild(from: P23). Derived, rebuildable, markings-filtered at the router (the index never becomes an authz bypass — read-path filtering applies after retrieval or via filtered indexes per marking). Adapters: Meilisearch/Typesense (Lean) · Quickwit (Scale/Air-gap — object-store-native) · OpenSearch (query-richness alt).

P6 · Blobput/get/list/presign immutable objects. MinIO (Lean/Air-gap) · S3 (SaaS) · Ceph (owned-storage on-prem).

P7 · Batch Transformsubmit(job: TransformSpec): JobHandle; dataset→dataset, idempotent, spatially capable; never merged with P8 (they graduate independently). DuckDB + Python workers (Lean) · Spark+Sedona or Daft (Scale) · DuckDB (edge/branch-local). Trafficure: the GNN feature-build over 90 days of fused speeds is a P7 job reading P3/P4, writing a feature table back to P3.

P11 · Analytical Querysql(q, opts: { asOf?, branch? }): ResultSet federated over P3 + external sources. DuckDB (Lean — embedded, covers most early load) · Trino (Scale — federation when customers demand cross-store SQL) · DataFusion (embeddable building block). Locked: Trino is not a day-one component.

P20 · Orchestrator — schedule/scale/secrets-inject services and sandboxes. K8s (Scale/Air-gap, hardened profile) · Nomad or plain K8s (Lean) · systemd (edge).

P22 · Observability — OTLP in, query out; audit is not here (audit falls out of P2). SigNoz (Lean/Air-gap) · OTel→ClickHouse→Grafana (Scale, reusing P4’s engine).

P24 · Visual Projection — tier 2 by dependency, specified at tier-1 depth

Tiles, tilesets, and rasters are Serving-plane projections of the World plane — derived, rebuildable, truth of nothing — built by the Materialization plane. The kernel stays blind to representation: color ramps, glTF bindings, and layer styling are meaning, declared in P0 as projection metadata on entity types (the Foundry move of hanging display config off object types), never kernel-known. Three scenarios lean hard on this port (Trafficure’s digital twin, NetworkAccess’s network map, SmartSignal’s coverage surfaces); SmartMarket uses its aggregate species; IT-ops barely exercises it — which is fine.

interface VisualProjection {
// -- serving (all pass the seam: these are Query specializations) --
tile(layer: LayerId, z: number, x: number, y: number,
ctx: PolicyCtx, opts?: { branch?: BranchId }): MVT
tileset(id: TilesetId, ctx: PolicyCtx,
opts?: { branch?: BranchId }): TilesetManifest // 3D Tiles root; traversal by SSE
raster(layer: LayerId, window: GeoWindow, ctx: PolicyCtx): COGSlice
liveChannel(layer: LayerId, ctx: PolicyCtx,
opts?: { branch?: BranchId }): Stream<TraitOverlay> // Subscribe-fed; carries ResolvedValue
// -- materialization side (only P8/P7 call these) --
invalidate(delta: GeometryDelta): DirtyTileKeys // computed per geometry-changing Act
bake(layer: LayerId, partition: MarkingPartition): BakeHandle // P7 batch job → PMTiles/3D Tiles
pin(tileset: TilesetId, snapshot: SnapshotId): PinnedTileset // released as-of baselines only
rebuild(from: WorldStore): RebuildHandle // the port-honesty guarantee
}

Invariant: featureId == entityId in every tile, tileset instance, and raster band index. A click in any client resolves to a governed Query on the ontology — the 3D scene is a view of the reality, never a parallel world. This single rule is what keeps visualization inside the seam.

The four species, one port:

SpeciesSourcePipelineServes
Geometry vector tilesP23 resolved geometrydynamic: Martin/pg_tileserv over P1/P23 · static: tippecanoe/Planetiler → PMTiles on P6roads, cables, parcels, buildings-2D
Aggregate tilesP4 via ClickHouseH3 hex-bin materialized views → MVT at query timetraffic density, market potential, alarm heatmaps
3D tilesetsP23 geometry + P6 meshesP7 batch: decimation → HLOD tree by geometric error → OGC 3D Tiles (glTF/b3dm) on P6city twins, plant/site models
RastersP7 outputsCOG on P6, served windowed via titilerRF coverage (SmartSignal), terrain, imagery
geometry-changing Act ──► P2 DecisionLog ──► P8 ──► P23 ──► invalidate() ──► dirty keys ──► re-bake/serve-dynamic
high-volume Asserts ──► P4 ───────────────────────────────► liveChannel() ──► client joins by entityId

The Act/Assert split predicts the tiling strategy — this is the port’s central design fact. Geometry changes by Act (a road re-laned, a cable rerouted: decisions, rare), trait values change by Assert (speeds, alarm states: declarations, torrential). Therefore: bake geometry into the pyramid; stream traits as a live overlay joined client-side by entityId. Invalidation subscribes to the DecisionLog, and because geometry-Acts are rare, computing dirty tile keys across zooms per Act is tractable. Asserts never touch a tile. The overlay carries the ResolvedValue, not a scalar — a CONTESTED speed renders visibly differently, which is fusion earning its keep in pixels.

Policy partitioning — the decision table. A pre-baked tile contains every feature in it; served raw, it is an authorization bypass (the region-scoped contractor downloads the whole fiber plant in one .pbf). Every layer must choose:

StrategyHowCostUse when
(a) Dynamic-filteredtiles rendered per request, policy predicate pushed into the tile queryCPU per request; correct alwaysfine-grained policy, low-zoom traffic modest
(b) Baked per marking partitionone pyramid per coarse marking (realm / region / classification band)storage × partitions; combinatorial explosion if markings are finecoarse, stable markings only
(c) Hybridbaked pyramid holds only coarse-marking-safe geometry; sensitive attributes and entities ride the dynamic layerboth, boundedthe default for regulated deployments

Branch visualization = canon pyramid + branch-diff overlay. A what-if branch never gets its own pyramid; it renders as canon tiles plus an overlay of exactly the features its Act log touched — which the branch-local DecisionLog yields for free. Toggling the intervention on/off over the same base city is the Trafficure demo moment.

Boundary honesty: Google Photorealistic 3D Tiles is a Call to a licensed external service — ToS forbids meaningful caching, so it is structurally SaaS/demo-only and cannot cross the air gap. The air-gapped base is named now, not discovered later: own 3D building data (SmartSignal’s footprints + heights) extruded or photogrammetry-tiled into self-hosted 3D Tiles, plus a Protomaps/OpenMapTiles planet extract as basemap. One codebase, two base-layer adapters — deployment-mode-behind-the-port again.

Locked considerations: CRS lives on the geo kind (traits stored CRS-tagged; per-city ENU tangent-plane projection is a client/edge concern, kernel-blind). Equipment renders as one glTF per equipment type with per-instance transforms (EXT_mesh_gpu_instancing / i3dm) — a million poles is one instanced mesh family with entityIds in the instance table. As-of visualization is bounded honestly: tilesets are pin()ed only for released snapshots (e.g. monthly network baselines); arbitrary as-of is served exclusively through dynamic small-extent queries — time-travel tiles are not pretended to be free. Client stacks (MapLibre, deck.gl, Three.js/R3F + Koota ECS) are pure userland consuming standard formats; the generated SDK grows a typed viz module whose layer descriptors bind entity types to tile sources, type-checked against the live reality.

Adapters: vector-dynamic Martin (Rust, fast, PostGIS-native) vs pg_tileserv (simpler, Go) · vector-static Planetiler (fast planet-scale bakes) vs tippecanoe (finer feature-drop control), both → PMTiles (single-file, range-request, air-gap-perfect) · raster titiler over COG (Lean through Air-gap) · 3D bake py3dtiles / custom Sedona→glTF pipelines (self-hosted) vs Cesium ion (managed, SaaS-only) · aggregate ClickHouse H3 materialized views, no dedicated tile server needed. Scale adds a CDN in front of (b)/(c) baked layers; Air-gap goes PMTiles-heavy with the self-hosted base.

Worked examples. Trafficure: road geometry bakes daily at most; speeds ride liveChannel at full Assert volume as ResolvedValues (a contested corridor renders hatched); the one-way what-if is canon + branch-diff overlay. NetworkAccess: strategy (c) — physical plant baked per regional marking partition; customer attachments and sensitive attributes dynamic-only; contractor’s client physically cannot fetch what policy forbids. SmartSignal: coverage surfaces are P7 outputs written as COGs, windowed via raster(); building 3D Tiles double as the air-gap base layer. SmartMarket: no geometry of its own — pure H3 aggregate tiles over customer-modeled measures, which is why the species split matters: a reality with zero drawn features still gets a full map product.


6. Request lifecycles

Act (the decision path):

SDK: ctx.for(wo).completeWorkOrder(input)
│ 1. P15 authenticate actor (human OIDC / agent SVID)
│ 2. acquire(): P12 check ─ P13 decide ─ P14 mint → Capability
│ 3. invoke(): P14 verify + fast context re-check (TOCTOU guard)
│ 4. Action logic runs in P9 sandbox → declared mutation intent
│ 5. P1 txn { put(state); appendOutbox(fact) } → OrderToken ← the weld
│ 6. read-your-write availabe NOW from P1
│ 7. outbox relay → P2 DecisionLog (ordered by the same token)
│ 8. P8 projections → P23 resolved state, P5 index, P3 canonical
└─ ActOutcome: Committed | Denied | Pending(approval)

Assert (the declaration path): driver emit / SDK assert.trait(...) → cheap source-authority gate → P4 bitemporal append (idempotent) → P8 fusionRun on affected (subject, predicate) → P23 putResolved → subscribers on derived views fire. Zero contact with the DecisionLog.

Call (the crossing, ROUND_TRIP): workflow call(cap, intent) → P16 enforces capability + rate limit → driver actuateReceipt{correlationId} → CallLog fact. Later, the external consequence arrives via emit as Statements carrying the same correlationId → reconciliation closes the in-flight intent. In any branch, this entire path is stubbed or served from the recorded receipt.

Branch (simulation):

branch.create("what-if-882-oneway")
= P3.clone(snapshot) (copy-on-write mechanism)
+ P23.overlay(branch) (branch-local resolutions)
+ branch-local DecisionLog (kernel-owned)
+ Call stubs (a sim never phones outside)
replay: Acts re-execute against the clone; Asserts read as-of or injected
as provenance:{kind:"simulated"}; fusion runs per-branch
merge: branch.diff(main) → PROPOSED real Acts → the ordinary governed
Act path on canon (merge grants no authority; it queues decisions)

The last line is the branch model’s integrity: merging a simulation does not write reality; it proposes Acts that then face policy like any other.


7. Four walkthroughs, end to end

7.1 Trafficure — contested speed to intervention. Google/TomTom/camera assert conflicting speeds on road-882 (P17→P4). Fusion (P0-declared, P8-run) resolves 41 ±7 CONTESTED into P23. The command-center dashboard (P18 SDK) renders the contested badge; a congestion workflow (P10) subscribed to a derived view proposes making 882 one-way. An analyst creates a branch, the intervention Act replays into it, the CTM simulation (P7 job over the branch via DuckDB) projects a 12% corridor improvement, branch.diff renders in the UI, and the merge proposes a real Act — which returns Pending(approval) for the traffic commissioner. Every plane touched, no store touched directly, the sim never called the ATCS.

7.2 NetworkAccess — work order at Jio scale. Technician’s app calls completeWorkOrder (§6 Act path verbatim). The interesting scale property: the read-your-write came from P1 at commit time, the org-wide dashboards read P23/P5 seconds later, and the monthly regulatory report reads P3 as-of month-end — three read paths, three freshness classes, one logical model. When write contention on Postgres becomes measurable, P1’s adapter graduates to FDB and nothing above this paragraph changes — that sentence is the ports model’s entire value.

7.3 IT-ops — drift and a governed migration. The Proxmox driver (EXTERNAL_SOR) emits VM inventory as Asserts; P23 holds observed state; desired state lives as kernel-owned Entities. A drift projection (P8) marks divergent VMs; remediation is proposed as Acts; approved ones become ROUND_TRIP Calls whose receipts reconcile by correlationId. The cluster migration is first a branch: clone, replay migration Acts, verify invariants over the branch with P11, then merge → a proposed, ordered runbook of real Calls. The kernel never pretends to own Proxmox’s truth; it owns the decisions about it.

7.4 SmartMarket — a reality in an afternoon. Onboarding = schema Acts (P0) → SchemaLog → projectIR → branded TypeScript SDK + MCP manifest published (P18). Ultra Tech’s connectors (P17, Debezium against their ERP) start emitting Asserts; fusion policies for their contested fields (distributor-reported vs ERP-reported offtake) are declared and P23 fills with resolved, settledness-tagged values. An analyst agent (P9 sandbox, P15 SVID, attenuated P14 capability) builds a territory dashboard against the generated tools. Nothing was deployed; a reality was declared, and the operating system grew a new typed surface around it.


8. Build sequence and open forks

MVP order (Lean profile, dependencies respected):

0. P0 Ontology Registry (Postgres) + trait-kind vocabulary
1. P1 Postgres+PostGIS with txn-outbox + OrderToken ← the weld
2. P2 NATS JetStream, DecisionLog + SchemaLog first
3. Seam v0: authenticate → acquire → Act path; P12 OpenFGA, P13 Cedar,
P14 short-lived signed tokens (Biscuit as the stated target)
4. P8 custom materializer → P23 on Postgres (ResolvedValue from day one,
even when every value is SETTLED — the shape must never be a scalar)
5. P4 (Timescale, or ClickHouse if Trafficure volume is immediate) + Assert path
6. P17 first two drivers (one EXTERNAL_SOR emit, one ROUND_TRIP actuate) + P16
7. P18 IR → TypeScript SDK + MCP manifest ← non-negotiable, early
8. P3 Iceberg/MinIO + snapshot discipline; then branch v0 (clone + overlay + stubs)
9. P10 DB-backed workflows; P9 WASM replacing trusted workers on a dated plan

Graduation to Scale is per-port and evidence-gated (P1→FDB on proven contention; P8→Flink on state complexity; P11→Trino on federation demand; P2→Redpanda on throughput) — observed thresholds, never aspiration.

Open forks (unchanged upstream + newly surfaced here): the Assert→Act promotion boundary; the cross-aggregate atomicity line (saga catalog); the trait-kinds closed set under all four scenarios’ graph shapes; StatementLog admission — which evidence earns audit-grade logging vs the P4-only path (surfaced in P2); PEER_SOR field-ownership semantics (surfaced in P17); fusion-policy expressiveness — declarative vocabulary vs sandboxed fusion functions, the declaration/effect seam inside fusion itself (surfaced in P23); the dynamic-vs-baked boundary per layer — whether the (a)/(b)/(c) choice is a static P0 declaration or adaptively re-decided from observed tile traffic and policy-grain metrics (surfaced in P24); the raw-vs-asserted boundary — exactly when landed staging data crosses from outside the governed universe to inside it, the ingestion analogue of Assert→Act (surfaced in the ingestion section).



9. The hot write path — Assert visibility at operational speed

The outbox solved read-your-write for Acts. For Asserts the earlier “cache the hot value” was a hand-wave; this is the design. The trap is coupling visibility to analytical durability — ClickHouse wants batches (seconds), Iceberg wants files (minutes); an operational tool cannot wait on either. So the Assert path is one ordered stream, three consumers at three speeds:

driver ─► gateway (authority check only, fast ack) ─► StatementStream (P2 topic)
├─► HOT · Last-Value Cache: per-source last values + incrementally-fused
│ ResolvedValue per (entity, trait) — milliseconds
├─► WARM · ClickHouse batcher: bitemporal history, windows — seconds
└─► COLD · Iceberg compactor: canonical / as-of — minutes

The Hot Value Cache (LVC) is the named new component (Lean: gateway-memory + Redis · Scale: FDB versionstamped upserts or Redis Cluster · Edge: in-process). It forces one deliberate constraint: fusion policies must be incrementally computable (weighted means, latest-wins, k-source votes — fine; full-history policies run only in WARM and publish their result forward to the LVC).

Freshness is declared, and lag is visible. Each trait’s P0 declaration carries a freshness class — hot(ms), warm(s), cold(min) — and only hot traits earn LVC entries. If a tier falls behind its class, the World plane marks the trait STALE: the SLA is not a dashboard, it is a queryable property an agent checks before acting. “Eventually in sync” is structural, not aspirational — all three tiers consume the same ordered stream, so they cannot diverge, only lag, and the lag is observable.

Read routing (final form): latest → LVC · windows/history → ClickHouse · as-of/canonical → Iceberg · point entity state → P1/P23. Per-source monotonic sequence numbers give gap detection (a hole becomes a DriverLog statement); idempotence is upsert-by-(source, seq), not broker transactions.


10. The Query IR — the read surface

The largest previously-unwritten kernel surface. The design: one kernel-owned Query IR, many userland syntaxes, many execution backends. Every read — SDK, GraphQL, SQL, MCP, tiles — compiles to the same logical plan, because that is the only place policy can be enforced once.

IR node taxonomy (closed, kernel-owned): Select(entityType, predicate) · Traverse(link|family|*, direction: out|in|both, depth|until) — the wildcard is admitted at depth 1: Traverse(*, in, 1) is the entity-360 / where-used read, served from the inverse adjacency index (§27.1) · Trace(upstream|downstream|path, until) — first-class because NetworkAccess lives on circuit traces; accepts a declared path (§27.5) or link family (§27.8) as its edge relation · Spatial(within|near|intersects, geom) (kind-driven) · Temporal(asOf | window | branch) · Aggregate(groupBy, measures) · Similar(embedding, k) · Project(traits, resolved|raw) — resolved is the default; raw evidence requires an elevated capability.

Policy is a rewrite pass, not a per-store feature. Markings and row-level rules are injected into the IR as predicates before the plan reaches any backend; trait-level denial becomes column masking in Project. One enforcement point, five backends, zero per-store leak paths. Query budgets (row caps, timeouts, scan cost) are Policy-set per principal class — agents get tighter budgets than dashboards.

Surfaces (all P18 projections): the typed SDK builder (primary); GraphQL generated per-reality from the ontology; SQL only as governed per-principal schemas — filtered views, never raw SQL (raw SQL is an IR bypass; blocked for agents by default, matching the MCP stance); MCP tools for agents; standing queries = Subscribe over an IR-defined view (the continuous-query case, served from WARM). openCypher is a possible later surface over Traverse/Trace — a syntax, not a new engine.


11. ML — training, serving, and predictions as citizens

Almost everything lands on existing machinery; the two genuinely new items are the port and the determinism split.

P25 · Model Inference (a specialized Call driver)infer(model, input, cap) → Completion and embed(content, cap) → Vector; non-deterministic, recorded to CallLog, never replayed. Adapters: vLLM/Triton/Ollama (self-hosted, air-gap), hosted LLM APIs (SaaS), LiteLLM/router. Model artifacts live in P6 under P0-registered manifests (version, signature, eval report, allowed realms); deploying a model is an Act.

The determinism split does real work: stochastic or hosted inference is a Call (stub-in-branch); small deterministic models — quantized ONNX scorers — compile into P9 WASM functions, making them replayable and therefore branch-safe: a simulation re-runs its congestion model freely but never re-phones an LLM. The reversibility boundary sorts ML automatically.

Features: offline = P3 tables built by P7; online feature serving = the §9 Hot Value Cache — not a separate feature store. Predictions re-enter reality as Asserts with provenance = model@version — fused, trust-weighted against observations, visible in derivedFrom; drift monitoring is a P7 job diffing model-asserted vs observed statements. Training is P7 on GPU node classes (P20). ML is governed for free because it was never special.


12. The business-process layer

The cut: the kernel owns durable execution (P10), triggers, timers, compensation-over-the-log, and the approval outcome (Pending(approval) on Acts). Userland owns process meaning — definitions, SLAs, escalation, assignment. Two principles now locked:

  1. Process-instance-as-entity. A running workflow (a PIMM construction project) is an Entity whose status Traits are updated by Acts as it progresses. Process state hidden inside the engine, invisible to Query, is forbidden — otherwise “all stalled projects in Maharashtra” cannot be answered by the same verb as everything else and the OS claim breaks.
  2. Human tasks are WorkItem entities completed by Acts — inboxes, field-app task lists, and agent-proposes/human-disposes flows are all just Queries and Acts. No parallel task subsystem.

BPMN, where a customer demands it, is a userland compiler into the workflow SDK — never a kernel adapter. DMN-style rules split along the existing seam: rules that gate are Policy; rules that compute are derivation functions.


13. Hardening the open flanks

13.1 Streaming semantics

Event time is validTime, arrival is systemTime — bitemporality is the late-data answer; a reading arriving 40s late lands at its true validTime and windows honor it up to a watermark declared per stream in the driver manifest (maxLateness). Beyond the watermark, late statements still land (bitemporal) but trigger window revisions, not silent rewrites — a revision is itself observable. Backpressure sheds by freshness class: hot is never shed; cold degrades first; overflow goes to a quarantine lane, never dropped silently. Backfill/replay re-emits from the P2 archive under a reprocessing flag so fusion and Subscribes can distinguish replay from live.

13.2 Authorization at scale

Budget: point check p99 < 5ms, list-filtering never per-row. Four mechanisms, layered:

  1. Two-tier enforcement: coarse markings (realm / region / classification band) compile to indexable IR predicates — cheap, applied to every plan; fine ReBAC checks run only on the candidate set that survives. Most rows never reach SpiceDB.
  2. Denormalized relationship closure (the Zanzibar “Leopard” lesson): flattened group-membership / ancestor indexes for the hot relations, maintained from the outbox — check becomes an index hit.
  3. List queries use LookupResources / precomputed accessible-ID sets or marking partitions (P24’s tile strategy generalized) — never N checks for N rows.
  4. Capability amortization: acquire pays the full evaluation once; invoke re-validates cheaply. Authorization data replicates per site; Biscuit verifies offline in air-gap.

Entity-level authority is granted through relationships to containers (project, region, org-node), not per-entity ACLs; direct per-entity grants are allowed but bounded and audited. Authority-bearing Traits (owner, custodian) materialize into relations via the same outbox that syncs SpiceDB.

13.3 Hierarchies — geography, organization, and their repercussions

Containment is a kernel-known link-kind (hierarchy, a graph-edge subtype) — the one structural fact the kernel must understand, because four mechanisms hang off it: transitive-closure indexes (materialized ancestor tables per hierarchy); policy inheritance (a grant on a node covers the subtree via ReBAC arrow relations — never copied grants); rollups (P23/ClickHouse pre-aggregation along declared hierarchies: zone → district → state); and subtree moves (a reorg is one Act; the closure reindexes; grants follow structure). Geography and organization are different hierarchies over the same entities, and permissions are typically their intersection (region × business unit). Two disciplines: H3 is indexing, admin boundaries are entities — never conflate the mechanism with the meaning; and boundaries are bitemporal — a redrawn district must not silently re-parent history, so as-of queries bind to the boundary version at their validTime.

13.4 Package management — realities as software

A Reality Package is a versioned, signed bundle: ontology fragment + value types + actions + policies + workflows + driver manifests + dashboards + fixtures. Semver; signed (cosign); dependencies declared against kinds/capabilities and resolved before install; install is a transaction of schema Acts with a P0 dry-run compatibility check — no side-channel installer. Upgrades classify per P0 change rules: additive = free; narrowing/breaking = requires a shipped migration job (P7). The registry lives on the Factory hub; air-gap installs reuse P21’s signed-bundle machinery. Our own products are packages — NetworkAccess is the kernel + a telecom reality package — which makes the packaging system dogfood, and makes customer- or agent-authored packages first-class citizens of the same pipeline rather than a second-class extension mechanism.

13.5 The scripting ladder

Three rungs, matched to three safety envelopes:

  1. Expressions — a pure, total, declarative language (CEL-class) for derived traits, validation predicates, fusion parameters. Kernel-evaluated; cannot loop, cannot effect; no sandbox needed.
  2. Scripts — sandboxed WASM (TS/Python) importing only the verbs; for action logic, glue, small automations. Shipped inline (governed by grant) or via package.
  3. Services — full SDK applications deployed outside the kernel, crossing the seam over transport. Plus a governed REPL/notebook: a session Actor carrying the user’s capabilities — the analyst’s and the agent’s scratchpad — where reads are IR queries and writes are still verbs. The ladder is the type-system seam again: declaration → sandboxed effect → deployed program.

13.6 Sandbox hardening (P9, concretely)

Wasmtime fuel/epoch interruption (CPU bounds) · per-instance memory caps · no ambient WASI clock or entropy — time is injected (branch-local time in simulations) and entropy is sealed-and-recorded so runs stay replayable · module compile cache + pooled instances for cold-start · per-invocation capability table injection (the only imports) · resource classes declared in the function manifest · verb budgets per actor (denial-of-wallet protection) enforced as Policy rate predicates at the seam.


14. The open-questions register

The living index of what is genuinely unresolved (absorbs and extends §8’s fork list). Each item names the question and the current leading answer, not a decision.

#QuestionCurrent lean
1Erasure vs immutability (DPDP/GDPR right-to-erasure against append-only Truth)Designed — §16 (per-subject DEKs, erasure-as-Act, rebuild-as-purge, legal holds). Open remainder: blind-index scope per deployment
2Tenancy isolation modelResolved — §26.4 (tenant owns realms; kernel invariants tier-independent; isolation as deployment tier)
3Branch merge semanticsDesigned — §15 (rebase model; write-set + precondition + policy-drift conflicts; opt-in strict reads). Open remainder: adjudication UX
4Entity resolution & identityULIDs + resolve() external refs (locked); cross-source conflation (Google’s road vs TomTom’s road) via sameAs statements + fusion across identities, resolver as P7 — semantics unproven at Trafficure scale
5Schema→instance migrationChange classes designed; lazy-vs-eager is GATED — trigger: first production breaking change (§26)
6Multi-region / DRGATED — trigger: first contract with an RPO/RTO clause (§26); log-replication primitive noted in P2
7Offline / edge syncDesigned — §22 (offline session = device micro-branch; reconnect = §15 merge). Remaining: adjudication UX (shared with §15)
8Quotas, metering, billingVerb metering per actor/package from DecisionLog + CallLog; agent budgets (verb + token) as Policy predicates; billing is a projection over the logs
9Kernel ABI versioningVerbs never break; IR and Reality-IR are versioned; SDKs semver with deprecation windows; the kernel’s own upgrade is a P21 bundle
10Notification fan-outUser-facing push/email/SMS is an ACTUATE driver consuming Subscribes — no kernel notification system
11Testing userlandGolden-fixture realms + branch-based test worlds + deterministic replay harness; a package’s CI runs its workflows in a branch
12Data residencyRealm-to-site pinning declared in P0, enforced by Factory placement
13(carried from §8)Resolved: Assert→Act promotion §26.1 · raw-vs-asserted §26.2 · StatementLog admission §26.3 · PEER_SOR §26.5 · (atomicity §18). GATED: fusion expressiveness (first inexpressible policy) · dynamic-vs-baked tiles (traffic metrics)
14Trait-kinds closed setStress-tested §19, parameterized §20. Link traversal semantics completed — §27 (inverse index, element granularity, referential actions, two-sided cardinality, declared paths); graph-representation completeness audited — §27.8 (hyperedges = reification; link families added; analytics boundary drawn). Interface evolution resolved — §26.6 (declared-and-verified conformance; required-trait additions = major version). Document-kind governance GATED (first SmartMarket onboarding)
15Surface spec depthHow expressive the declarative Surface language must be before the custom-widget escape hatch dominates (§17.1) — the classic low-code cliff
16Offline conflict UXRejected offline proposed-Acts: adjudication flow designed, field-worker experience not (§17.6)
17Presence & collaborationMulti-user co-editing signals (who is viewing/editing this entity) — P26 could carry it; deliberately deferred
G1Subscribe pattern grammar (A·1, SPEC)Designed — §24.1 (closed 4-form pattern language + combinators; rung-1 total)
G2WorkItem claim semantics (A·4, SPEC)Designed — §24.2 (kernel Lease primitive; unified with G4)
G3Offline = branch unification (A·6, UNIFY)Designed — §22. The offline queue is a micro-branch; reconnect is a §15 merge. One machine, not two
G4Semantic-lock leases (A·5, SPEC)Designed — §24.2 (same Lease mechanism; auto-release or escalate on lapse)
G5ROUND_TRIP timeout policy (A·8, SPEC)Designed — §24.3 (reconcile-before-retry; late-receipt adjudication)
G6Branch resource governance (B·4, GOV)Designed — §23.1 (branch classes + quota envelopes; archive-and-rehydrate expiry; sweeps as one grant)
G7Trust-weight feedback governance (B·8, GOV)Designed — §23.2 (manual/proposed/bounded-auto modes; fusion config made bitemporal)
G8Sim-time control surface (B·3, SPEC)Designed — §24.4 (clock ops are branch Acts — runs reproducible from the log)
G9Multi-branch comparison in the IR (B·5, SPEC)Designed — §24.5 (one Compare node; ranking stays userland)
C1PLAN branch class (journey C·2, SPEC)§23.1’s table needs a months-lived plan class — implemented as a logical branch (act log over a base pointer, like device branches), never a mandatory snapshot clone. Rule: branch machinery stays inside what Postgres/Iceberg do cheaply
C2Inter-tenant reality transfer (C·10)GATED — trigger: first genuinely inter-tenant contracting deal. In practice SmartBuild deploys as a NetworkAccess module for one customer → same realm → handover dissolves (lifecycle transition). The signed export/import mechanism stays sketched, not built
C3Plan-vs-evidence divergence (C·6, SPEC)§15’s conflict taxonomy is Act-vs-Act; plan branches also conflict with observed Asserts. Merge needs a declared divergence detector — change orders are exactly this adjudication
C4Contract-bound grants (C·3, GOV)Contractor capabilities should auto-revoke on contract lifecycle events; Biscuit time-caveats exist, the binding policy rule doesn’t
D1Virtual-read caching (§28, GOV)A TTL cache over delegated reads quietly recreates a warm mirror without statements — the honest line between cache and mirror is undrawn. GATED — trigger: first virtual deployment where delegated latency hurts
D2Identity-spine scale (§28)Spine materialization cost and refresh cadence for warehouse-scale virtual sources (100M+ rows) unproven. GATED — trigger: first warehouse-scale virtual mapping


15. Branch merge — the rebase model

Merge is replay-based, never state-diff based. Because Acts are semantic commands (not byte diffs), merging a branch means re-validating and re-applying the branch’s intent against the canon that exists now — a rebase, not a three-way file merge. This dissolves most of the classical merge problem, because Acts carry their own validations: an Act that no longer makes sense against advanced canon fails its own precondition, which is exactly what a conflict is.

merge(branch) →
1. WRITE-SET INTERSECTION A_branch × A_canon-since-fork → overlap report
2. DRY-RUN REBASE fork a merge-preview branch from canon HEAD;
replay branch Acts in order — validations run,
Policy runs AS OF NOW, fusion recomputes
3. MERGE PROPOSAL ordered proposed Acts + conflict report
+ World-level preview diff
4. ADJUDICATION per conflict: drop | adapt | override (capability-gated)
5. COMMIT proposed Acts apply to canon through the normal seam —
Pending(approval) outcomes apply as for any Act

Conflict taxonomy (kernel-detected, userland-resolved — the law again):

  • Overlap — canon and branch wrote the same (entity, trait). Mechanical: write-set intersection. For cardinality-N link traits the unit is the element — (entity, trait, target) — so two branches adding different edges to the same entity never spuriously conflict (§27.2); orderedN stays trait-granular by design, because concurrent re-orderings of one path are a real conflict.
  • Precondition failure — the branch Act’s validation fails on current canon (entity retired, status moved on).
  • Policy drift — Policy changed since fork; the Act would now be denied or newly requires approval. Merged Acts are policy-checked at merge time, never fork time — a branch is not a policy time capsule.
  • Read staleness (opt-in strict mode, per action type) — the Act read values that have since changed. Read-set tracking is expensive; default is write-set conflicts only, with strictReads declared per Action in P0 where serializability genuinely matters (e.g. financial adjudications).

Invariants: merge never bypasses the seam (merged Acts are real Acts); simulation-only artifacts — injected synthetic Asserts, stubbed Call facts — never merge; only Acts carry intent across. The merge-preview is itself a branch, so the machinery is self-hosting; periodic rebase without commit of a long-lived branch is the same pipeline stopped at step 3. Branch-of-branch forks from the branch snapshot with identical semantics.

Trafficure: the one-way study merges as one proposed Act (setDirection) — trivially clean unless canon re-laned the same street meanwhile, which surfaces as an overlap for a human to adjudicate. NetworkAccess: a change-control dry-run branch with 40 construction Acts rebases nightly; two conflicts (a joint retired in canon) surface as precondition failures and are adapted before the CAB commit.


16. Erasure — the crypto-shredding envelope

The DPDP/GDPR collision — right-to-erasure vs an append-only Truth plane — resolves through the architecture’s own rebuildability, and it must be day-one: the Statement envelope reserves the encryption wrapper from the first commit, even while keys are realm-coarse.

Mechanism. Value types carry an optional PII classification in P0: pii: subjectRef naming which entity is the data subject. For PII-bearing traits, the statement’s value payload is encrypted with a per-subject DEK before it lands anywhere durable (P2, P3, P4); envelope keys wrap DEKs under a realm KEK held in the key manager (OpenBao self-hosted / cloud KMS / HSM — an adapter behind a Keys sub-port of P14). Identifiers stay pseudonymous ULIDs in the clear, so ordering, lineage, and non-PII indexing are untouched.

Erasure is an Act (governed, approved, audited): destroy the subject’s DEK → the immutable history remains, as ciphertext no one can ever read → trigger rebuild of affected Serving/World projections, which is cheap because they were rebuildable by design — the erasure mechanism is the “truth of nothing” property doing legal work. ResolvedValues recompute without the shredded evidence; affected traits become BLIND or tombstoned. The audit trail records that erasure happened, never what was erased.

Consequences accepted: PII traits get restricted indexing (exact-match via HMAC blind index where operationally required; no full-text, no range); legal holds are a P0 retention class that pins a DEK against destruction until the hold lifts; key escrow/backup follows the realm KEK’s custody rules; branches inherit DEK access by capability, so a shredded subject is unreadable in every branch simultaneously.


17. The customer touchpoint surface — apps, realtime, protocols

The gap audit for the everyday product: what a field engineer, an operator, and a customer’s script actually touch daily. Five genuinely missing pieces, now specified.

17.1 Surfaces — declarative apps over the Reality IR

The founding requirement — dynamic apps on the fly, per-customer UI — lands as Surface definitions in P0: declarative layouts (pages, panels, forms, map layers, task lists) whose every binding is an IR query or an Action reference. Shells — a web shell, a mobile shell — interpret Surfaces; they ship once, realities ship Surfaces. A Surface is package content (§13.4), authored by us, customers, or agents, and validated against the ontology at install (a binding to a nonexistent trait is a compat failure, not a runtime blank). Escape hatch: custom widgets as sandboxed modules (P9-adjacent, verb-only imports) — never arbitrary script injection into the shell. Contract detail (archetype grammar, runtime, shells, capture path, decision records) lives in surface-platform.md.

17.2 P26 · Realtime Session Gateway

The generalization of P24’s liveChannel: a session-scoped fan-out tier. Contract: open(session) → resumable stream; sub(standing IR query | event pattern) → SubId with multiplexing (one socket, N subscriptions); server pushes diffs against the query result, not raw events; resume tokens survive reconnects (mobile networks are the norm, not the exception); per-session backpressure with freshness-class shedding (§13.1’s rule reused at the edge). Transport: WebSocket primary, SSE fallback, both under Connect streaming. Adapters: in-process fan-out (Lean) · dedicated gateway tier reading LVC + P2 (Scale) · same, site-local (air-gap).

17.3 Attachments & media — the missing kind

Field photos on work orders, splice diagrams, PDFs on projects — unmodeled until now. Resolution: a media trait kind joins the closed set (numeric · geo · temporal · graph-edge · categorical · media): the trait value is a governed reference {blobRef, contentType, digest, size} into P6; bytes move via seam-issued presigned upload/download URLs (short-lived, capability-derived), never through the verb payload path. Ingest pipeline (userland, P8-fed): virus scan → EXIF strip-or-extract (a field photo’s GPS can Assert the equipment’s observed location — media becoming evidence) → thumbnail derivatives as P24 raster-adjacent projections. PII classification (§16) applies to media traits; erasure shreds the blob DEK.

17.4 Outbound webhooks — customers’ scripts as first-class

“People write scripts against alerts” = a platform-shipped webhook driver (ACTUATE): customers register endpoints + event patterns (a governed Act); deliveries are HMAC-signed, retried with exponential backoff, dead-lettered visibly, and every delivery is a CallLog fact. Inbound customer automation is just the SDK/MCP surface — no separate “integration platform.”

17.5 Networking & protocol register

One table, so nothing is implicit:

ConcernDecision
Verb transportConnect (HTTP/2, gRPC-web compatible) — browser and backend, one contract
RealtimeWebSocket / SSE via P26, resumable
Tiles/3D/rasterHTTP + CDN for baked public partitions; range-requests for PMTiles; no CDN in air-gap — site-local cache tier instead
Human authOIDC (P15) → session → capability acquisition; refresh rotation; device registry for mobile; step-up auth for sensitive Acts
Service/agent authmTLS with SPIFFE SVIDs; agents never hold long-lived secrets
Enterprise edgeTLS everywhere, WAF at the gateway, per-tenant IP allowlists, private-link options for dedicated deployments
API versioningverbs stable; IR + Reality-IR versioned; SDK semver (§14.9)
CachingETags on entity Queries (version = ordering token); CDN only for coarse-marking baked artifacts — policy-filtered responses are never shared-cached
ExplainabilityExplain joins the IR node set: explain(entity, trait) returns the derivedFrom chain, fusion policy, and settledness — “why does it say 42” is a governed query, and the lineage UI is just a Surface over it
i18ndisplay names, units, locales are P0 projection metadata on value types; the kernel compares SI, shells render locale

17.6 Offline field client — superseded by §22 (offline = branch)

The mobile shell embeds a local store (SQLite): Surface-declared queries sync as read replicas with freshness stamps; writes queue as proposed Acts on-device, submitted through the seam on reconnect — the agent-proposes/human-disposes pattern reused for disconnection, so a rejected offline Act arrives back as an adjudication item, not silent data loss. Conflict UX remains open (register).



18. Cross-aggregate consistency — atomicity classes and the saga catalog

The outbox gives atomic state+record within one transaction. The undesigned part was everything wider. The design rests on one generative rule and one declaration.

The generative rule: an invariant that spans a Call can never be atomic. The boundary is irreversible, so any flow touching the external world is automatically saga-class — no judgment required, the verb decides. This is the fourth time the verb taxonomy has settled a physical-architecture question.

The declaration: every Action carries an atomicity class in P0.

ClassScopeMechanism
LOCAL (default)one entity + its owned sub-entitiesone P1 transaction
TRANSACTIONALmulti-entity, same realm, declared bounded write-setone P1 transaction (Postgres txn / FDB txn — both handle multi-entity within limits; the bound is declared so the kernel can colocate and refuse unbounded writes)
SAGAcross-realm, cross-shard, or any step involving a Callcompiled to a kernel-recognized saga

A SagaDefinition (P0) is an ordered list of steps — each an Act or a Call — where every step declares its compensation class:

  • REVERSIBLE — a compensating Act exists (release the reservation);
  • EXTERNALLY_COMPENSABLE — a compensating Call exists, best-effort and recorded (refund the charge);
  • FORWARD_ONLY — no compensation is possible (the trench is dug); failure spawns a human adjudication WorkItem.

Forcing the class per step is the honesty mechanism: a designer cannot wave at “we’ll roll back” when a step is physically forward-only. Execution is P10; the saga instance is a process-entity (§12) — status queryable, in-flight work visible. Intermediate visibility is a feature for an operational tool (the NOC wants to see in-flight provisioning); where an invariant needs mid-saga protection, the saga’s first step sets a semantic lock — a status trait like RESERVED — a domain lock, never a database lock held across steps. Retries are idempotent by (sagaId, stepId); compensation runs in reverse order; ROUND_TRIP Call steps complete via P17’s correlation machinery.

The saga catalog is package content. Each Reality Package ships its invariant catalog: every cross-entity invariant enumerated and classified (TRANSACTIONAL vs SAGA vs projection-lag-is-fine). Examples that set the pattern — NetworkAccess: splice creation atomically updates both fiber ends + the joint’s capacity (TRANSACTIONAL, write-set of 3); work-order completion → inventory decrement → billing event is a SAGA (billing crosses a realm). Trafficure: a signal-plan swap updates all phases of one junction atomically (TRANSACTIONAL); a corridor-wide retiming is a SAGA of per-junction Acts with REVERSIBLE compensations. IT-ops: VM provisioning is a SAGA whose middle step is a Call — by the generative rule, it was never going to be anything else. Rollups, search, aggregates are projections, not invariants; they lag, and that is not a consistency bug.


19. The trait-kinds stress test — the closed set, v1

The set was asserted closed at five and never tested. Running all four scenarios’ actual shapes through it broke it in three places — which is the test doing its job.

Finding 1 — text was missing entirely. Names, descriptions, field notes: not numeric, not categorical (unbounded), and requiring full-text index machinery. An embarrassing omission hiding in plain sight — every mock-up assumed it, no document declared it.

Finding 2 — vector is a kind, not a feature. SmartMarket similarity, semantic search, ML embeddings: a fixed-dimension float array is not expressible as any scalar kind, and it demands its own index machinery (ANN). vector(dim) is shape, not meaning — the kernel indexes it blind to whether it embeds a product or a road segment.

Finding 3 — document as a bounded escape hatch. SmartMarket’s model-on-the-fly reality needs attribute bags before fields earn typed modeling. A document (JSON) kind exists but is deliberately second-class: not fusable, not indexable except by declared path-extraction into typed traits, and flagged in package compat checks — with an explicit graduation story (paths promote to typed traits by additive schema Acts). The staging area inside the ontology, with pressure to leave it.

Finding 4 — graph-edge holds, but only with declared shape metadata. The scenarios’ graphs differ structurally, and the kernel must know three shape facts per edge class: directionality (undirected splice-connectivity vs directed depends-on), hierarchy membership (a declared acyclic edge class gets §13.3’s closure indexes and inheritance; the write path enforces acyclicity), and cyclicity (IT-ops dependency graphs cycle — Trace() must be cycle-safe, and hierarchy machinery must never be pointed at a cyclic class). Turn restrictions (a constraint over an edge pair) and circuits (ordered paths) are expressible as entities referencing edges — no new kind, and Trace() carries the traversal. Linear referencing — “the cut is at 1.2 km along the cable,” “the pothole at chainage 340 m” — is a value type composed of (edge-ref + numeric offset) with a composite index declared in P0; composite index declarations join P0’s contract. (The traversal semantics this finding asserted — reverse lookups, traces through reified edges — are mechanized in §27.)

The closed set, v1 (nine kinds), each earning its place by distinct index machinery:

KindIndex machinery
textfull-text (P5)
numericB-tree / range
categoricalhash / bitmap (booleans are categorical-2)
temporalrange + bitemporal
geoR-tree / H3 / S2
graph-edgeadjacency + (if hierarchy) closure
medianone — governed blob ref (§17.3)
vectorANN
documentnone — path-extraction only

The claim renews: this set is closed until a scenario produces a shape requiring index machinery none of the nine provide — the same falsifiable-test discipline as the verbs.



20. The type system, completed — parameterized kinds, interfaces, end-to-end consistency

Supersedes §19’s flat table: kinds are type constructors, and a constructor’s parameters are exactly what the kernel needs to choose storage representation, index machinery, and mechanical validation — still shape, never meaning. A parameter is either a literal the kernel interprets (f64, dim=768, cosine) or a reference into userland schema the kernel enforces opaquely (categorical(scheme), link(target)): the kernel checks the type-tag mechanically without knowing what a Cable is — the same declare/enforce/blind pattern as fusion policies.

The nine constructors (closed set, v2):

ConstructorParametersMachinery the parameters select
textshort | longFTS indexing default
numerici32 | i64 | f32 | f64 | decimal(p,s)width, exactness, range index — decimal is mandatory for money; §19’s flat numeric would have put billing on float64
categoricalscheme: SchemeRef, hierarchical?bitmap vs dictionary; hierarchical schemes join §13.3’s closure machinery (taxonomy rollups). Schemes are P0 objects — shared, evolvable by additive Acts. Booleans = categorical over the boolean scheme
temporalinstant | date | interval, resolutionrange + bitemporal index
geopoint | line | polygon | multi*, crsgeometry class picks the index: points → H3/S2 cells, lines/polygons → R-tree; CRS validated at admission
link (née graph-edge)target: EntityType | Interface, class: hierarchy(acyclic) | flow(directed) | peer(undirected), cardinality: 1 | N | orderedN, targetCardinality?: 1 | N, onTargetRetire?: restrict | detach | cascadedouble-entry adjacency (forward + inverse, §27.1); closure iff hierarchy; acyclicity enforced at write for hierarchy class; cycle-safe Trace() for flow; inbound cardinality and referential actions enforced from the inverse index (§27.3–27.4). §19’s shape-metadata finding absorbed as parameters; traversal semantics completed §27
mediacontentTypes?, maxSize?governed blob ref (§17.3)
vectordim, metric: cosine | l2 | dotANN index
documentschemaRef?, extractions: paths→typednone — path-extraction only; even the escape hatch declares its shape

Interfaces — the composability unlock. An interface is a userland-declared structural contract (Locatable = has a geo trait; Connectable = has peer links + capacity); entity types conform structurally, and P0 checks conformance mechanically. Links, IR queries, and Surfaces may target interfaces instead of concrete types — which is what lets a package’s generic map Surface bind Locatable and work in every reality, and splice logic target Connectable across cable generations. The kernel verifies conformance; it never knows what Locatable means. Link families are the edge-side analogue (§27.8): where an interface unions target types, a family unions link types (connectivity = {splicedTo, patchedTo, crossConnected}) — declared in P0, versioned, additive to extend — so traversals bind the family and survive new link types the same way Surfaces survive new entity types.

Three layers, finally explicit:

  1. Kind constructor — kernel, closed set of nine.
  2. Value type — userland: a constructor instantiation + semantic identity + declarative constraints + unit/display metadata. Speed = numeric(f32) & unit:"km/h" & range[0,300]. Unit is a value-type tag: branded SDK types make Speed+Distance a compile error; the seam checks value-type identity; the kernel never learns km/h.
  3. Trait — a named slot of a value type on an entity type, carrying freshness class, fusion policy, PII class, and index requests (incl. §19’s composite indexes).

End-to-end type consistency — the keystone rule: hand-written schema anywhere in the system is a defect. P0 is the single source of type truth; the Reality IR is its canonical serialization; everything else is generated — including storage DDL. Postgres columns, ClickHouse schemas, FDB record descriptors, and index definitions are projections of the parameterized kinds; no engineer writes CREATE TABLE for entity storage, so no site exists where a divergent type can enter. One P0 declaration manifests consistently as: storage column + index choice · seam payload validation (every wire value tagged with its value-type version, validated before commit) · branded SDK type · GraphQL type · MCP tool JSON-schema · Surface widget offer (a geo(point) trait auto-offers map widgets). Version skew is governed by the §14.5 migration classes: widening numeric(i32→i64) additive; narrowing = shipped migration job; scheme additions additive, removals breaking. An SDK pinned at IR vN against a kernel at vN+2 is compat-checked at the seam — never silently coerced.



21. The IR family — three intermediate representations, one discipline

The honest audit: we have been saying “IR” for three different things, only one of which is designed. Consolidating — the system has exactly three IRs, and one discipline covers them all: every IR is versioned, schema-checked against P0, produced and consumed only by machines — hand-writing any IR instance is a defect (§20’s keystone, extended from schema to every generated artifact).

IR-1 · Reality IR (the schema — feeds P18). The canonical serialization of a realm’s declared reality: kind-constructor instantiations, value types, entity types, interfaces, links, link families (§27.8), path declarations (§27.5), Actions (with atomicity class), Events, capability vocabulary, policy vocabulary, fusion policies, freshness/retention/PII classes, driver mappings, projection metadata. Consumers: SDK projector, GraphQL/MCP generators, storage-DDL generator, driver-mapping validator, Surface validator. Status: content list settled; the concrete format (a versioned JSON schema, Conjure-style) is an implementation task, not an open design.

IR-2 · Query IR (the reads — §10). The logical plan every read compiles to; the policy-injection point. Status: node taxonomy designed; G1 (Subscribe pattern grammar) and G9 (multi-branch comparison) are its two open extensions.

IR-3 · Surface IR (the apps — completes §17.1). The declarative application format, now specified to contract level. (Amended 2026-07-02: the flat layout-node list superseded by the archetype grammar from the UI Framework & Lexicon; shells, runtime, and decision records in surface-platform.md.) A Surface document is a tree of two archetype nodes plus layout primitives: a Workspace binds a collection query, a projection set (map · table · list · cards · board · timeline · chart — several live at once, sharing one focus), and a focus contract (its DetailCard); a Composition is a card canvas of Workspace queries at glance altitude; Page · Panel · Form · DetailCard remain layout/detail primitives, and TaskInbox is a Workspace preset over WorkItems. The dials (focus · altitude · time · layers) are shell view-state, never document content. Every data slot is an IR-2 query reference, every button is an Action reference (with its capability requirement visible), every map layer is a P24 layer descriptor, and every widget slot may name a sandboxed custom module (P9-class, verb-only imports). Three consequences make it real: (a) install-time validation — a Surface referencing a nonexistent trait or an Action the installing realm lacks is a package compat failure; (b) capability-aware rendering — the shell hides or disables Actions the session’s capabilities cannot acquire, computed from the same P0 vocabulary (no hand-coded “if admin” logic); (c) kind-driven widget offers — a geo(point) trait auto-offers map widgets, a categorical(hierarchical) offers a tree filter, a media offers a gallery: the parameterized kinds (§20) drive the palette. Surfaces are package content, diffable, agent-authorable, governed as schema Acts.

Everything else that looks like an IR is a projection of these three: MCP tool manifests and GraphQL schemas project from IR-1; tile layer configs from IR-1 + IR-3; the branded SDKs from IR-1 with IR-2 embedded as the query builder.


22. G3 resolved — offline is a branch

The journey walk’s unification finding, adopted: §17.6’s separate offline-adjudication flow is deleted. An offline session is a micro-branch, and reconnection is a §15 merge. One machine.

Mechanics. When a device goes offline (or preemptively, at sync), the shell opens an implicit device branch: base pointer = the device’s last sync token (its read-replica watermark), branch-local act log = the queued work. It is a logical branch — no analytical snapshot clone; the device’s synced replica already is its base state. Offline Acts append to the device log exactly as branch Acts; offline Asserts (the splice photo’s EXIF location) ride along as branch statements.

Reconnect = merge. The §15 pipeline runs verbatim: write-set intersection against canon-since-sync-token → dry-run rebase (validations and Policy run as of now — a permit revoked while Kavya was underground correctly blocks her queued Act) → clean steps auto-commit → conflicts become adjudication WorkItems routed by the same §12 machinery, to the field worker (“canon says this joint was retired at 03:40 — confirm your splice target”) or their supervisor per Policy.

What the unification buys. The offline conflict taxonomy is inherited, not invented — overlap, precondition failure, policy drift all apply verbatim; strictReads Actions get offline protection for free; the offline queue becomes inspectable with branch tooling (a supervisor can preview a crew’s pending work as a branch diff before they reconnect); and §14.7’s “conflict UX undesigned” collapses into §15’s single remaining “adjudication UX” item. One design surface where there were two.

One honest asymmetry. Device branches differ from sim branches in trust posture: they run on hardware we don’t control, so their Acts are always proposed-class regardless of the actor’s normal authority — the merge-time policy evaluation is the authority, never the device. (A sim branch’s Acts are similarly quarantined until merge; the symmetry holds — which is the deeper reason the unification is correct: a branch is precisely “Acts whose authority is deferred to merge time.”)



23. The GOV findings — governance rules for branches and learning loops

23.1 Branch resource governance (G6)

Branches get classes, declared in P0, each carrying its quota envelope:

ClassTypical actormaxCount / actorStorage budgetTTLCompute budget
interactivehuman engineerfewgenerousweeksper-realm pool
sweepagentmany, via one granttight aggregatehours–dayshard cap
device (§22)field device1 per devicereplica-sizedsessionn/a
merge-previewsystemephemeralminimalminutesminimal
testCIper-packageminimalruncapped

Quotas are Policy predicates evaluated at branch.create acquire; usage meters from branch metadata + DecisionLog. Sweeps are one governed requestsweep(paramSpace) → N branches under a single aggregate budget, not N create calls — which is also what makes G9’s comparison natural.

Expiry is cheap because a branch’s identity is its log. TTL lapse → read-only → grace → archive: the branch act-log is retained in P2 (tiny), the overlay and materializations are dropped. An archived branch rehydrates by replaying its log onto a fresh snapshot. Nothing is ever “deleted by quota” — it is compressed to its intent. An agent may fork forty cities; it may not keep forty cities materialized.

23.2 Trust-weight feedback governance (G7)

Fusion trust weights are P0 configuration, mutated only by an Act (updateFusionTrust), capability-gated to a per-realm steward. Drift jobs (P7) produce evidence — a TrustReport statement — and never write weights. Closing the loop has three modes, declared per fusion policy:

  • manual — steward reviews the TrustReport, issues the Act.
  • proposed — the drift job proposes the Act → Pending(approval): agents propose, humans dispose, again.
  • bounded-auto — self-tuning inside a declared envelope (±x% per window, hard floor/ceiling); any adjustment beyond the envelope demotes to a proposal. The honest middle: a learning system with a governed leash.

Locked consequence discovered here: fusion configuration is bitemporal. An as-of query must resolve values using the fusion policy and weights as of that time, or historical resolution silently rewrites what the system believed. Weight history rides the PolicyLog; Explain(trait, asOf) returns the weights that produced the belief. Without this, §7’s as-of guarantee was quietly false for fused traits.


24. The SPEC cluster — six contracts closed

24.1 Subscribe pattern grammar (G1)

A closed, declarative pattern language — rung 1 of the scripting ladder (total, non-Turing, kernel-evaluated) — so the kernel never grows a general CEP engine:

pattern := event(type, predicate) -- single match
| window(source, condition, duration) -- threshold / delta / count over streams
| sequence(p1 then p2 within t) -- temporal composition
| absence(p1 not-followed-by p2 within t) -- the alarm-never-cleared case
combinators: debounce(t) · throttle(rate) · latch(until condition)

Predicates reuse the value-type constraint vocabulary (§20). window compiles to WARM-tier standing queries; event to log filters; debounce/latch is what alarm flap-suppression is — the journey’s A·1 case falls out. Anything richer is a rung-2 script subscribing to simpler patterns. Closed until a journey produces a pattern none of the four forms express.

24.2 Leases — one mechanism, two applications (G2 + G4, unified)

A kernel Lease primitive: claim(target) → Lease{holder, expiry} (optimistic — succeeds iff unclaimed or lapsed), renew, release, steal (capability-gated, audited).

  • WorkItem claims (G2): completion Acts carry a valid-lease precondition, checked at the seam; P26 pushes claim-state diffs, so the second supervisor sees “claimed by Arjun” live.
  • Semantic locks (G4): a saga’s RESERVED trait carries a lease held by the sagaId; P10 heartbeats it. On lapse, per the saga definition: auto-release (run the reservation’s compensation) or escalate (steward WorkItem). A stalled saga self-heals or surfaces — never silently holds inventory forever.

24.3 ROUND_TRIP correlation policy (G5)

DriverManifest.correlation = { window, retry: {n, backoff}, onTimeout: reconcile-then(presume-failed | escalate) }. The load-bearing rule: timeout is uncertainty, not failure — reconcile before retrying. A non-idempotent external action (create the VM, charge the card) is never blindly re-issued; on window lapse the driver issues a status Call (“did it happen?”) and only then compensates or escalates. Receipts arriving after resolution land flagged late-receipt and open adjudication iff state diverged.

24.4 Sim-time control surface (G8)

clock(branch): set(rate) (0 = paused · 1 = realtime · N = accelerated) · step(Δt) (discrete, for deterministic runs — rate changes disallowed mid-step) · until(t). Branch Schedule streams fire on the branch clock; as-of Assert reads map through the clock origin. Clock operations are branch Acts — they land on the branch log, so a simulation run is fully reproducible from its log alone.

24.5 Multi-branch comparison (G9)

One new IR node, nothing more: Compare(branches[], plan, alignKeys) → a result table keyed by branch and aligned by entity/key. Ranking, diffing, and statistics are ordinary Aggregate nodes over the comparison table — userland composition, not kernel algebra. Cost is N× and G6 budgets apply. The explicit stance: the kernel fans out and aligns; judgment about which future is better stays above the seam.


25. Reality IR — the concrete format

Versioned JSON documents under a published meta-schema, canonically serialized (RFC 8785 / JCS). Canonical bytes → stable digests → content-addressable, signable — which package signing (§13.4) and air-gap bundles already require. JSON over protobuf because IR documents are review artifacts (ontology changes read as diffs in a PR); protobuf remains the transport (P19).

{ "irVersion": "1", "realm": "netaccess-jio", "ontologyVersion": "…ulid…",
"digest": "sha256-…", "imports": [{"package":"telecom-core","version":"2.1.0"}],
"declarations": [
{ "kind":"valueType","id":"01H…","name":"Speed","version":3,
"constructor":{"numeric":{"repr":"f32"}},
"constraints":{"range":[0,300]},"annotations":{"unit":"km/h","pii":null} },
{ "kind":"linkType","id":"01H…","name":"feeds","version":1,
"constructor":{"link":{"target":{"interface":"Connectable"},
"class":"flow","cardinality":"N"}} },
{ "kind":"actionType","id":"01H…","name":"completeSplice","version":2,
"input":{"…":""},"atomicity":{"transactional":{"maxWriteSet":3}},
"capability":"CompleteSplice","outcomes":["Committed","Denied","Pending"] }
] }

Rules that make it live: every declaration carries a stable ULID id and a version — renames keep the id (SDK regeneration maps old name → new); an ontologyVersion is a set of declaration versions; and the compat checker is a pure function over two IR documents, classifying every diff into the §14.5 migration classes (additive / narrowing / breaking) mechanically — no human judgment in the classification, only in what to do about breaking. Ontology-as-code is supported (IR docs in git, PR review), but authority is always P0’s log: a merged PR compiles to schema Acts; git is a mirror of governed history, never a side channel around it.



26. Register triage — resolving what blocks, gating what doesn’t

The discipline: every register item gets one of three classes. NOW = conceptual, load-bearing for the first commit — resolved below. GATED = resolvable only sensibly at a named trigger; deciding earlier is guessing. EVIDENCE = requires real load/data; deliberately open.

ClassItemsTrigger
NOWAssert→Act promotion · raw-vs-asserted boundary · StatementLog admission · tenancy model · PEER_SOR ownership · interface evolutionresolved in §26.1–26.6
GATEDmigration lazy-vs-eager (first breaking change) · fusion expressiveness (first inexpressible policy) · dynamic-vs-baked tiles (tile-traffic metrics exist) · Surface spec depth (NetworkAccess screen-corpus session) · multi-region DR (first RPO contract) · billing detail (commercialization) · document-kind governance (first SmartMarket onboarding) · adjudication & offline UX (field pilot) · blind-index scope (first regulated deployment)named per item
EVIDENCEentity conflation semantics at Trafficure scale · ABI deprecation windows · presence/collaborationreal data · real SDK consumers · deliberate deferral

26.1 Assert→Act promotion — the question dissolves

There is no promotion mechanism, because evidence and decisions never convert. The rule: acting on evidence is an Act; the evidence is cited, not promoted. Every Act carries basedOn: [statementRefs] — the justification field Explain already implied — so a decision made on a mirrored value records which statements it relied on, and the statements stay statements. The one genuine authority transition — an external SOR handing a field to us — is a manifest Act flipping authority on the driver mapping, after which writes to that field are Acts (writeback) rather than Asserts. Two rules, no machinery: evidence is cited; authority flips are governed manifest changes.

26.2 Raw-vs-asserted — the boundary event is the Assert emission

Firm: nothing without an entity identity and a statement envelope is reality. Staging tables (raw/cleaned datasets) sit under coarse ingestion markings, are not addressable by the Query IR (they have no entity identity), and cross into the governed universe at exactly one event — the materializer emitting an admitted Assert (mapped via P0, validated against kind constraints). The quarantine lane is staging; staging carries its own retention class.

26.3 StatementLog admission — evidentiary vs operational, mechanically tied to citation

Each trait’s P0 declaration carries an admission class: evidentiary (statements retained in the audit-grade StatementLog — surveyed locations, financial readings, compliance-feeding evidence) or operational (default — P4 time-series only, retention-classed, compacted). The closure that makes it mechanical rather than judgment-per-trait: if an Action’s basedOn schema cites trait X, the compat checker requires X to be evidentiary. Decisions may only cite evidence the system commits to keeping — enforced at package install, not by policy documents.

26.4 Tenancy — a tenant owns realms; isolation is a tier, not a redesign

Tenant = the commercial + security boundary (the org). Realm = a world boundary; a tenant owns many (per-city, per-environment, per-business-unit). Kernel invariants regardless of tier: realm id in every key and statement; cross-realm references only via explicit federation links; per-tenant KEKs (crypto isolation even when physically shared); verb budgets per tenant for noisy-neighbor control. Isolation tiers are then a deployment choice — shared (row/schema separation) → dedicated database → dedicated site (Factory-managed spoke) — swappable per tenant without touching the logical model, because the model never assumed co-tenancy anywhere.

26.5 PEER_SOR — ownership at trait granularity

The driver mapping carries an ownership map per mapped trait: KERNEL | EXTERNAL (PEER_SOR = the split case: we own status, they own location). Writes from the non-owner side are recorded but flagged nonauthoritative; fusion weights owner statements at full trust by default; divergence beyond declared tolerance raises a reconciliation WorkItem instead of silently averaging a fight between systems of record. Ownership changes are manifest Acts — the same governed transition as 26.1.

26.6 Interface evolution — declared-and-verified conformance

Refinement to §20: conformance is declared by the entity type and structurally verified by P0 — nominal + structural, not structural alone — precisely so that adding a trait for unrelated reasons never silently changes what an entity conforms to. Evolution rules, classified mechanically by the §25 compat checker: adding an optional trait to an interface = additive (minor); adding a required trait or narrowing = breaking = new interface major version. Conformance declarations target version ranges (Locatable@^1); packages keep working; migration = entity types adopt v2 via additive schema Acts, then dependents move their targets. Interface versioning is just declaration versioning — no new machinery.



§19 Finding 4 shape-tested the kind; §20 parameterized it. Neither tested the reads. Running the four scenarios’ actual traversal patterns through link-as-trait — starting from the pattern every scenario shares, fan-in (many entities of many types, each holding a typed link to one target) — held the model but exposed six unpinned semantics. Each resolution below completes link-as-trait rather than replacing it; the alternative, a separate edge primitive, would forfeit bitemporality, fusion, branch overlays, and policy masking, then have to rebuild all four.

27.1 The inbound index — reverse traversal is not optional

A link lives as a trait on its source; the target’s record carries nothing. Yet the hot reads are inbound: every DetailCard’s entity-360 (“everything referencing this cable”), every retire-impact check, IT-ops blast radius, and Trace(upstream) itself — the design promised upstream tracing without ever saying who pays for it. Resolution: link-kind indexing is double-entry. The same P1 transaction that writes a link element writes the forward key (realm, source, linkType) → target and the inverse key (realm, target) → (linkType, source) — target-first precisely so that “everything pointing at X” is one range scan across all link types and all source entity types. The inverse index funds four mechanisms: reverse traversal, referential integrity (27.3), inverse-cardinality enforcement (27.4), and Trace(upstream).

IR consequence: Traverse gains direction: out | in | both, and at depth 1 admits a link-type wildcard — Traverse(*, in, 1) is the entity-360 / where-used read. Parameters, not taxonomy growth.

The near-miss the stress test caught: statements are LWW per (subject, predicate, source) and merge detects overlap per (entity, trait). If a cardinality-N link trait’s value were the whole target set, then adding one splice rewrites the set, a 10k-dependent router rewrites 10k elements per change, and two branches adding different splices to the same closure conflict spuriously at merge — a field crew’s device branch would collide with any canon topology change on that closure. Resolution: for cardinality-N links, the statement unit is the element. The link kind’s value shape is (target, polarity: asserted | retracted) — polarity lives in the kind’s value, the Statement envelope is untouched. The set is the union of live elements; LWW keys extend with the target — (subject, predicate, target, source); merge overlap detects per (entity, trait, target); retraction is a first-class statement, so every edge has a reconstructible bitemporal existence interval.

Fusion follows the same grain: settledness resolves per edge. Designed topology arrives as Acts, discovered topology (network scanners, CMDB sync) as driver Asserts, and where they disagree the edge is CONTESTED — as-built-vs-as-designed reconciliation is the fusion machinery earning its keep on structure, not a special subsystem.

Two consequences come with the discipline:

  • Parallel edges don’t exist in unattributed links. Element identity is the target; wanting multiplicity means the edges are distinguishable; distinguishable means attributed; attributed means reified (27.5). A set, not a bag — by construction.
  • orderedN is the exception: whole-value LWW, trait-granular conflict. Ordering is a property of the whole path; a circuit re-route is one intent. Two branches editing the same circuit should adjudicate — that conflict is correct, not spurious.

27.3 Referential integrity — onTargetRetire, enforced from the inverse index

The constructor gains onTargetRetire: restrict | detach | cascade (default restrict). Retiring an entity with live inbound restrict links fails the retiring Act’s own precondition — an inverse range scan inside the same txn. detach retracts the inbound edges as effects of the same Act. cascade retires the sources, bounded by the Action’s atomicity class (§18): a cascade exceeding maxWriteSet doesn’t get a silently bigger transaction, it graduates to a declared saga. Bitemporal honesty: the check governs canon now; as-of reads legitimately see edges to entities retired later — both were true then.

27.4 Cardinality is two-sided

cardinality constrains the outbound side only; “a port accepts at most one fiber” is an inbound constraint. The constructor gains targetCardinality?: 1 | N (default N), enforced at write via the inverse index. The classic 1:1 termination is cardinality: 1, targetCardinality: 1 — declarative, kernel-checked, meaning-blind.

27.5 Attributed relationships reify — and declared paths keep traces one hop

§19 Finding 4 said circuits and turn restrictions reify as entities “and Trace() carries the traversal” — asserted, never mechanized. In NetworkAccess the attributed relationship is the common case (splices carry loss dB, ports carry assignments), so every physical hop is strand → splice → strand: two edges per logical hop, on the exact workload the product lives on. Resolution: P0 gains a path declaration — a named composition of (linkType, direction) steps, type-checked mechanically from existing declarations (each step’s source type must match the previous step’s target type — shape, never meaning):

fiberPath = ⟨splice.from, in⟩ · ⟨splice.to, out⟩

Trace() accepts a declared path as its edge relation. And symmetric with hierarchy→closure: a path declared hot earns a derived adjacency index — direct strand→strand keys maintained by P8 from the outbox — so a circuit trace costs one range scan per logical hop despite reification. The pattern generalizes: declared structure buys maintained index (hierarchy → closure table; hot path → derived adjacency).

27.6 Boundaries and load

  • Realms. Traverse/Trace never silently cross a realm. A traversal reaching a federation link (§26.4) stops and reports the frontier unless the plan carries a capability for the peer realm.
  • Time. Adjacency, closure, and derived-path indexes are current-state Serving artifacts. Temporal(asOf) + Traverse routes to canonical (P3) — correct and slower, the same bounded honesty as P24’s as-of tiles; closures may be pinned for released baselines.
  • Degree. Fan-in is unbounded. Resolved-entity reads never inline unbounded link sets — link traits project as paged refs plus a degree counter maintained by P8, so SmartMarket’s “how many outlets does this distributor serve” is a point read and every supernode is quantified before anyone traverses it.
  • DAGs. hierarchy + cardinality: 1 = tree (cheap closure); + N = DAG (the BOM case) — closure machinery holds at higher maintenance cost; declared, therefore costed.

27.7 The scenario sweep

ScenarioTraversal patternMachinery
NetworkAccesscircuit trace through attributed splices/portsdeclared path + derived adjacency (27.5)
NetworkAccess”can I retire this pole?“inbound scan + onTargetRetire (27.1, 27.3)
NetworkAccess1:1 fiber↔port terminationtargetCardinality (27.4)
NetworkAccessas-built vs as-designed topologyper-element fusion, CONTESTED edges (27.2)
Trafficureturn restrictions over edge pairsreified entity (§19 F4, unchanged)
TrafficuresameAs conflation claimspeer links + per-element fusion (27.2)
IT-opsblast radius over cyclic depends-onTrace(upstream) on the inverse index, cycle-safe (27.1)
SmartMarketdistributor ↔ 5,000 outlets, one reassignmentelement-granular write + degree counter (27.2, 27.6)
all fourentity-360 DetailCardTraverse(*, in, 1) (27.1)

27.8 The representation audit — “reality is a graph,” checked construct by construct

The premise deserves a completeness check, not a vibe: if the model at the heart is a graph, every construct the graph-modeling literature has found necessary — property graphs, RDF/OWL, hypergraphs, temporal and uncertain graphs — must map to a kernel mechanism or be an explicit non-goal. The audit:

Graph constructKernel mechanism
Typed nodesentity types + interfaces (§26.6) — richness by composition, never subtype trees
Node propertiestraits — bitemporal, provenanced, fused, policy-masked: strictly richer than LPG properties
Typed edges, directed & undirectedlink classes: flow / peer / hierarchy (§20)
Edge propertiesreified relationship entities + declared paths (27.5)
Parallel edgesreification, forced by element identity (27.2)
N-ary relations / hyperedgesthe same reification: an entity holding N links is a hyperedge — turn restrictions (2-ary over edges), a splice tray joining 12 strands, a work-order assignment (crew × asset × permit). No new kind; the mechanism was already load-bearing
Ordered pathsorderedN (27.2)
Trees, DAGs, containmenthierarchy + closure (§13.3, 27.6)
Cyclic graphsflow + cycle-safe Trace
Inverse properties (OWL inverseOf)subsumed by double-entry adjacency (27.1) — every link is queryable in both directions; nothing to declare
Symmetric relationspeer class
Transitive relationsclosure for hierarchies; general rule-derived edges are derivation functions (§13.5) whose outputs re-enter as statements with provenance: derivation
Identity / sameAsconflation statements + fusion across identities (register #4)
Uncertain / contested edgesper-element fusion + settledness (27.2) — a graph whose edges carry CONTESTED honestly, which no mainstream graph store does
Temporal graphsbitemporal existence intervals per edge; as-of traversal (27.6)
Spatial graphsgeo kind + linear referencing (§19 F4)
Statements about statementsthe Statement envelope itself — provenance, confidence, derivedFrom, basedOn: RDF reification without the pain
Named subgraphsentities referencing edges (circuits); alternative worlds are branches; partitions are realms
Path-scoped aggregatesIR composition — Aggregate over Trace (“total insertion loss along this circuit” is a plan, not a feature)
Graph embeddingsvector kind; graph-ML predictions re-enter as Asserts (§11)

Two constructs the audit found genuinely missing, now added:

Link families — the union the traces actually need. A real circuit crosses heterogeneous connectivity types — splicedTo, patchedTo, crossConnected — and enumerating them per query is brittle across package upgrades. A link family is a P0-declared, versioned, named set of link types (connectivity = {splicedTo, patchedTo, crossConnected}); Traverse, Trace, and path steps accept a family wherever a link type is expected. It is the link-side analogue of an interface — interfaces union target types, families union edge types — and packages extend a family additively (a new cable generation’s link type joins connectivity without touching any existing query).

Cardinality bounds, disambiguated. cardinality: 1 is an upper bound (at most one). Required-ness — “every port belongs to a device” — is min-cardinality, and it lives where the seam already put it: the declarative constraint vocabulary (min/max, enum, regex, cardinality), checked at write. Both bounds declarative, both kernel-enforced, no new machinery.

And one boundary drawn so the closed taxonomy stays honest: graph analytics is a workload the kernel feeds, never a feature it hides. Motif/pattern matching beyond path traversal, weighted shortest-path, centrality, community detection are not IR nodes and will not become IR nodes — they run as P7 compute over P3 projections (or specialized engines mounted as read adapters, the Trino pattern), and their results re-enter as derived statements. Trafficure routing is the worked case: OSRM/Valhalla-class engines are userland consumers of projections, producing derived travel-time traits — governed on the way back in, like every other derivation. The kernel is a graph data model with OLTP traversal machinery; it is not, and should never pretend to be, a graph analytics engine.

The §19 claim renews once more: this machinery is closed until a scenario produces a construct or a traversal none of these mechanisms serve — the same falsifiable-test discipline as the kinds and the verbs.


28. The connector surface — capability descriptors, serving postures, and the virtual boundary

The Query IR’s pipeline (§10) routes plans over physical leaves — some kernel-owned (P1, P4, P3, P23, P5, the LVC), some external (a customer’s warehouse, a legacy Oracle, a lakehouse in place). The rule that keeps the planner honest: the planner routes by declared capability, never by brand. Every leaf — internal backend or external source — presents the same two declarations: a capability descriptor (what it can execute) and a serving posture (when its data is fetched). Internal and external differ in trust and freshness, not in contract shape.

28.1 The capability descriptor

interface ConnectorCapability {
tier: "F0" | "F1" | "F2" | "F3" // coarse floor — computed from the flags,
// declared for legibility, verified at install
pushdown: {
predicates: PredicateClass[] // which value-type constraint predicates it evaluates
projection: boolean
aggregates: AggClass[] // count | sum | minmax | percentile | none
joins: "none" | "colocated" | "full"
spatial: SpatialClass[] // within | near | intersects (geo kind)
temporal: { asOf: boolean; windows: boolean }
text: boolean // FTS (text kind)
vector: { ann: boolean; filteredAnn: boolean }
}
latency: "sub-ms" | "ms" | "sub-s" | "batch"
freshness: "hot" | "warm" | "cold" | "delegated"
ordering: "ordertoken" | "snapshot" | "best-effort"
estimate(scan: ScanSpec): CostEstimate // rows, bytes, latency, monetary — feeds OPTIMIZE and ACCOUNT
limits: { maxRows?: number; maxConcurrency?: number; rate?: RateSpec }
}
TierCan executePlanner treatmentExamples
F0whole relational subplans (filter + project + join + aggregate)push the fragment, stream results back as ArrowP1 Postgres · ClickHouse · Iceberg-via-DuckDB · Snowflake/BigQuery (delegated)
F1filtered/projected scans, plus one specialty (FTS, ANN, spatial)push predicates + projection; kernel does joins/aggregatesMeilisearch/Quickwit · ANN store · plain JDBC (delegated)
F2key or key-batch lookups onlysemi-join by entity-ID batches — never scannedLVC · REST/SaaS get-by-key drivers
F3nothing — emit-onlyvirtual reads refused at plan time (compat error, not runtime failure)Kafka/MQTT/OPC-UA feeds · webhook-style SaaS sources

Consumption rules, restating §10’s pipeline: ROUTE eliminates leaves by freshness × Temporal node; OPTIMIZE places fragments by pushdown flags and orders anchors by estimate(); plan validation enforces the residual-predicate discipline — every policy predicate either pushes down or is evaluated kernel-side, and a plan with a predicate that has no evaluation site is invalid, not slow. For delegated leaves the discipline doubles: policy predicates push down as reduction only and are re-evaluated on every returned row — the rows are in hand, the re-check is cheap, and an external engine is never trusted as a policy enforcement point.

28.2 Serving posture — when data is fetched

DriverManifest (P17) gains one field; the mapping gains a per-trait refinement:

serving: "MATERIALIZED" | "VIRTUAL" | "HYBRID"
// HYBRID: MappingRef declares per trait — serve: "materialize" | "delegate"

MATERIALIZED is the existing path: emit/CDC/bulkLoad → staging → admitted Asserts (§4, §26.2). VIRTUAL delegates trait reads to the source at query time through a federated leaf subplan. HYBRID splits per trait — hot traits ingest, the long tail delegates.

Delegated values carry the fourth freshness posture, delegated, with consequences that are constraints, not features to add later: no fusion (a single live source; a trait needing fusion must graduate), no bitemporal history (as-of over a delegated trait is a plan-time error), settledness limited to STALE-on-unreachable, and Explain returns the source, the pushed fragment digest, and fetch time instead of a derivedFrom chain. A delegated read synthesizes an ephemeral Statement (provenance {kind:"driver"}) that is never durable — it is a read, not a record. The closure with §26.3 is mechanical and load-bearing: evidentiary traits require durable statements → delegated traits cannot be evidentiary → an Action’s basedOn can never cite a delegated trait. Decisions cannot rest on evidence the system does not keep; the compat checker enforces it, and the forced graduation is the honest funnel: connect virtually in an afternoon, graduate the traits you act on. Graduation is a manifest Act flipping serve per trait — the same governed transition as §26.1’s authority flip.

28.3 The two grades of virtual — identity is never delegated

§26.2’s law — nothing without an entity identity and a statement envelope is reality — splits virtualization into two grades:

  • Entity-grade virtual. The identity spine always materializes, even when every value delegates: entity id (minted deterministically from the mapping’s declared source key — resolve() made pure), entity type and interface conformances, link traits, and every trait referenced by a marking predicate (§13.2’s indexable-markings rule cannot hold against a leaf we don’t control). Link traits never delegate — double-entry adjacency (§27.1) cannot be maintained against a source the kernel doesn’t own. Spine sync is an ordinary P8 projection over the source’s keys. Consequence: pure VIRTUAL does not exist at entity grade — VIRTUAL is HYBRID with the minimum spine. A query anchoring on a delegated trait (spatial, ANN, FTS) requires either pushdown support at the leaf or spine-materialization of that trait — checked at install, failed as a compat error.
  • Dataset-grade virtual. Attached tables with no entity identity: reachable only through P11’s governed per-principal SQL views, never addressable by the Query IR. This is where a dataset-world engine (Trino/Calcite-class) legitimately lives — below the seam, as one F0 delegate that ROUTE may hand relational fragments to. It never becomes a query surface of its own.

28.4 Boundary honesty for virtual reads

A delegated read is a boundary crossing, and P16’s unconditional-CallLog rule meets query-rate reality by logging at plan granularity, not row granularity: one CallLog fact per plan execution per virtual source, carrying the pushed-fragment digest, row/byte counts, and correlation to the query. Credentials are credentialScope-injected per manifest, never ambient. ACCOUNT (§10 budgets) gains the descriptor’s monetary dimension — a warehouse scan costs real money, and an agent’s budget says so before execution, not on the invoice.

28.5 Target families — the connective tissue, named

FamilyRepresentative targetsPostureWire
Enterprise OLTP / SoROracle, SQL Server, DB2, MySQL, Postgres, SAPMATERIALIZED (CDC + bulkLoad)Debezium · JDBC
Cloud warehousesSnowflake, BigQuery, Redshift, DatabricksVIRTUAL-first (F0)ADBC / Arrow Flight SQL preferred, JDBC bridge
Lakehouse in placeIceberg/Delta/Hudi catalogs, Parquet/GeoParquet on object storesVIRTUAL, zero-copy (F0)Iceberg REST catalog · direct Arrow scan
Streaming / telemetryKafka, Kinesis, MQTT, OPC-UA, NMS/EMS counters, PI historiansF3 emit-only → P4driver SDK
NoSQL / documentMongoDB, Cassandra, DynamoDBMATERIALIZED → document kind + path extractiondriver SDK / CDC
Geospatial estatesPostGIS, File-GDB, WFS/ArcGIS RESTMATERIALIZED (geo-validated); WFS reference layers may delegateGDAL-class ingest
SaaS / business APIsSalesforce, ServiceNow, SAP OData, JiraMATERIALIZED via Airbyte-protocol worker (the long tail); F2 get-by-key where live reads matterAirbyte protocol · REST
Graph storesNeo4j-classMATERIALIZED as link traits — traversals never federatedriver SDK

Worked examples. SmartMarket: Ultra Tech’s Snowflake attaches VIRTUAL on day one — the analyst agent queries entities that afternoon, delegated badge visible; when distributor-reported vs ERP-reported offtake needs fusion, monthly_offtake graduates to materialized by one manifest Act. NetworkAccess: the legacy Oracle inventory runs HYBRID through migration — identity, geometry, and splice links materialized (the map and Trace() need them), the 180-column attribute tail delegated until cutover, then flipped table-by-table under §26.5’s ownership map.


Companion documents: the-seam.md (physics), ports-and-adapters.md (architecture contract), hld-historical.md (superseded reference stack), vinxi-kernel-board.html (interactive board).