RFC-0001: Canonical Ontology
Purpose
Define what must be known about a real-world entity before authoritative claims are permitted.
This RFC implements Doctrine II: Identity Authority — the principle that identity must be established before semantic reasoning.
Definition
A Canonical Ontology Object represents a real-world entity type whose authoritative properties depend on a finite set of required state dimensions.
It does not: • Contain values • Compute answers • Fetch data
It only defines: • Identity • Required state • Authority requirements
Interface
interface OntologyObject { canonical_id: string; label: string; domain: string; identity_family: string; sensitivity: "state-invariant" | "state-sensitive";
state_axes: StateAxis[]; required_state: RequiredStateLogic;
authority_requirements: AuthorityRequirements; version: string;
// Composability (Amendment) extends?: string[]; // canonical_ids of parent ontologies
// Identity Resolution (Doctrine II Amendment) identity_resolution: IdentityResolution; }
// Doctrine II: Identity Authority — Identity Resolution Requirements interface IdentityResolution { // How identity was established (MUST NOT be semantic inference) source: "human_assigned" | "deterministic_lookup" | "cryptographic_proof" | "registry_canonical";
// Explicit prohibition: embeddings cannot establish identity derived_from_embedding: false; // MUST be false; this is a structural constraint
// Optional: what semantic candidates were considered (for audit) semantic_candidates_rejected?: string[];
// Optional: disambiguation rationale when multiple identities were possible disambiguation_reason?: string; }
interface StateAxis { key: string; type: "enum" | "range" | "validated_free" | "boolean" | "identifier" | "timestamp" | "composite" | "temporal_series"; allowed_values?: string[]; validator_ref?: string;
// For composite type: references to other axes component_axes?: string[];
// For temporal_series type: time-series structure temporal_config?: { value_type: "enum" | "range"; time_unit: "seconds" | "minutes" | "hours" | "days"; aggregation?: "latest" | "max" | "min" | "average" | "trajectory"; }; }
interface RequiredStateLogic { always: string[]; conditional?: Array<{ if: Condition; then: string[] }>; }
interface AuthorityRequirements { oracle_required: boolean; acceptable_oracles: OracleType[]; verification_method: VerificationMethod; human_lock_allowed: boolean; }
Invariants
• Identity ≠ Data
• Required state is finite and explicit
• Sensitivity is declared, not inferred
• Ontology is incremental by design
• **Identity is resolved, not inferred** (Doctrine II)
Identity Authority (Doctrine II Amendment)
RFC-0001 implements Doctrine II: Identity Authority — the principle that identity must be established before semantic reasoning begins.
The Law (from Doctrine II):
If the system does not know what something is, it is not allowed to guess what it resembles. Semantic similarity is never an authority for identity.
Core Distinction:
| Function | Properties | Role |
|---|---|---|
| Identity Resolution (Hard Gate) | Boolean, Discrete, Stable | Determines what a thing is |
| Semantic Inference (Soft Scorer) | Continuous, Probabilistic, Fluid | Suggests what it resembles |
Prohibition:
Semantic algorithms MUST NOT be permitted to assert, persist, or propagate identity. They may only:
- Propose Candidates (Search)
- Rank Options (Sort)
- Flag Anomalies (Filter)
Only an Identity Oracle (Human, Deterministic Lookup, or Cryptographic Proof) may promote a Candidate to an Identity.
Implementation Rule — Embeddings for Search, Keys for Truth:
// FORBIDDEN: Using embedding similarity as identity
const identity = nearestNeighbor(embedding); // ❌ Semantic inference
// REQUIRED: Using canonical lookup for identity
const identity = await lookupCanonical(key); // ✅ Deterministic resolution
Precedent Saturation (Stop Condition):
Identity resolution converges; semantic inference does not. Once identity is resolved:
- The Semantic Engine MUST be bypassed for that entity
- Subsequent queries use the resolved
canonical_iddirectly - Re-resolution occurs only when identity is explicitly invalidated
The Ontic Error:
Treating 0.99 similarity as TRUE identity is an ontic error. This error propagates through all downstream reasoning. RFC-0004 (Quote Binding) is the mechanical enforcement of this principle at the extraction layer.
SIR Resolution Pattern (Doctrine II Amendment)
The SIR (Subject–Included–Relevant) Resolution Pattern operationalizes Doctrine II by partitioning domain entities:
| Partition | Function | Authority | Semantic Access |
|---|---|---|---|
| S (Subject) | Canonical identity anchor | Oracle only | Read-only |
| I (Included) | Equivalence class (synonyms) | Oracle only | Read-only |
| R (Relevant) | Category, context, association | Curated + Inference | Read/Write |
The Boundary: S and I are curated. R is where semantic algorithms may operate.
Resolution Flow:
Input → R-constraint → I-match → S-resolution → Output
Invariants:
- Subject is singular (one canonical_id per mapping)
- Included collapses to Subject with confidence 1.0
- Relevant constrains but does not resolve
- S and I are append-only for humans
- Semantic operations are confined to R
Full specification: RFC-0001 Amendment: SIR Resolution Pattern
State Axis Expressiveness (Amendment)
Extended Types:
| Type | Use Case | Structure |
|---|---|---|
enum | Discrete categories | allowed_values: string[] |
range | Numeric bounds | range: { min, max } |
validated_free | Regex-validated text | validation: regex |
boolean | Binary state | true/false |
identifier | Unique keys | Opaque string |
timestamp | Time points | ISO 8601 / unix epoch |
composite | Structured state | component_axes: string[] |
temporal_series | Time-dependent | temporal_config: {...} |
Composite Axes: For state with internal structure (e.g., "cooking process" = temperature + time + method):
{
key: "cooking_process",
type: "composite",
component_axes: ["temperature", "duration", "method"]
}
Composite axes require all components to be present. Use when state dimensions are semantically coupled.
Temporal Series Axes: For time-dependent state (e.g., "symptom progression"):
{
key: "pain_trajectory",
type: "temporal_series",
temporal_config: {
value_type: "range",
time_unit: "hours",
aggregation: "trajectory" // Captures pattern, not just current value
}
}
Decomposition Guidance: Complex real-world state should decompose into multiple axes when:
- Components can vary independently
- Components have different oracle sources
- Components have different sensitivity levels
If state cannot decompose cleanly, use composite or temporal_series.
COO Composability (Amendment)
Canonical Ontology Objects may inherit from parent ontologies using the extends field.
Inheritance Rules:
required_state.alwaysis the union of all parentalwaysarrays plus the child's ownstate_axesare merged; child axes with the same key override parent axesconditionalrequirements are concatenated (all conditions apply)authority_requirementsfrom the child take precedence; unspecified fields inherit from first parent
Conflict Resolution:
- If parents have conflicting
sensitivity, the child MUST declare its own - If parents have overlapping
state_axeswith incompatible types, the child MUST override explicitly - Circular inheritance is a validation error
Cross-Domain References:
Cross-domain extends requires explicit bridge declaration:
interface CrossDomainBridge {
from_domain: string; // e.g., "medicine"
to_domain: string; // e.g., "nutrition"
trust_relationship:
| "inherits_authority"
| "advisory_only"
| "requires_dual_oracle";
}
| Relationship | Meaning | Example |
|---|---|---|
inherits_authority | Child inherits parent's oracle trust | nutrition/interaction → medicine/drug (inherits medical oracle) |
advisory_only | Parent state is informational, not authoritative | medicine/dosage → nutrition/grapefruit (flags interaction, doesn't dose) |
requires_dual_oracle | Both domain oracles must verify | finance/tax → law/jurisdiction (both must agree) |
Example: Composed Ontology
// Parent 1: nutrition/ingredient/chicken
{
canonical_id: "nutrition/ingredient/chicken",
required_state: { always: ["ingredient_family", "cut", "skin_status"] }
}
// Parent 2: nutrition/preparation/frying
{
canonical_id: "nutrition/preparation/frying",
required_state: { always: ["oil_type", "temperature", "duration"] }
}
// Composed child: nutrition/dish/fried_chicken
{
canonical_id: "nutrition/dish/fried_chicken",
extends: ["nutrition/ingredient/chicken", "nutrition/preparation/frying"],
required_state: {
always: ["portion_amount"] // Merged with parents
}
}
Human Lock Semantics (Amendment)
human_lock_allowed: true enables human override of the decision matrix with audit requirements:
- Purpose: Allow authorized humans to override automated decisions
- Mechanism: Human provides override_reason, system records audit entry
- Constraint: Override does not bypass oracle verification—it overrides the decision given oracle data
- Not a circuit breaker: Circuit breaker behavior is
skipped_circuit_open(RFC-0008)
Critical Limitation: Human lock MAY override authorization decisions, but MUST NOT override extraction verification failures (RFC-0004). Hallucinated state cannot be approved—only replaced with verified input. This preserves the sensor/simulator boundary.
interface HumanLockOverride {
override_by: string; // User/role identifier
override_reason: string; // Mandatory justification
original_decision: string; // What the system would have decided
override_decision: string; // What the human decided
timestamp: string; // ISO 8601
}
Abuse Mitigation:
interface HumanLockPolicy {
rate_limit: {
max_overrides_per_operator: number; // Per time window
window_hours: number;
};
escalation_threshold: {
count: number; // N overrides in period T
period_hours: number;
action: "notify_supervisor" | "require_approval" | "suspend_operator";
};
two_person_rule?: {
required_for_domains: string[]; // e.g., ["medicine", "law"]
second_approver_role: string;
};
}
Human locks are auditable events, not silent bypasses.
⸻