Event schema reference
EventType — all 26 event types
export type EventType =
// Claim lifecycle
| "sentence_first_seen"
| "sentence_removed"
| "sentence_modified"
| "sentence_reintroduced"
// Citation changes
| "citation_added"
| "citation_removed"
| "citation_replaced"
// Template changes
| "template_added"
| "template_removed"
| "template_parameter_changed"
// Section & page structure
| "section_reorganized"
| "lead_promotion"
| "lead_demotion"
| "page_moved"
// Links & categories
| "wikilink_added"
| "wikilink_removed"
| "category_added"
| "category_removed"
// Access control
| "protection_changed"
// Content conflict
| "revert_detected"
| "edit_cluster_detected"
// Talk page correlation
| "talk_page_correlated"
| "talk_thread_opened"
| "talk_thread_archived"
| "talk_reply_added"
| "talk_activity_spike";
Core interface: EvidenceEvent
All events share a common envelope with before/after snapshots and
deterministic facts. There are no discriminated subtypes — all fields are
optional at the envelope level:
export interface EvidenceEvent {
eventId?: string; // deterministic content hash (see below)
eventType: EventType; // discriminator
claimId?: string; // claim identity hash, when applicable
fromRevisionId: number; // parent revision
toRevisionId: number; // source revision
section: string; // section title where change occurred
before: string; // text / state before the change
after: string; // text / state after the change
deterministicFacts: DeterministicFact[]; // facts backing this event
modelInterpretation?: ModelInterpretation; // set by downstream consumers
layer: EvidenceLayer; // provenance layer
timestamp: string; // ISO 8601
}
Supporting types
export type EvidenceLayer =
| "observed" // directly observed from the diff
| "policy_coded" // coded against a policy rule
| "model_interpretation" // set by downstream consumers
| "speculative" // inferred but without a hard rule
| "unknown"; // layer not yet classified
export interface DeterministicFact {
fact: string;
detail?: string;
provenance?: FactProvenance;
}
export interface FactProvenance {
analyzer: string; // analyzer that produced this fact
version: string; // analyzer version
inputHashes: string[]; // hashes of input data used
parameters?: Record<string, string | number | boolean>; // parameters used by the analyzer
}
export interface ModelInterpretation {
semanticChange: string;
confidence: number;
policyDimension?: PolicyDimension;
discussionType?:
| "notability_challenge"
| "sourcing_dispute"
| "neutrality_concern"
| "content_deletion"
| "content_addition"
| "naming_dispute"
| "procedural"
| "other";
}
export type PolicyDimension =
| "verifiability"
| "npov"
| "blp"
| "due_weight"
| "protection"
| "edit_warring"
| "notability"
| "copyright"
| "civility";
ModelInterpretation and modelInterpretation on EvidenceEvent are never set by Refract's deterministic pipeline — they exist for downstream consumers to attach semantic analysis without modifying the deterministic event.
AnalyzerConfig is a supporting type exported from @refract-org/evidence-graph that defines configurable parameters for analyzers (similarity thresholds, time windows, revert patterns). See the CLI reference for the per-flag equivalents.
Deterministic identity
eventId is derived deterministically from the event content so the same
observation always produces the same ID:
modelInterpretation is excluded from the hash so downstream consumers can add it without changing the event's deterministic identity.
import { createHash } from "node:crypto";
export function createEventIdentity(
event: Omit<EvidenceEvent, "eventId" | "modelInterpretation">,
): string {
const factsStr = event.deterministicFacts
.map((f) => `${f.fact}:${f.detail ?? ""}`)
.join("|");
const identityKey =
`${event.eventType}|${event.fromRevisionId}|${event.toRevisionId}|` +
`${event.section}|${event.before}|${event.after}|${event.timestamp}|${factsStr}`;
return createHash("sha256").update(identityKey).digest("hex").slice(0, 16);
}
The hash is truncated to 16 hex characters (64 bits of collision resistance).
Version compatibility
When consuming Refract events across different package versions, the schemaVersion field on each event tells you which schema produced it.
| refract CLI | @refract-org/evidence-graph |
EVENT_SCHEMA_VERSION |
Key changes |
|---|---|---|---|
| 0.5.x | 0.4.x | "0.4.0" |
sentence_modified event type, FactProvenance.parameters, AnalyzerConfig, EVENT_SCHEMA_VERSION, CLAIM_IDENTITY_VERSION |
| 0.4.x | 0.3.x | "0.3.0" |
ClaimLedger, ObservationReport, --report flag, cron merging |
| 0.3.x | 0.2.x | "0.2.0" |
25 event types, initial public release |
Negotiation rules:
- Consumers SHOULD accept events with the same minor schema version (0.4.x)
- Consumers MAY accept events across minor versions if they handle unknown
EventTypemembers gracefully (skip unrecognized types, log, preserve) - Consumers MUST NOT silently drop events with unrecognized event types — log them and preserve the raw data
- When
schemaVersionis missing, assume the most recent compatible schema for the consuming package version