Spec-15-Fact-Semantics
What this spec defines
The supported behavior of facts after they are written: provenance, expiry, contradiction detection, query-time winner selection, and conflict entities.
Extraction status
This file contains the ADR-010 prose extraction for fact semantics.
Atomic fact shape is owned by Spec-01-Fact-Model; scope
enforcement is owned by Spec-02-Scopes-and-ACL; HTTP route shape
is owned by Spec-03-HTTP-API.
Legacy version labels from archived source material are normalized
to the current v0.9.0a1 protocol line here. Historical wording
remains available in spec/archive/evolution/ and
spec/EVOLUTION.md.
Provenance
Every fact carries source and timestamp. A node MUST store both without modification.
Query responses MUST return the original source; relay metadata
MUST NOT replace the original source.
Inbound federated facts SHOULD record receiving-node provenance separately from the original source. The receiving node MAY assert a local meta-fact:
entity=<fact-id>
relation="stigmem:received_from"
value={type:"ref", v:"<originating-node-id>"}
source="system:stigmem"
The receiving-node provenance fact is local accounting and MUST NOT be re-replicated as if it were part of the origin peer's assertion set.
Expiry
Facts whose valid_until timestamp has passed MUST NOT be returned
by ordinary fact queries. A caller MAY request expired facts with an
explicit include_expired=true option on routes that support it.
Expired facts remain in the store. Expiry is a read-filtering and operational health concern, not a destructive deletion rule.
TTL meta-facts
Operators or agents that need to schedule future expiry for a fact
that was originally asserted without valid_until MAY attach a TTL
meta-fact. The meta-fact's entity is the target fact id, the relation
is stigmem:ttl, and the value is the intended expiry datetime:
entity=<fact-id>
relation="stigmem:ttl"
value={type:"datetime", v:<expiry>}
valid_until and confidence are orthogonal.
A historical certain fact may have confidence=1.0 and a
valid_until timestamp that marks when it stopped being current.
Contradiction detection
A contradiction exists when two facts a and b satisfy all of:
Same entity
a.entity == b.entity
Same relation
a.relation == b.relation
Same scope
a.scope == b.scope
Different value
a.value != b.value
Both confident
a.confidence > 0.0 AND b.confidence > 0.0
Both facts MUST be retained. Nodes MUST NOT silently overwrite one fact with the other.
Entity normalization from Spec-01-Fact-Model applies before
contradiction detection. Facts written with different raw entity
strings that normalize to the same canonical entity participate in
the same contradiction set.
Query-time resolution
When a query needs a single preferred fact for a contradicted
(entity, relation, scope) tuple, nodes SHOULD apply this ordering:
- Higher
confidencewins. - Equal confidence: higher HLC wins.
- Equal confidence and HLC: return both with
contradicted: trueand let the caller decide.
This ordering does not delete or mutate losing facts. It only controls presentation and default winner selection.
Conflict entities
When a contradiction is detected on write, a node SHOULD create a
first-class conflict entity in the stigmem:conflict: namespace. The
conflict entity reifies disagreement as queryable data.
The conflict relation links the competing fact ids:
entity="stigmem:conflict:<uuid>"
relation="stigmem:conflict:between"
value={type:"text", v:"<fact-id-a> <fact-id-b>"}
source="system:stigmem"
confidence=1.0
scope=<same scope as the conflicting facts>
A companion status fact tracks resolution state:
entity="stigmem:conflict:<uuid>"
relation="stigmem:conflict:status"
value={type:"string", v:"unresolved"}
source="system:stigmem"
confidence=1.0
scope=<same scope as the conflicting facts>
Resolution is itself represented as new provenance-bearing data.
The node MUST NOT mutate original facts to hide the conflict.
Out of scope
This spec does not define:
Atomic fact field definitions
Scope authorization rules
HTTP route shape
For conflict listing or resolution.
Decay sweep algorithms
Async lint or decay jobs
Plugin-based custom resolution
Policies.