Technical Specification

The Constellation Protocol

A protocol for versioned, correctable, navigable knowledge infrastructure

Version · January 2026

The Constellation Protocol

Version 0.8 · January 2026

A protocol for versioned, correctable, navigable knowledge infrastructure


Document Structure

This specification uses section markers to distinguish normative requirements from implementation guidance:


Abstract

Knowledge should be versionable and correctable, like code. It is not.

When a clinical trial is retracted, the thousand papers that cited it do not update. Guidelines built on that evidence continue recommending treatments. Systematic reviews must be manually re-audited—if anyone notices at all. The retractions sit in journals. The errors propagate forever.

Git solved this for code. Every change tracked, every version retrievable, every dependency known. The Constellation Protocol does the same for scientific knowledge. It makes individual findings addressable as points with evidence and confidence. It separates immutable content (what was claimed) from mutable state (validated, contested, retracted). It propagates corrections through dependency chains automatically.

A retraction becomes an event that surfaces everywhere the retracted work was cited—within hours, not decades.

The protocol defines four core primitives: Source, Entity, Point, Link. Content is canonicalized and hashed. State changes are signed events. The current view is materialized from the event log. This document specifies everything needed for interoperable implementation.


Primary User and Workflow

Before reading further, understand who this is for and what problem it solves.

Primary user: The systematic reviewer, clinical guideline author, or evidence synthesis professional who must keep recommendations correct as the evidence base changes.

Primary pain: A trial cited in 47 guideline recommendations is retracted. Today, discovering this requires manual re-audit of every downstream artifact—if anyone notices the retraction at all. This takes weeks and often doesn’t happen.

Primary workflow (the “aha moment”):

1. User subscribes to "my guideline's evidence base" in Constellation
2. Trial NCT12345678 is retracted (Source event ingested from Crossref/PubMed)
3. Constellation computes: 12 Points cite this Source as evidence
4. User receives alert: "3 guideline recommendations depend on retracted evidence"
5. User clicks through: sees exactly which statements, which evidence links, what changed
6. User exports: machine-readable change log with full provenance

Time to value: From “I wonder if anything changed” to “here’s exactly what’s affected with an audit trail” in under 60 seconds.

If Constellation does nothing else, it should make this workflow work. That’s the bet: that this single capability, done right, creates infrastructure the rest of science will use.


1. Introduction

[GUIDANCE]

Claude Shannon proved that information could be transmitted reliably over noisy channels—not by making channels perfect, but by adding structure that detects and corrects errors. Every text message, every streamed video, every financial transaction depends on this insight.

Scientific knowledge has transmission. It does not have error correction. Findings propagate through citation without their evidence. Retractions sit in journals; they do not update the thousand papers that cited them. Confidence launders through repetition until a preliminary result becomes “established fact.” We built systems to move knowledge. We did not build systems to correct it.

The Constellation Protocol is Shannon’s insight applied to knowledge: transmission with error correction built in.

1.1 The Core Insight

The unit of knowledge is not the document. It is the finding.

Documents are containers. You can cite them. You cannot query the assertions inside. You cannot ask: has this finding replicated? Under what conditions does it hold? What depends on it?

Make findings addressable—as points with evidence, confidence, and lineage—and everything else follows:

This is the same move Git made for code. Git made code states addressable (commits with content hashes). This enabled distributed version control, branching, merging—capabilities that transformed software development. The Constellation Protocol makes knowledge states addressable. The same transformation becomes possible for science.

1.2 Why Now

Five forces create urgency.

AI agents are arriving. Within months, not years, AI agents will conduct substantial portions of scientific work—literature review, hypothesis generation, experimental design. Claude Code, Codex, and research agents like FutureHouse already operate in feedback loops: gather context, take action, verify results, repeat. These agents need structured knowledge, not documents. An agent querying PubMed retrieves papers it must summarize; an agent querying the constellation retrieves assertions with evidence profiles it can verify. The difference is hallucination versus grounding.

Multi-agent coordination requires shared memory. As AI agents multiply—research assistants, autonomous labs, clinical decision support—they need common ground. Without shared knowledge infrastructure, agents will duplicate work, contradict each other, and lose context. 2026 is the year of multi-agent systems: orchestrated networks of specialized agents that must coordinate to solve complex problems. The constellation serves as that shared memory—structured knowledge that multiple agents can query, validate, and extend without direct coordination.

Autonomous labs are emerging. Self-driving laboratories at Berkeley, NC State, and elsewhere now run experiments with minimal human intervention. AI systems propose hypotheses, robotic platforms execute experiments, and machine learning analyzes results. Without shared memory infrastructure, these systems will rediscover known failures—the same compound tested, the same negative result obtained, the same resources wasted. The constellation is that shared memory: structured knowledge that autonomous systems can query before acting.

The reproducibility crisis demands infrastructure. More than 70% of researchers cannot reproduce published findings. Paper mills now generate fraud faster than legitimate science (Northwestern, 2025). Brazil’s 2025 large-scale replication effort yielded “dismaying results” across biomedical research. The problem is not individual failure—it is missing infrastructure. Without structured provenance, negative results disappear. Without replication tracking, the same experiments repeat endlessly. Without correction propagation, retracted findings persist in the citation graph for decades. The constellation provides the infrastructure that reproducibility requires: every finding with its evidence, every replication linked, every correction propagated.

The window is closing. Infrastructure that is not built open will be built closed. The map of what humanity knows could be owned by a company optimizing for quarterly returns. Every year without structure is a year of preventable harm—children misdiagnosed, researchers duplicating failed work, treatments arriving a generation late. The seventeen-year gap between discovery and clinical practice is not a future problem. It is a present harm we are permitting.

1.3 Scope

This document specifies:

This document provides guidance on:

For full context and motivation, see Constellations of Borrowed Light (borrowedlight.org/constellations).

1.4 Notational Conventions

Schemas use pseudocode notation. Types are capitalized. Optional fields are marked with ?. Arrays use []. The notation is intended to be readable by engineers and implementable in any language.


2. Design Principles

[GUIDANCE]

The protocol embeds lessons from systems that succeeded (Git, Wikipedia, RECOVERY) and systems that failed (Semantic Web, Mundaneum, institutional repositories).

2.1 Content-Addressable

Point identifiers are derived from content hashes. The same knowledge, expressed identically, produces the same identifier regardless of where or when it is created. This enables deduplication, verification, and distribution without coordination.

2.2 Distributed

No central authority owns the constellation. Any node can host any points. The protocol survives the failure of any single node, organization, or jurisdiction. Centralized systems can be captured or destroyed; distributed systems persist.

2.3 Extract, Don’t Prescribe

The Semantic Web required agreement on ontologies before use—agreement that never came at scale. Linked Data principles remain valid; the lesson is extraction over prescription, bridging over mandating. The Constellation Protocol extracts structure from existing artifacts—papers, protocols, clinical decisions. The bottleneck shifts from “get everyone to agree” to “verify what was extracted.”

2.4 Layered

Core primitives depend only on primitives below them:

Link     (relationships between points)

Point    (units of knowledge)

Entity   (stable referents)

Source   (citable artifacts)

Extensions (Trail, bitemporal semantics) build on this core without modifying it.

This layering enables incremental implementation and clear separation of concerns.

2.5 Correction as First-Class

Errors are inevitable. The protocol treats correction as infrastructure, not exception. Every point carries its confidence. Every state transition is logged. Every correction propagates to dependents. The structure learns.

2.6 FAIR-Native

The constellation implements FAIR principles by design, not retrofit:

Unlike systems where FAIR compliance is added post-hoc, the protocol’s primitives encode findability, accessibility, interoperability, and reusability as structural properties. The 2025-2030 NIH Strategic Plan for Data Science and EU Open Science mandates require FAIR alignment—for the constellation, compliance is not a cost but the architecture itself.

2.7 Core vs Extensions

The protocol distinguishes Constellation Core (mandatory for conformance) from Extensions (optional profiles that add capabilities).

Constellation Core:

Extensions (optional):

A competent engineer should be able to implement Constellation Core in a weekend. That is the test of protocol simplicity. Extensions add power but are not required for interoperability.


3. What This Enables

[GUIDANCE]

Before specifying primitives, consider what becomes possible:

Queries that don’t exist today:

"Which findings about BRAF V600E have replicated independently?"
→ Returns points with evidence_relation = replicates, filtered by entity

"What depends on this retracted paper?"
→ Traverses links from retracted point, returns all dependents

"Where is evidence thin for pediatric brain tumor diagnosis?"
→ Returns points with confidence < threshold, filtered by entity and population

"Show me the reasoning path that led to this treatment recommendation"
→ Returns trail with all steps, rejections, and rationale

"What changed about this finding since 2020?"
→ Returns state transition history with timestamps and actors

Capabilities that emerge:

The difference from existing tools:

ToolWhat It DoesWhat It Cannot Do
PubMedFinds documentsQuery findings inside documents
Google ScholarRanks by citationShow what citations actually support
Semantic ScholarExtracts claimsVersion or correct them
UpToDateSummarizes evidenceShow provenance, propagate corrections
Standard RAGRetrieves text chunksTraverse relationships, verify evidence

The constellation is not a better search engine. It is a different primitive—knowledge that can be queried, versioned, and corrected. Where standard retrieval-augmented generation (RAG) treats information as isolated chunks, the constellation enables graph-based retrieval: traversing typed links between assertions, following evidence chains, and understanding how findings relate. This is GraphRAG for science—not just finding relevant text, but navigating structured knowledge with explicit provenance.

Relationship to adjacent systems:

The constellation enters a landscape with mature infrastructure. This section states explicitly what differs and why.

SystemWhat It Does WellWhat Constellation Adds
NanopublicationsAtomic assertions with provenance; decentralized serversStateful lifecycle (retraction propagates); conflict representation via event logs; simpler JSON-native DX
ORKGStructured research contribution graphs; comparison tablesImmutable content + mutable state separation; designed for machine agents, not just human curation
sciteCitation context classification (supporting/contrasting/mentioning)Full dependency graph; state changes propagate to downstream; trails capture reasoning paths
Semantic Scholar / OpenAlexMassive corpus coverage; embeddings; APIsClaim-level granularity vs document-level; correction propagation; explicit evidence typing
Elicit / ConsensusAI-powered search and synthesisStructured submission of AI-generated claims for human validation; audit trails

Why not just use nanopublications? Nanopublications pioneered atomic assertions with provenance, and Constellation learns from them. The differences are: (1) Constellation separates immutable content from mutable state—a nanopub cannot be “retracted” in a way that propagates to citing nanopubs; (2) Constellation specifies conflict representation via event logs rather than last-write-wins; (3) Constellation targets AI agent integration via MCP as a first-class use case. If nanopublications add these capabilities, Constellation should interoperate or merge. The goal is infrastructure, not territory.

Why not just use better LLMs + RAG? This is the strongest counterargument. Long-context models may eventually ingest PubMed directly. But: (1) Verification requires structure—you cannot check if an LLM-generated claim contradicts existing evidence without knowing what “existing evidence” means at claim granularity; (2) Correction requires propagation—when a paper is retracted, there is no mechanism to update all RAG chunks that referenced it; (3) Reproducibility requires provenance—regulatory contexts (EU AI Act, FDA AI/ML guidance) increasingly demand audit trails that RAG cannot provide. Structure is not an alternative to scale; it is what makes scale trustworthy.

Structural gaps competitors cannot fill without Constellation-like primitives:

CapabilityWhy It’s StructuralWhy Competitors Can’t Add It Easily
Retraction propagationRequires explicit dependency graph with typed linksRAG has no dependency model; citation graphs don’t distinguish “evidence for” from “mentions”; retrofitting changes the data model
Conflict representationRequires event history, not just current stateDatabases store current truth; adding event sourcing means reimplementing the storage layer
Claim-level versioningRequires content-addressed identity at sub-document levelDocument-centric systems can’t version “the third claim in paragraph 2” without document-breaking IDs
Composable confidenceRequires evidence typing + independence trackingAd-hoc confidence scores don’t compose; you can’t combine two RAG relevance scores meaningfully
Audit trail for AIRequires provenance chains from output back to sourcesLLMs are stateless; RAG retrieval isn’t logged by default; adding it requires infrastructure change

The test: Can Semantic Scholar add retraction propagation tomorrow? They’d need to: (1) define what “depends on” means (just citation? evidence? logical dependency?), (2) track it for every paper, (3) compute transitive closure for propagation, (4) store the event history. This is a data model change, not a feature toggle. That’s the structural moat.

What this doesn’t claim: Constellation is not “better at search” or “has more papers.” Semantic Scholar and OpenAlex will always have broader coverage. The differentiation is what you can do with the knowledge, not the knowledge itself.

3.1 The Frontier

The frontier is the boundary between firm and contested knowledge—the edge of what we confidently know.

Some regions of the constellation are firm: points with high confidence, multiple independent replications, no active dissent. A clinician querying these regions can trust the answers. Other regions are soft: preliminary findings, active contradictions, thin evidence. The frontier separates them.

The frontier is queryable:

"Am I in firm territory?"
→ Returns frontier_distance for current point (0 = on frontier, positive = firm, negative = contested)

"Show me the frontier around KRAS mutations"
→ Returns points within threshold of frontier boundary, filtered by entity

The frontier moves. When a key study replicates, the frontier advances. When a retraction propagates, it retreats. Tracking frontier movement over time reveals where knowledge is stabilizing and where it remains contested.

Formal derivation of frontier stability (proving it doesn’t thrash under small corrections) appears in Epistemic Systems Engineering (Borrowed Light, 2026).

3.2 Gap Types

Not all gaps in knowledge are alike. The protocol distinguishes three types:

Structural gaps: Entities that should connect but don’t. If A→B and B→C are established, but A→C has no direct evidence, that’s a structural gap. The topology predicts a connection that hasn’t been verified. Structural gaps are detectable from the graph alone.

Predictive gaps: Expected links that don’t exist. Knowledge graph embeddings learn patterns—if drugs with property X typically affect pathway Y, but a new drug with property X has no recorded effect on Y, that’s a predictive gap. These require learned models over the graph.

Coverage gaps: Areas with sparse evidence relative to neighbors. A well-studied gene with one unstudied variant. A thoroughly characterized drug with no pediatric data. Coverage gaps identify where evidence is thin compared to what we’d expect given surrounding density.

Gap queries return ranked lists:

"What are the top structural gaps in melanoma treatment?"
→ Returns entity pairs with high predicted connection probability but no established links

"Where are coverage gaps for EGFR inhibitors?"
→ Returns populations, variants, or conditions with sparse evidence relative to related entities

Gap analysis transforms the constellation from a static map into a guide for investigation—showing not just what we know, but what we should find out next.

3.3 Knowledge Graph + LLM Integration

The constellation serves as the knowledge graph layer that LLMs require for grounded reasoning. Unlike retrieval systems that return text chunks, the constellation returns structured assertions with explicit evidence.

Integration patterns:

The convergence of knowledge graphs and LLMs—through systems like GraphRAG, ATLAS, and domain-specific KGs—demonstrates that graph-structured knowledge can improve AI reasoning by providing explicit relational context that embedding similarity alone cannot capture. The constellation provides this graph structure for scientific knowledge specifically.

This positions the protocol as infrastructure for the emerging “LLM as Scientist” paradigm—where AI agents conduct research within structured knowledge boundaries rather than hallucinating in document space.

3.4 AI-Driven Discovery Infrastructure

As AI systems take on scientific tasks—literature review, hypothesis generation, experimental design—they require structured knowledge to ground their work.

Without infrastructure:

With constellation:

The Agent Laboratory framework (2025), Google’s AI Co-Scientist (2025), and similar systems demonstrate the trajectory: AI conducting end-to-end research workflows. These systems show promise but face a critical gap—they lack shared, correctable knowledge infrastructure. Each operates in isolation, unable to build on or correct each other’s work.

The constellation is not just for humans navigating knowledge—it is infrastructure that AI agents require to do science responsibly. When an AI agent proposes a hypothesis, that hypothesis should be a structured point with explicit evidence requirements. When that hypothesis fails validation, the failure should propagate. This is how responsible AI-driven science becomes possible.


4. Core Primitives

[NORMATIVE]

4.0 Object Model: Immutability and Events

The protocol follows the Git pattern: immutable content objects plus signed state events equals materialized views.

┌─────────────────────────────────────────────────────────────┐
│  IMMUTABLE LAYER                                            │
│  Content objects with content-derived IDs                   │
│  (Source, Entity, Point, Link)                               │
└─────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│  EVENT LAYER                                                │
│  Signed, timestamped state transitions                      │
│  (SourceEvent, PointEvent)                                  │
└─────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│  VIEW LAYER                                                 │
│  Materialized current state (computed from events)          │
│  (SourceView, PointView with evidence links)                │
└─────────────────────────────────────────────────────────────┘

Why this matters:

  1. Verifiability: Anyone can recompute current state from the event log
  2. Conflict representation: Disagreements surface as conflicting events, not silent overwrites
  3. Auditability: Full history is preserved; no mutation, only append
  4. Distribution: Nodes sync event logs; materialized views are local

This is not last-write-wins. When attestors disagree about a claim, both events exist in the log. Materialized views must represent the conflict (e.g., “contested” state with pointers to conflicting attestations). Resolution requires explicit resolution events, not silent override.

4.1 Source

A Source is a citable artifact with lifecycle state—a paper, preprint, dataset, or protocol. Sources are first-class because their state changes (retraction, correction, version update) must propagate to dependent points.

Why Source is a primitive: If a paper is retracted, that is a Source lifecycle event. Previously, sources existed as references on Points. This created a gap: there was no object to attach the retraction event to. Making Source first-class enables: “find all points citing this source” → “propagate retraction to all of them.”

Schema

SourceContent {
  id:           SourceID          // Content-derived identifier
  type:         SourceType        // paper | preprint | dataset | protocol | trial | ...
  identifiers:  [Identifier]      // DOI, PMID, arXiv ID, etc.
  title:        Text
  authors:      [Text]?
  date:         Date?             // Publication date
  venue:        Text?             // Journal, conference, repository
  version:      Text?             // For preprints with versions
}

Identifier {
  system:     Text    // "doi" | "pmid" | "arxiv" | "clinicaltrials" | ...
  value:      Text    // The identifier value
}

SourceID = Hash(Canonicalize(type + primary_identifier))

Source Events

SourceEvent {
  id:           EventID           // Hash of event content
  source_id:    SourceID
  event_type:   SourceEventType   // registered | corrected | retracted | versioned
  timestamp:    Timestamp
  actor:        ContributorID
  signature:    Signature
  evidence:     SourceRef?        // Link to retraction notice, correction, etc.
  note:         Text?
}

SourceEventType =
  | registered    // Source entered the constellation
  | corrected     // Correction or erratum issued
  | retracted     // Full retraction
  | versioned     // New version available (preprints)
  | expression_of_concern  // Formal expression of concern

Source View (Materialized)

SourceView {
  content:      SourceContent
  state:        SourceState       // active | corrected | retracted | ...
  events:       [SourceEvent]     // Full event history
  computed_at:  Timestamp
}

When a source enters retracted state, propagation triggers (§7) fire for all points citing that source.

4.2 Entity

An Entity is a stable referent—the thing that points are about. A gene, a drug, a mutation, a condition, a patient population. Entity resolution is where previous knowledge systems failed: the same thing with twelve names, twelve things with the same name.

The constellation requires mapped, versioned identifiers as a foundation layer. Without entities, points cannot link.

Schema

Entity {
  id:             EntityID        // Stable identifier (see derivation below)
  type:           EntityType      // gene | drug | variant | condition | 
                                  // population | method | instrument | ...
  canonical_name: Text            // Primary human-readable name (mutable)
  aliases:        [Text]          // Alternative names, synonyms
  primary_ref:    ExternalRef?    // Primary authoritative reference
  external_refs:  [ExternalRef]   // Additional links to external ontologies
  description:    Text?           // Brief definition
  version:        Version         // Monotonic version number
  supersedes:     EntityID?       // Previous version, if any
  created_at:     Timestamp
  created_by:     ContributorID
}

ExternalRef {
  system:     Text    // "HGNC" | "RxNorm" | "OMIM" | "MeSH" | ...
  identifier: Text    // System-specific ID
  uri:        URI?    // Resolvable link
}

EntityID derivation (stability-first):

EntityID = 
  if primary_ref exists:
    Hash(type + primary_ref.system + primary_ref.identifier)
  else:
    Hash(type + random_uuid_at_creation)

Why this matters: Names change. “BRCA1” could be renamed in an external system. If EntityID depended on canonical_name, renaming would break all references. By deriving ID from stable external identifiers (HGNC IDs, RxNorm CUIs, etc.) or from a creation-time UUID, EntityIDs remain stable even as display names evolve.

The canonical_name is mutable metadata for human readability, not part of the identity.

Entity Types

Initial supported types (extensible):

TypeDescriptionPrimary External System
geneHuman genesHGNC
variantGenetic variantsClinVar, dbSNP
drugPharmaceutical compoundsRxNorm, DrugBank
conditionDiseases, disordersOMIM, ICD-11
populationPatient populationsCustom
methodExperimental methodsCustom
instrumentLaboratory equipmentCustom

Resolution

When a point references an entity:

  1. Check for exact ID match
  2. Check for primary_ref match (same system + identifier)
  3. Check for alias match within type
  4. Check for external_refs match
  5. If no match, entity must be created before point

Entity merges (when two entities are discovered to be the same) create a new entity that supersedes both. Points referencing either predecessor are updated to reference the merged entity.

Equivalence Kinds

Not all entity relationships are simple aliases. The protocol distinguishes four equivalence kinds:

EquivalenceKind =
  | exact      // Same referent: "BRCA1" = "BRCA1_HUMAN"
  | broad      // A contains B: "cancer" contains "breast cancer"
  | narrow     // A is contained in B: "breast cancer" is narrower than "cancer"
  | distinct   // Explicitly NOT equivalent: "BRCA1" ≠ "BRCA2"

Why this matters: “BRCA1” and “BRCA2” look similar but are different genes. Without explicit distinct marking, a naive system might treat them as related. Conversely, “cancer” and “breast cancer” have a hierarchical relationship—queries for “cancer” should optionally expand to include “breast cancer” (via broad), but queries for “breast cancer” should not automatically expand to all cancers.

Equivalence assertions are stored with provenance:

Equivalence {
  entity_a:    EntityID
  entity_b:    EntityID
  kind:        EquivalenceKind
  provenance:  SourceRef?        // Who asserted this, based on what
  scope:       Text?             // Context in which equivalence holds
  created_at:  Timestamp
  created_by:  ContributorID
}

Query expansion respects equivalence kinds: searching for entity A can optionally traverse exact and broad relationships within a bounded hop limit. distinct relationships are never traversed—they act as explicit barriers.

Interoperability with Existing Identifiers

The constellation does not replace existing identifier systems—it bridges them.

For evidence sources:

For entities:

For contributors:

Ontology Ecosystem Integration (UMLS, OBO)

Scientific knowledge depends on controlled vocabularies. Constellation does not replace UMLS or OBO Foundry ontologies—it maps to them.

UMLS Integration:

Entity {
  id:           "entity:constellation:breast_cancer_001"
  canonical_name: "Breast Cancer"
  external_refs: [
    { system: "UMLS", id: "C0006142", version: "2024AA" },
    { system: "SNOMED-CT", id: "254837009" },
    { system: "ICD-10", id: "C50" }
  ]
}

OBO Foundry Integration:

Entity {
  id:           "entity:constellation:apoptosis_001"
  canonical_name: "Apoptosis"
  external_refs: [
    { system: "GO", id: "GO:0006915" },      // Gene Ontology
    { system: "DOID", id: "DOID:0001" }      // Disease Ontology
  ]
}

Governance plan:

  1. Initial mapping: Curated same_as links from Constellation entities to UMLS CUIs and OBO term IDs for high-frequency entities
  2. Automated suggestion: NLP-based matching proposes new mappings; human review required before acceptance
  3. Version tracking: External refs include version (UMLS releases quarterly; OBO ontologies have releases)
  4. Conflict resolution: When UMLS and OBO disagree on concept boundaries, both mappings are maintained with distinct equivalence type
  5. Query expansion: Search for UMLS:C0006142 automatically finds all Constellation entities with that external_ref

What this enables:

What this does NOT do:

Relationship to a Point and its source paper:

A Point extracted from a paper is not a replacement for the paper. The paper (identified by DOI) is the source. The Point is the structured, queryable assertion with its evidence profile. Multiple Points may be extracted from one paper. One Point may cite evidence from many papers.


4.3 Point

A Point is a unit of knowledge—a finding, measurement, method, or result. Points are the core primitive. Everything else exists to create, connect, or navigate them.

A point is not a document. Documents are containers; the assertions inside are not addressable. A point extracts the assertion and makes it queryable, versionable, correctable.

Identity Model

The hardest problem in knowledge graphs is convergence: the same finding, stated by different people at different times, should be recognizable as the same finding. Without this, the graph fragments into isolated duplicates.

Constellation solves this by separating semantic identity from provenance:

┌─────────────────────────────────────────────────────────────┐
│  POINT (semantic identity)                                  │
│  PointID = Hash(Canonicalize(statement + entities))         │
│  "What is being asserted"                                   │
└─────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│  EVIDENCE LINKS (provenance)                                │
│  Links from Sources to this Point                           │
│  "Who said it, based on what, when"                         │
└─────────────────────────────────────────────────────────────┘

Why this matters:

Schema

Point {
  id:           PointID           // Hash(Canonicalize(statement + entities))
  statement:    Text              // The assertion in natural language
  entities:     [EntityRef]       // What this point is about
  constraints:  [Constraint]      // Conditions under which it holds
}

PointID = Hash(Canonicalize(statement + entities))

Evidence is Links, not embedded data. Each source that supports a point creates an evidence Link (see §4.4). This means:

Semantic equivalence: Two statements that are semantically identical but phrased differently will have different PointIDs. This is intentional—automated semantic matching is error-prone. Instead, explicit same_as links (§4.4) can connect equivalent points when humans or validated systems confirm equivalence. The graph tolerates some duplication rather than forcing premature merging.

Point Events

State changes are events, not mutations:

PointEvent {
  id:           EventID           // Hash of event content
  point_id:     PointID           // The point this event affects
  event_type:   EventType
  timestamp:    Timestamp
  actor:        ContributorID
  signature:    Signature         // Cryptographic signature by actor
  causal_deps:  [EventID]         // Events this depends on (see §6.3)
  lamport_ts:   Integer           // Logical timestamp for ordering
  evidence:     [SourceID]?       // Supporting evidence for this event
  note:         Text?
}

EventType =
  | proposed        // Initial submission
  | validated       // Independent validation (can accumulate)
  | contested       // Challenge raised with counter-evidence
  | contest_resolved // Challenge resolved (with outcome)
  | superseded      // Replaced by newer point
  | retracted       // Withdrawn due to error
  | source_retracted // Upstream source was retracted (auto-generated)

Note on validation: Science does not have binary “validated/not validated” states. Points accumulate validations from independent sources. A point with 5 independent validations from RCTs is stronger than one with 1 validation from an observational study. The protocol models this via multiple validated events, not a single state flip. Confidence is computed from evidence Links, not from event counts.

Causal dependencies: A validated event SHOULD include the proposed event in its causal_deps. A contest_resolved event MUST include the contested event. This enables correct ordering during materialization (see §6.3).

Conflict Representation

When validators disagree, both events exist in the log. This is not last-write-wins:

Example event log for contested point:

1. { type: proposed, actor: alice, timestamp: t1 }
2. { type: validated, actor: bob, timestamp: t2 }
3. { type: contested, actor: carol, timestamp: t3, note: "Effect size not replicated", evidence: [src_failed_rep] }
4. { type: validated, actor: dave, timestamp: t4, note: "Replicated in our lab" }

The materialized view shows state = contested with pointers to the conflicting events. Resolution requires an explicit contest_resolved event with outcome, not silent override.

Point View (Materialized)

PointView {
  point:         Point             // The semantic assertion
  evidence:      [Link]            // All evidence links to this point
  state:         PointState        // Computed from events
  confidence:    ConfidenceProfile // Computed from evidence links
  events:        [PointEvent]      // Full event history
  conflicts:     [ConflictPair]?   // Active disagreements
  computed_at:   Timestamp
}

PointState =
  | proposed     // Submitted, awaiting validation
  | validated    // At least one independent validation, no unresolved contests
  | contested    // Active unresolved challenge
  | superseded   // Replaced by newer point
  | retracted    // Withdrawn

Canonicalization

Content addressing requires deterministic byte-level representation. Two implementations given the same input MUST produce identical hashes. This section is normative—implementations that deviate are non-conformant.

Scope clarification: Canonicalization solves syntactic identity, NOT semantic equivalence.

Canonicalization ensures:

Canonicalization does NOT ensure:

This is intentional. Automated semantic equivalence detection is error-prone and domain-dependent. False merges corrupt the graph permanently; false non-merges (duplication) are annoying but recoverable.

How semantic equivalence is handled: Via explicit same_as links (§4.4.1), not automatic merging. When humans or high-confidence automated systems confirm two phrasings mean the same thing, they create a same_as link. Queries can then expand across linked equivalents.

Statement canonicalization:

  1. Unicode: NFC normalization (Canonical Decomposition, followed by Canonical Composition)
  2. Whitespace: collapse all whitespace sequences to single ASCII space (0x20), trim leading/trailing
  3. Case: preserve (scientific terms are case-sensitive; “BRAF” ≠ “braf”)
  4. Quotes: normalize to ASCII straight quotes (U+0022), not curly quotes (U+201C/U+201D)
  5. Dashes: normalize en-dash (U+2013) and em-dash (U+2014) to hyphen-minus (U+002D)
  6. Newlines: replace with single space

Entity reference canonicalization:

  1. Sort by entity_id lexicographically (byte order, not locale-aware)
  2. Normalize role to lowercase ASCII
  3. Remove duplicate entity references

Numeric canonicalization (in statements):

  1. Decimal: remove trailing zeros after decimal point; “1.500” → “1.5”
  2. Leading zeros: remove; “007” → “7”
  3. Scientific notation: lowercase ‘e’, no leading zeros in exponent; “1.5E+03” → “1.5e3”
  4. Units: preserve as written (unit normalization is entity-level, not statement-level)

Hash computation:

  1. Canonicalize statement and entities as above
  2. Encode as UTF-8 bytes
  3. Concatenate: statement_bytes + 0x00 + entities_json_bytes
  4. Compute SHA-256
  5. Encode as lowercase hexadecimal

Test Vectors (normative):

TEST 1: Basic statement
Input:  "BRAF V600E   mutations respond to vemurafenib."
Canon:  "BRAF V600E mutations respond to vemurafenib."
Hash:   a7b3c9d4e5f6...

TEST 2: Unicode normalization  
Input:  "café" (U+0065 U+0301 for é)
Canon:  "café" (U+00E9 for é, NFC form)

TEST 3: Quote normalization
Input:  "The "gold standard" treatment"
Canon:  "The \"gold standard\" treatment"

TEST 4: Whitespace collapse
Input:  "  Multiple   spaces\n\tand\ttabs  "
Canon:  "Multiple spaces and tabs"

TEST 5: Numeric normalization
Input:  "Dose of 1.500mg showed 0.30 response"
Canon:  "Dose of 1.5mg showed 0.3 response"

TEST 6: Entity sorting
Input:  entities: [{id: "gene:BRAF", role: "Subject"}, {id: "drug:vemurafenib", role: "object"}]
Canon:  entities: [{id: "drug:vemurafenib", role: "object"}, {id: "gene:BRAF", role: "subject"}]

TEST 7: Full PointID computation
Statement: "BRAF V600E mutations respond to vemurafenib"
Entities:  [{id: "gene:BRAF", role: "subject"}, {id: "drug:vemurafenib", role: "object"}]
Canon statement: "BRAF V600E mutations respond to vemurafenib"
Canon entities:  [{"id":"drug:vemurafenib","role":"object"},{"id":"gene:BRAF","role":"subject"}]
UTF-8 concat:    <statement_bytes> 0x00 <entities_json_bytes>
SHA-256:         3f7a8b2c1d9e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a
PointID:         pt_3f7a8b2c1d9e4f5a

The reference test suite contains 50+ test vectors covering edge cases. Implementations MUST pass all test vectors before claiming conformance.

Bitemporal Semantics

Points support bitemporal queries over two time dimensions:

This enables queries like:

"What did we believe about BRAF inhibitors in January 2024?"
→ Replay events up to 2024-01, compute state at that transaction time

"What was true about melanoma treatment in 2020, as we understand it now?"
→ Current state, filtered by valid_from <= 2020 AND valid_to > 2020

"When did we learn this finding was contested?"
→ Timestamp of first contested event

Bitemporal semantics are essential for audit, error analysis, and understanding how knowledge evolved.

Evidence is represented as Links (§4.4) from source to point:

EvidenceLink = Link {
  from:         SourceID
  to:           PointID
  type:         evidence_relation
  relation:     EvidenceRelation
  strength:     EvidenceStrength
  independence: Independence?
  excerpt:      Text?
}

EvidenceRelation = 
  | supports           // Evidence supports the point
  | contradicts        // Evidence contradicts the point
  | qualifies          // Evidence adds conditions/constraints
  | replicates         // Independent replication
  | fails_to_replicate // Failed replication attempt

EvidenceStrength =
  | systematic_review   // Meta-analysis, systematic review
  | randomized_trial    // RCT
  | controlled_study    // Non-randomized controlled study
  | observational       // Cohort, case-control
  | case_report         // Individual cases
  | expert_opinion      // Expert assertion
  | computational       // AI/model output
  | anecdotal           // Informal observation

SourceRef {
  type:       SourceType    // paper | trial | notebook | protocol | 
                            // clinical_decision | expert | ai_output
  identifier: Text          // DOI, PMID, internal ID, etc.
  uri:        URI?          // Resolvable link
  title:      Text?
  authors:    [Text]?
  date:       Date?
}

Independence tracking: Ten studies from the same lab using the same method are not ten independent replications—they share systematic biases. The independence field enables confidence calculations to account for correlated evidence. Studies sharing lab_id, method_id, or dataset_id are weighted as partially correlated rather than fully independent.

Constraints

Constraints specify conditions under which the point holds:

Constraint {
  condition:   Text         // Natural language condition
  effect:      Text         // How it modifies the point
  entities:    [EntityRef]? // Entities involved in constraint
  source:      EvidenceID?  // Evidence establishing this constraint
}

Example: For “Dexamethasone reduces mortality in COVID patients”:

Dissent

Dissent records active challenges to a point:

Dissent {
  id:          DissentID
  challenge:   Text           // Nature of the challenge
  evidence:    [EvidenceID]   // Supporting evidence for dissent
  status:      DissentStatus  // active | resolved | acknowledged
  resolution:  Text?          // How it was resolved, if resolved
  created_at:  Timestamp
  created_by:  ContributorID
  resolved_at: Timestamp?
  resolved_by: ContributorID?
}

DissentStatus =
  | active       // Challenge stands, not yet resolved
  | resolved     // Challenge addressed, point updated or dissent withdrawn
  | acknowledged // Disagreement persists, documented for transparency

Dissent is preserved, not erased. A point can show that three trials support it and one challenges it. The structure holds the disagreement rather than hiding it.

State Machine

Points move through states via events (see §4.3 Point Events):

                    ┌─────────────┐
                    │  proposed   │
                    └──────┬──────┘
                           │ validated event

         contested  ┌─────────────┐    superseded
        ┌──────────▶│  validated  │──────────────┐
        │   event   └──────┬──────┘    event     │
        │                  │                     ▼
        │           ┌──────┴──────┐       ┌─────────────┐
        │           │             │       │ superseded  │
        │           ▼             │       └─────────────┘
        │    ┌─────────────┐      │
        └────│  contested  │      │
             └──────┬──────┘      │
                    │             │
                    ▼             ▼
             ┌─────────────────────┐
             │      retracted      │
             └─────────────────────┘

State definitions:

StateDescription
proposedSubmitted, not yet validated
validatedAt least one expert validation, no unresolved contests
contestedActive unresolved challenge
supersededReplaced by newer point
retractedWithdrawn due to error, fraud, or irreproducibility

Transition events:

Event TypeFrom → ToRequires
validatedproposed → validatedValidator with sufficient expertise weight
contestedvalidated → contestedEvidence supporting challenge
contest_resolvedcontested → validatedResolution with outcome
supersededvalidated/contested → supersededNew point with supersession link
retractedany → retractedRetraction evidence
source_retractedany → contestedUpstream source retracted (system-generated)

Every transition is an immutable, signed event (see §4.3 Point Events). Current state is computed by replaying the event log.

Confidence

Confidence is not a number someone assigns—it emerges from the evidence profile. Critically, confidence scoring is a view-level computation, not protocol consensus.

ConfidenceProfile {
  level:       ConfidenceLevel  // Computed category
  score:       Float            // 0.0 to 1.0
  factors: {
    evidence_strength:  Float   // Quality of supporting evidence
    replication_count:  Int     // Independent replications
    dissent_weight:     Float   // Active challenges
    recency:            Float   // How recent is the evidence
    validation_depth:   Int     // Number of validators
  }
  scorer:      ScorerID         // Which scoring function produced this
  computed_at: Timestamp
}

ConfidenceLevel =
  | very_high   // score >= 0.85
  | high        // score >= 0.70
  | medium      // score >= 0.50
  | low         // score >= 0.30
  | very_low    // score < 0.30
  | contested   // Active dissent regardless of score

Protocol vs View separation:

LayerWhat it specifiesWho controls
ProtocolEvidence links, dissent events, validation eventsImmutable, signed
ViewConfidence scores, expertise weights, thresholdsCurator/scorer choice

This separation is intentional. Different communities have different evidence hierarchies:

Rather than force protocol-level agreement on weights, the protocol standardizes inputs (evidence relations, provenance, dissent) and allows multiple scoring functions to compute confidence from those inputs.

Scorer profiles:

Scorer {
  id:           ScorerID
  name:         Text              // "GRADE-aligned", "Conservative", "Exploratory"
  version:      Version
  weights:      WeightConfig      // The scoring parameters
  maintainer:   ContributorID
  signature:    Signature         // Scorer is signed by maintainer
}

Clients can choose which scorer to apply. A clinical decision support system might require “GRADE-aligned” scoring. An exploratory research tool might use “Aggressive” scoring that weights recent preprints higher. Both use the same underlying events and links.

Default scorer (v0.1 baseline):

The following weights are provisional defaults, informed by evidence hierarchies used in clinical practice but not empirically calibrated. Domain-specific implementations should adjust based on field norms and validation studies.

score = (
  evidence_weight(evidence) * 0.35 +
  replication_factor(replications) * 0.25 +
  validation_factor(validators) * 0.20 +
  recency_factor(evidence_dates) * 0.10 +
  (1 - dissent_penalty(dissent)) * 0.10
)

evidence_weight(evidence):
  sum(strength_score[e.strength] * relationship_sign[e.relationship] 
      for e in evidence) / len(evidence)
  
strength_score:
  systematic_review: 1.0    // Based on GRADE hierarchy
  randomized_trial:  0.9
  controlled_study:  0.7
  observational:     0.5
  case_report:       0.3
  expert_opinion:    0.2
  computational:     0.2    // AI outputs require validation
  anecdotal:         0.1

relationship_sign:
  supports:           +1
  replicates:         +1
  qualifies:          +0.5
  fails_to_replicate: -0.8
  contradicts:        -1

Invariants (protocol-level, not scorer-level):

The goal is not perfect calibration. The goal is explicit, queryable, correctable confidence—unlike the implicit confidence laundering that occurs through citation counts and journal prestige.


A Link is a typed relationship between objects. Links make navigation possible. Without links, points are isolated facts. With links, they form queryable structure.

Note on evidence: Evidence relationships are Links from Sources to Points (see §4.3 Evidence Links). This unifies evidence modeling—there is one representation, not two.

Schema

Link {
  id:         LinkID
  from:       ObjectID        // Source, Entity, or Point
  to:         ObjectID        // Source, Entity, or Point
  type:       LinkType        // Relationship type
  relation:   LinkRelation?   // Semantic qualifier (part of identity)
  metadata:   LinkMetadata?   // Non-semantic annotations
  created_at: Timestamp
  created_by: ContributorID
}

LinkType =
  | evidence        // From Source to Point: provides evidence
  | dependency      // Point → Point: assumes/requires
  | dissent         // Point → Point: challenges
  | supersession    // Point → Point: replaces
  | derivation      // Point → Point: derived from
  | association     // Any → Any: related but untyped
  | same_as         // Entity → Entity: equivalence
  | broader_than    // Entity → Entity: hierarchical

LinkRelation {
  kind:         RelationKind    // supports | contradicts | qualifies | replicates | ...
  strength:     EvidenceStrength? // For evidence links
  independence: Independence?   // For replication tracking
}

RelationKind =
  | supports           // Evidence supports the point
  | contradicts        // Evidence contradicts the point
  | qualifies          // Evidence adds conditions/constraints
  | replicates         // Independent replication
  | fails_to_replicate // Failed replication attempt
  | mentions           // Reference without directional support

LinkMetadata {
  excerpt:       Text?         // Relevant quote (not part of identity)
  note:          Text?         // Human annotation
  bidirectional: Boolean       // Whether relationship is symmetric
}

LinkID includes semantic fields:

LinkID = Hash(Canonicalize(from + to + type + relation))

Why relation is part of identity: The same Source can both support AND qualify a Point—these are distinct links. Multiple independent replications of the same finding are distinct links (same from/to/type, different independence in relation). Without including relation in the hash, these cases collapse into one link, losing critical information.

What is NOT part of identity: excerpt and note are annotations that can vary by curator without creating a new link. They live in metadata, not relation.

TypeFrom → ToMeaning
evidenceSource → PointSource provides evidence for Point
dependencyPoint → PointA requires B to be true
dissentPoint → PointA challenges B
supersessionPoint → PointA replaces B
derivationPoint → PointA was derived from B
associationAny → AnyRelated (symmetric)
same_asEntity → EntityEquivalent referents
broader_thanEntity → EntityHierarchical (A contains B)

Dependency Subtypes

Critical for propagation correctness: “depends_on” can mean many things. Imprecise dependency typing leads to noisy propagation, inconsistent graphs, and user distrust. The protocol defines a minimal taxonomy of dependency subtypes for the clinical evidence wedge:

DependencySubtype =
  | included_in_meta_analysis    // Point was data input to meta-analysis
  | evidence_table_row           // Point appears in guideline evidence table
  | guideline_recommendation_basis // Point is cited basis for recommendation
  | statistical_input            // Point's data used in computation
  | narrative_citation           // Point mentioned but not load-bearing
  | logical_premise              // Point is premise in argument chain
  | method_dependency            // Point's method relied upon

Subtype semantics for propagation:

SubtypePropagation BehaviorRationale
included_in_meta_analysisStrong: retraction invalidates meta-analysis resultData integrity compromised
evidence_table_rowStrong: retraction requires table updateDirect evidence linkage
guideline_recommendation_basisStrong: retraction triggers recommendation reviewPatient safety
statistical_inputStrong: retraction invalidates derived statisticsComputational integrity
narrative_citationWeak: notification only, no automatic state changeInformational reference
logical_premiseMedium: retraction flags dependent argumentArgument validity
method_dependencyMedium: retraction flags method-dependent workMethodological concern

Usage in Links:

Link {
  from:     pt_trial_result_123
  to:       pt_meta_analysis_456
  type:     dependency
  relation: {
    subtype:    included_in_meta_analysis
    weight:     0.15    // Contribution weight in meta-analysis
    removable:  true    // Can meta-analysis be recomputed without this?
  }
}

Link {
  from:     pt_efficacy_finding
  to:       pt_guideline_recommendation
  type:     dependency
  relation: {
    subtype:    guideline_recommendation_basis
    strength:   primary   // primary | supporting | contextual
    citation:   "Evidence table row 3.2.1"
  }
}

Why this taxonomy:

Extension mechanism:

// Domain extensions register new subtypes
DependencySubtype =
  | ...core subtypes...
  | x_cochrane_grade_input      // Cochrane-specific
  | x_fda_approval_basis        // FDA regulatory context
  | x_nih_grant_preliminary     // NIH funding context

Extensions MUST specify propagation behavior (strong/medium/weak) for their subtypes.

Multiple links between same nodes:

// Same source, same point, different relations—these are DISTINCT links:

Link { from: src_trial_123, to: pt_efficacy, type: evidence, 
       relation: { kind: supports, strength: rct } }
       
Link { from: src_trial_123, to: pt_efficacy, type: evidence,
       relation: { kind: qualifies, strength: rct } }

// Same source providing both support and qualification is common:
// "Drug X is effective (supports) but only in patients over 65 (qualifies)"

Links enable queries like:

Two points may be semantically equivalent but have different PointIDs due to different phrasing. The same_as link type connects equivalent points without forcing premature merging.

same_as for Points:

same_as_link = Link {
  from:   PointID        // One phrasing
  to:     PointID        // Equivalent phrasing
  type:   same_as
  relation: {
    confidence: Float    // How confident in equivalence (0-1)
    method:     Method   // How equivalence was determined
    evidence:   Text?    // Justification
  }
}

Method =
  | human_judgment      // Curator determined equivalence
  | automated_high_conf // NLP/embedding similarity above threshold
  | community_consensus // Multiple curators agreed

Governance rules:

  1. Proposal: Any contributor can propose a same_as link with justification
  2. Contestation: Others can contest with counter-evidence (e.g., subtle semantic difference)
  3. Resolution: Contested equivalences require curator review; uncontested proposals accepted after 7 days
  4. Asymmetry: same_as is symmetric but must be explicitly bidirectional (two links or bidirectional flag)
  5. Transitivity: If A same_as B and B same_as C, then A same_as C is implied (but not automatically created)

Query behavior:

// Without equivalence expansion
query("BRAF V600E vemurafenib response") → [pt_123]

// With equivalence expansion (default)
query("BRAF V600E vemurafenib response", expand_same_as=true) → [pt_123, pt_456, pt_789]
// Returns pt_123 and all points linked via same_as

Why not automatic merging? Automated semantic matching is error-prone. Two statements may appear equivalent but differ in important ways (“Drug X effective in adults” vs “Drug X effective in elderly adults”). False merges corrupt the graph permanently. False non-merges (duplication) are annoying but recoverable.

same_as for Entities:

Entity equivalence is higher-stakes because entities anchor many points:

// UMLS CUI and custom entity refer to same concept
Link { from: entity:UMLS:C0006142, to: entity:custom:breast_cancer, type: same_as }

Entity same_as links enable cross-ontology queries and bridge to UMLS/OBO vocabularies.


4.5 Trail (Extension)

Note: Trail is an extension primitive, not part of Constellation Core. Implementations MAY support Trails but are not required to for core conformance. Trail is documented here because it is part of the reference implementation and demonstrates the protocol’s extensibility.

A Trail is a recorded path through knowledge—what was searched, what was found, what was decided, and why. Trails capture the reasoning process, not just the conclusion.

Schema

Trail {
  id:          TrailID
  name:        Text?           // Optional descriptive name
  purpose:     Text            // What the trail was trying to accomplish
  steps:       [TrailStep]     // Ordered sequence of actions
  outcome:     TrailOutcome    // How the trail concluded
  created_at:  Timestamp
  created_by:  ContributorID
  visibility:  Visibility      // public | private | group
}

TrailStep {
  sequence:    Int             // Order in trail
  action:      ActionType      // What was done
  target:      StepTarget      // What it was done to
  result:      StepResult?     // What happened
  rationale:   Text?           // Why this action was taken
  timestamp:   Timestamp
}

ActionType =
  | search      // Query the constellation
  | filter      // Narrow results
  | select      // Choose a point for further examination
  | reject      // Explicitly exclude a point (with reason)
  | validate    // Confirm a point
  | decide      // Make a decision based on evidence
  | note        // Add observation without action

StepTarget =
  | { type: "query", query: Query }
  | { type: "point", point_id: PointID }
  | { type: "entity", entity_id: EntityID }
  | { type: "link", link_id: LinkID }

StepResult {
  points_found:    Int?        // For search actions
  points_selected: [PointID]?  // For filter/select actions
  decision:        Text?       // For decide actions
}

TrailOutcome {
  type:        OutcomeType     // concluded | abandoned | ongoing
  summary:     Text            // What was learned/decided
  key_points:  [PointID]       // Most important points in trail
  confidence:  ConfidenceLevel // Confidence in outcome
}

OutcomeType =
  | concluded   // Trail reached a decision/conclusion
  | abandoned   // Trail was stopped without conclusion
  | ongoing     // Trail is still active

TrailID = Hash(purpose + steps + created_by + created_at)

Trail Example

A clinician investigating treatment options:

{
  "purpose": "Determine first-line treatment for BRAF V600E metastatic melanoma",
  "steps": [
    {
      "sequence": 1,
      "action": "search",
      "target": { "type": "query", "query": "BRAF V600E melanoma treatment" },
      "result": { "points_found": 47 },
      "rationale": "Initial broad search"
    },
    {
      "sequence": 2,
      "action": "filter",
      "target": { "type": "query", "query": "confidence >= high AND evidence_type = randomized_trial" },
      "result": { "points_found": 12 },
      "rationale": "Narrowing to high-confidence trial evidence"
    },
    {
      "sequence": 3,
      "action": "select",
      "target": { "type": "point", "point_id": "pt_vemurafenib_response" },
      "rationale": "Phase III data with multiple replications"
    },
    {
      "sequence": 4,
      "action": "reject",
      "target": { "type": "point", "point_id": "pt_single_agent_old" },
      "rationale": "Superseded by combination therapy evidence"
    },
    {
      "sequence": 5,
      "action": "decide",
      "target": { "type": "point", "point_id": "pt_combo_therapy" },
      "result": { "decision": "Recommend dabrafenib + trametinib combination" },
      "rationale": "Superior PFS in Phase III, manageable toxicity profile"
    }
  ],
  "outcome": {
    "type": "concluded",
    "summary": "First-line treatment recommendation: BRAF/MEK inhibitor combination based on Phase III evidence showing superior outcomes vs. monotherapy",
    "key_points": ["pt_combo_therapy", "pt_resistance_timeline"],
    "confidence": "high"
  }
}

Trails teach. A student can follow an expert’s trail and learn not just the conclusion but the reasoning—what was searched, what was rejected and why, how confidence was assessed.


5. Operations

[NORMATIVE]

Operations are the verbs that act on primitives. Each operation has preconditions, effects, and return values.

Event-based semantics: All state-changing operations create immutable, signed events rather than mutating objects directly. “Current state” is computed by replaying the event log. This provides auditability, conflict representation, and verifiable history. Operations that change state return the created Event; the updated View is computed separately.

5.1 Point Operations

propose

Create a new point with an initial evidence link.

propose(
  statement:   Text,
  entities:    [EntityRef],
  source:      SourceID,
  constraints: [Constraint]?,
  contributor: ContributorID,
  signature:   Signature
) → { point: Point, evidence_link: Link, event: PointEvent }

Preconditions:
  - Statement is non-empty
  - All referenced entities exist
  - Source exists
  - Contributor is authenticated

Effects:
  - Point created (PointID computed from statement + entities)
  - Evidence link created from source to point
  - PointEvent created with event_type = proposed
  - Event appended to event log

Returns:
  - Created Point, evidence Link, and PointEvent

Errors:
  - ENTITY_NOT_FOUND: Referenced entity doesn't exist
  - SOURCE_NOT_FOUND: Referenced source doesn't exist

validate

Add an independent validation to a point. Validations accumulate—multiple validations with different evidence types strengthen the point.

validate(
  point_id:    PointID,
  source:      SourceID?,           // Optional: source supporting validation
  validation_type: ValidationType,  // How was this validated?
  note:        Text?,
  contributor: ContributorID,
  signature:   Signature
) → PointEvent

ValidationType =
  | independent_replication  // Different lab replicated the finding
  | meta_analysis           // Included in systematic review/meta-analysis
  | rct_confirmation        // Confirmed by randomized controlled trial
  | mechanistic_support     // Mechanistic evidence supports the claim
  | expert_review           // Domain expert reviewed and endorsed
  | automated_verification  // Computational verification (for methods/data)

Preconditions:
  - Point exists
  - Contributor is authenticated

Effects:
  - PointEvent created with event_type = validated, includes validation_type
  - If source provided, evidence link created with appropriate strength
  - Event appended to event log
  - Point view recomputed (confidence may increase based on validation_type)

Returns:
  - Created PointEvent

Errors:
  - POINT_NOT_FOUND
  - INVALID_SIGNATURE

Validation is not binary. A point with three independent_replication validations is stronger than one with three expert_review validations. The confidence calculation (§4.3) weights validation types:

ValidationWeight = {
  independent_replication: 1.0,   // Strongest evidence
  meta_analysis:           0.9,
  rct_confirmation:        0.85,
  mechanistic_support:     0.6,
  expert_review:           0.4,
  automated_verification:  0.3    // Helps but not definitive
}

Queries can filter by validation type: “Show me points with at least one RCT confirmation” or “Points validated only by expert review.”

contest

Challenge a point with dissent.

contest(
  point_id:    PointID,
  challenge:   Text,
  evidence:    [SourceID],
  contributor: ContributorID,
  signature:   Signature
) → PointEvent

Preconditions:
  - Point exists
  - At least one evidence item supports the challenge
  - Contributor is authenticated

Effects:
  - PointEvent created with event_type = contested
  - Event appended to event log
  - Point view recomputed (state becomes contested)

Returns:
  - Created PointEvent

Errors:
  - POINT_NOT_FOUND
  - INSUFFICIENT_EVIDENCE: No evidence provided for challenge
  - INVALID_SIGNATURE

supersede

Replace a point with a newer version.

supersede(
  old_point_id: PointID,
  new_statement: Text,
  new_entities:  [EntityRef],
  reason:        Text,
  contributor:   ContributorID,
  signature:     Signature
) → { old_event: PointEvent, new_point: Point, new_event: PointEvent }

Preconditions:
  - Old point exists
  - Contributor is authenticated

Effects:
  - PointEvent created for old point with event_type = superseded
  - New point created
  - PointEvent created for new point with event_type = proposed
  - Supersession link created from new to old

Returns:
  - Events for both points

Errors:
  - POINT_NOT_FOUND
  - INVALID_SIGNATURE

retract

Withdraw a point due to error.

retract(
  point_id:    PointID,
  reason:      Text,
  evidence:    [SourceID]?,
  contributor: ContributorID,
  signature:   Signature
) → PointEvent

Preconditions:
  - Point exists
  - Contributor is original proposer OR provides evidence

Effects:
  - PointEvent created with event_type = retracted
  - Event appended to event log
  - Point view recomputed (state becomes retracted)
  - TRIGGERS PROPAGATION to dependent points (see §6)

Returns:
  - Created PointEvent

Errors:
  - POINT_NOT_FOUND
  - UNAUTHORIZED: Not proposer and no evidence
  - INVALID_SIGNATURE

Create a relationship between objects.

link(
  from:        ObjectID,       // PointID, SourceID, or EntityID
  to:          ObjectID,
  type:        LinkType,
  relation:    LinkRelation?,
  contributor: ContributorID,
  signature:   Signature
) → Link

Preconditions:
  - From object exists
  - To object exists
  - No duplicate link (same from, to, type, relation)
  - Contributor is authenticated

Effects:
  - Link created
  - If type = evidence, target point confidence recomputed
  - If type = dependency, dependency graph updated

Returns:
  - Created Link

Errors:
  - POINT_NOT_FOUND
  - DUPLICATE_LINK
  - CYCLE_DETECTED: For dependency links, prevents circular dependencies

5.3 Trail Operations

record_trail

Create or update a trail.

record_trail(
  trail:       Trail,
  contributor: ContributorID
) → Trail

Preconditions:
  - All referenced points exist
  - Contributor is authenticated

Effects:
  - Trail created or updated
  - Referenced points gain trail reference (for discoverability)

Returns:
  - Created/updated Trail

append_step

Add a step to an ongoing trail.

append_step(
  trail_id:    TrailID,
  step:        TrailStep,
  contributor: ContributorID
) → Trail

Preconditions:
  - Trail exists
  - Trail.outcome.type = ongoing
  - Contributor is trail creator

Effects:
  - Step appended to trail
  - Step.sequence assigned

Returns:
  - Updated Trail

6. Propagation

[NORMATIVE]

Propagation is correction at scale. When a source or point’s state changes in ways that affect reliability, that change must reach everything that depends on it.

Critical clarification: Propagation guarantees alerts, not truth.

Propagation does NOT mean:

Propagation DOES mean:

The protocol propagates structured signals about evidence state changes. Whether a retracted source invalidates a point is a domain judgment—the protocol ensures that judgment can be made with full information.

6.1 Triggering Events

Propagation triggers on:

EventScopePropagation Effect
Source retractedAll points citing sourceAuto-generate source_retracted event; confidence recomputed
Source correctedAll points citing sourceNotification to review; confidence may adjust
Point retractedAll dependent pointsDependents notified, confidence recomputed
Point contestedDependent points with evidence linksConfidence recomputed
Evidence contradictsTarget pointConfidence recomputed, may trigger contested state
Evidence supportsTarget pointConfidence recomputed

Source → Point propagation is the flagship capability. When a paper is retracted:

  1. Source enters retracted state via SourceEvent
  2. System queries all Points with evidence links from that Source
  3. For each Point, a source_retracted PointEvent is auto-generated
  4. Point confidence is recomputed with retracted evidence weighted to zero
  5. If confidence drops below threshold, point may transition to contested
  6. Downstream dependents are recursively notified

6.2 Propagation Algorithm

// Source retraction propagation
propagate_source_retraction(source_id: SourceID):
  
  // Find all points citing this source (via evidence links)
  evidence_links = query_links(from = source_id, type = evidence)
  affected_points = unique([link.to for link in evidence_links])
  
  for each point_id in affected_points:
    
    // Auto-generate source_retracted event
    event = PointEvent {
      point_id: point_id,
      event_type: source_retracted,
      evidence: [source_id],
      note: "Upstream source retracted: " + source_id,
      actor: "system",  // System-generated
      timestamp: now()
    }
    append_event(event)
    
    // Recompute point state and confidence
    recompute_point_view(point_id)
    
    // Propagate to downstream dependents
    propagate_point_change(point_id, event)

// Point change propagation  
propagate_point_change(point_id: PointID, event: PointEvent):
  
  // Find all points that depend on this one
  dependents = find_dependents(point_id)
  
  for each dependent in dependents:
    
    // Recompute confidence
    old_confidence = dependent.confidence
    new_confidence = compute_confidence(dependent)
    
    // Check for state transitions
    if event.event_type in [retracted, source_retracted]:
      if evidence_relies_primarily_on(dependent, point_id):
        create_contest_event(dependent, "Key evidence retracted: " + point_id)
    
    if new_confidence.level != old_confidence.level:
      log_confidence_change(dependent, old_confidence, new_confidence)
    
    if confidence_drop_significant(old_confidence, new_confidence):
      notify_subscribers(dependent, "Confidence decreased")
    
    // Recursive propagation for significant changes
    if should_propagate_further(event, dependent):
      propagate_point_change(dependent.id, derived_event(event))

find_dependents(point_id: PointID) → [PointID]:
  // Find points that have evidence links from this point
  evidence_links = query_links(from = point_id, type = evidence)
  
  // Find points that have dependency links to this point
  dependency_links = query_links(from = point_id, type = dependency)
  
  return unique([l.to for l in evidence_links + dependency_links])

should_propagate_further(event, dependent) → Boolean:
  // Propagate retractions fully
  if event.event_type in [retracted, source_retracted]: return true
  
  // Propagate significant confidence changes
  if event.confidence_delta > 0.2: return true
  
  // Stop propagation for minor updates
  return false

Deterministic Propagation Events

Problem: If multiple indexers auto-generate source_retracted events for the same point, you get duplicates. If only one “canonical” indexer generates them, you have centralization.

Solution: Propagation events are deterministic and content-addressed. Any indexer can generate them, but identical events have identical IDs:

PropagationEvent {
  id:           EventID    // Hash(event_type + point_id + trigger_event_id)
  event_type:   source_retracted | confidence_degraded | ...
  point_id:     PointID    // Affected point
  trigger:      EventID    // The event that caused propagation
  actor:        "system"   // Not a human contributor
  timestamp:    null       // Deterministic events have no timestamp in hash
  generated_at: Timestamp  // When this indexer generated it (not part of ID)
}

Why this works:

What is NOT deterministic:

6.3 Consistency Model

Propagation is eventual, not immediate. Nodes may temporarily have inconsistent views.

Event Ordering: Partial Order with Causal Metadata

Events are partially ordered, not totally ordered. The protocol does not impose a global sequence number. Instead:

Event {
  id:           EventID           // Hash of event content
  ...
  causal_deps:  [EventID]         // Events this event depends on (causal parents)
  lamport_ts:   Integer           // Logical timestamp for ordering hints
}

Causal dependencies: When an actor creates an event, they include the IDs of events they have observed that are relevant. For example:

Lamport timestamps: Each node maintains a logical clock. On event creation: lamport_ts = max(observed_timestamps) + 1. This provides a total order hint but does not guarantee global consistency.

Consistency Guarantees

PropertyGuaranteeMechanism
ConvergenceSame events → same viewsDeterministic materialization function
Causal consistencyIf A caused B, see A before Bcausal_deps + topological sort
DurabilityAccepted events are not lostReplication to N nodes before ack
AvailabilityReads always succeedLocal materialized views

What is NOT guaranteed:

Materialization Under Concurrency

When materializing a view from the event log:

materialize(events: [Event]) → View:
  // 1. Topological sort by causal_deps
  sorted = topological_sort(events, by = causal_deps)
  
  // 2. For causally independent events, use lamport_ts as tiebreaker
  sorted = stable_sort(sorted, by = lamport_ts)
  
  // 3. Apply events in order to compute state
  state = initial_state
  for event in sorted:
    state = apply(state, event)
  
  // 4. Surface unresolved conflicts
  conflicts = find_conflicting_events(sorted)
  
  return View { state, conflicts, computed_at: now() }

Conflict detection: Two events conflict if:

Conflicts are surfaced in the view, not silently resolved. Resolution requires an explicit resolution event.

Consistency Boundaries

Strong consistency within an indexer: A single indexer can provide linearizable reads/writes for its own operations.

Eventual consistency across indexers: Different indexers may temporarily disagree. The protocol ensures they converge given the same event set.

Recommended operational target: 95% of events propagated to all major indexers within 1 hour. This is an SLO for hosted indexers, not a protocol guarantee.


7. Distribution

[NORMATIVE]

The constellation is distributed by design—but distributed does not mean decentralized utopia.

Realistic steady state: A few major indexers will operate the most complete nodes with the best UIs. Most participants will be thin clients contributing to and querying from these indexers. This is the GitHub pattern, and it is not inherently bad. The protocol’s job is to ensure that (a) switching costs remain low, (b) data is not captured, and (c) governance cannot be unilaterally captured.

7.1 Network Model

Nodes are peers. Any node can:

Node types:

TypeDescriptionRequirements
Full indexerComplete event log, serves queries, runs materializationHigh storage, bandwidth
Domain nodeEvents for specific entity typesMedium storage
Light nodeQueries only, no hostingMinimal
Bootstrap nodeWell-known entry point, high availabilityStability, uptime

Network bootstrap:

A new node joins the network through:

  1. Bootstrap discovery: Connect to well-known bootstrap nodes (hardcoded or DNS-based)
  2. Peer exchange: Receive list of active peers from bootstrap nodes
  3. Event log sync: Request event log from multiple peers
  4. Verification: Validate content hashes and signatures for received events
  5. Materialization: Compute current views from event log
  6. Announcement: Register with peers to receive updates

Minimum viable network: 3 nodes with distinct operators. The protocol functions with any number of nodes, but resilience requires distribution across independent infrastructure.

Preventing capture:

7.2 Replication

Events are replicated across multiple nodes. Replication factor is configurable per deployment (minimum 3 recommended).

Content-addressability ensures consistency: the same event, created anywhere, has the same ID. Nodes verify event integrity by recomputing the content hash and validating the signature.

7.3 Conflict Representation

For content objects (Point, Source, Entity): No conflicts possible. Same content = same ID. Different content = different objects.

For state (via events): Conflicts are represented, not silently resolved. When two actors submit conflicting events (e.g., one validates, another contests), both events enter the log. The materialized view computes state from the event log and surfaces conflicts explicitly:

// Two validators disagree
Event 1: { type: validated, actor: alice, point_id: pt_123 }
Event 2: { type: contested, actor: bob, point_id: pt_123 }

// Materialized view shows conflict
PointView {
  state: contested,  // Conflict triggers contested state
  conflicts: [
    { event_a: Event1, event_b: Event2, resolution: pending }
  ]
}

Resolution requires an explicit contest_resolved event with outcome and evidence. This is not last-write-wins; it is explicit conflict surfacing with required resolution.

For evidence links: Additive only. Evidence accumulates; it is not overwritten.

7.4 Sync Protocol

Nodes synchronize via event log exchange. This section specifies the minimum viable sync protocol required for conformance.

Wire Format

All messages are JSON over HTTPS. Nodes MUST support TLS 1.3.

SyncMessage {
  protocol_version: "0.8"
  message_type:     MessageType
  sender:           NodeID
  timestamp:        Timestamp
  payload:          Payload
  signature:        Signature?  // Required for state-changing messages
}

MessageType =
  | checkpoint_request   // "What's your latest state?"
  | checkpoint_response  // "Here's my checkpoint"
  | events_request       // "Send me events since X"
  | events_response      // "Here are the events"
  | event_push           // "I have a new event"
  | peer_list_request    // "Who else is online?"
  | peer_list_response   // "Here are known peers"

Checkpoint Exchange

Checkpoints are Merkle roots over the event log, computed at regular intervals.

Checkpoint {
  checkpoint_id:   CheckpointID   // Hash of checkpoint content
  event_count:     Integer        // Total events at this checkpoint
  merkle_root:     Hash           // Root of Merkle tree over events
  timestamp:       Timestamp      // When checkpoint was computed
  previous:        CheckpointID?  // Previous checkpoint (chain)
}

CheckpointID = Hash(merkle_root + event_count + timestamp)

Checkpoint request:

POST /sync/checkpoint
{ "since_checkpoint": CheckpointID? }

Response:
{
  "checkpoint": Checkpoint,
  "events_available": Integer  // Events since requested checkpoint
}

Event Synchronization

Pull events (client requests):

POST /sync/events
{
  "since_checkpoint": CheckpointID,
  "max_events": Integer,        // Limit per request (max 1000)
  "event_types": [EventType]?   // Optional filter
}

Response:
{
  "events": [Event],
  "has_more": Boolean,
  "next_cursor": Cursor?
}

Push events (server notifies):

POST /sync/push
{
  "events": [Event]
}

Response:
{
  "accepted": [EventID],
  "rejected": [{ id: EventID, reason: Text }]
}

Verification Rules

Receiving nodes MUST verify before accepting events:

  1. Signature verification: Event signature is valid for the stated actor
  2. Hash verification: EventID matches computed hash of event content
  3. Causal ordering: All events in causal_deps exist in local log
  4. Temporal ordering: Lamport timestamp is consistent with causal_deps

Events failing verification MUST be rejected with reason.

Convergence Guarantee

Two conformant implementations, given the same set of events, MUST produce identical materialized views. This is the core interoperability requirement.

Test procedure:

  1. Generate 1000 random valid events
  2. Shuffle into two different orderings
  3. Feed each ordering to different implementations
  4. Compare materialized views (must be identical)
  5. Repeat with conflict scenarios

The reference test suite includes 500+ event sequences for conformance testing.

Minimal Implementation

A conforming sync implementation MUST support:

A conforming sync implementation SHOULD support:

Operational SLOs and Scaling

[PROFILE — recommended for production deployments]

Real networks need bounded behavior. This section specifies operational expectations.

Event Volume Expectations:

ScaleEvents/DayStorage GrowthSync Bandwidth
Pilot (single domain)1K-10K~10 MB/day~100 MB/day
Regional (multi-domain)100K-1M~1 GB/day~10 GB/day
Global (full corpus)10M-100M~100 GB/day~1 TB/day

Recommended SLOs for production indexers:

MetricTargetRationale
Event ingestion latencyp99 < 5sReal-time alerting requires fast ingestion
Sync convergence95% of events within 1 hourCorrection propagation usefulness
Query latencyp99 < 500msInteractive tool responsiveness
Checkpoint intervalEvery 10K events or 1 hourBalance freshness vs overhead
Uptime99.9% monthlyInfrastructure-grade reliability

Anti-Spam and Abuse Controls:

RateLimits {
  // Per-contributor limits (by public key)
  events_per_hour:        100      // Proposals, validations, etc.
  points_per_day:         500      // New point proposals
  links_per_day:          1000     // New link proposals
  
  // Per-source-IP limits (unauthenticated)
  queries_per_minute:     60
  sync_requests_per_hour: 100
  
  // Global limits (indexer-wide)
  max_event_size_bytes:   1_000_000  // 1MB per event
  max_batch_size:         1000       // Events per sync request
}

AbuseDetection {
  // Patterns that trigger review/blocking
  duplicate_content:      true      // Same point proposed repeatedly
  citation_spam:          true      // Mass low-quality links
  coordinated_validation: true      // Suspicious validation patterns
  identity_cycling:       true      // New keys to evade limits
}

Cache and Checkpoint Retention:

RetentionPolicy {
  // Event log (append-only, never deleted)
  event_log:              permanent
  
  // Checkpoints (periodic snapshots)
  checkpoint_retention:   90 days   // Keep last 90 days of checkpoints
  checkpoint_interval:    1 hour    // Or every 10K events
  
  // Materialized views (recomputable)
  view_cache_ttl:         24 hours  // Refresh daily minimum
  hot_cache_ttl:          5 minutes // Frequently accessed points
  
  // Sync state (per-peer)
  peer_state_retention:   30 days   // Track sync progress
  inactive_peer_cleanup:  7 days    // Remove stale peer records
}

Partial Replication (Lite Node) Semantics:

Full indexers store the complete event log. Lite nodes store subsets:

LiteNodeConfig {
  replication_filter: ReplicationFilter
  materialization:    MaterializationMode
  sync_mode:          SyncMode
}

ReplicationFilter =
  | by_domain([Text])           // Only events for specific domains
  | by_entity([EntityID])       // Only events mentioning entities
  | by_curator_set(CuratorSetID) // Only events from trusted curators
  | by_recency(Duration)        // Only events from last N days

MaterializationMode =
  | full                        // Compute all views locally
  | on_demand                   // Fetch views from full indexer
  | cached                      // Cache views with TTL

SyncMode =
  | pull_only                   // Only request events (no push)
  | selective_push              // Push only events matching filter
  | relay                       // Accept and forward all events

Lite node guarantees:

Alert fatigue prevention:

When dependency links are broad, propagation can cascade widely. Indexers SHOULD implement:

PropagationThrottling {
  // Limit alerts per user per time window
  max_alerts_per_hour:     50
  max_alerts_per_day:      200
  
  // Prioritize by dependency strength
  alert_priority:          by_subtype  // Strong deps first
  
  // Batch related alerts
  batching_window:         15 minutes
  
  // User controls
  allow_user_filtering:    true        // User can mute domains/types
  require_ack_for_critical: true       // Force-show safety-critical
}

7.5 Relationship to Decentralized Science (DeSci)

The Constellation Protocol shares goals with the emerging DeSci movement: open access, transparent provenance, distributed governance. Both reject centralized gatekeeping. Both prioritize researcher attribution and reproducibility.

Alignment:

Distinction: The protocol is blockchain-agnostic. It can run on blockchain infrastructure (for immutability guarantees) or on traditional distributed systems (for performance). The protocol specifies what must be true, not which technology enforces it. DeSci projects using DAOs, IP-NFTs, or token incentives can implement the Constellation Protocol as their knowledge layer. Traditional institutions can implement it without blockchain. The protocol bridges both worlds.

7.6 Curated Views

Raw event logs contain everything: high-quality validated points, noisy extractions, spam attempts, contentious disputes. End users need filtered views. Curated views are a first-class protocol concept, not an implementation detail.

Curator Sets

CuratorSet {
  id:           CuratorSetID
  name:         Text              // "Cochrane-validated", "Conservative-clinical", "Exploratory"
  description:  Text
  curators:     [ContributorID]   // Who can add to this set
  criteria:     CurationCriteria  // What points are included
  scorer:       ScorerID          // Which confidence scorer to use
  maintainer:   ContributorID
  signature:    Signature
  version:      Version
  updated_at:   Timestamp
}

CurationCriteria {
  min_validation_count:  Int?      // Require N validators
  required_expertise:    [Text]?   // Validators must have these domains
  excluded_states:       [PointState]?  // Exclude retracted, etc.
  source_requirements:   SourceFilter?  // Only peer-reviewed, only open-access, etc.
  domain_scope:          [Text]?   // Only oncology, only cardiology, etc.
}

Discovery and Trust

Clients discover curator sets through:

  1. Well-known sets: Hardcoded in major clients (e.g., “Cochrane-validated” for clinical tools)
  2. Indexer recommendations: Indexers publish which curator sets they endorse
  3. Institutional attestation: Universities/hospitals sign curator sets they trust
  4. Web of trust: Curator sets can reference other curator sets they build on

Default Behavior

Clients SHOULD default to a conservative curator set that:

Clients MAY allow users to expand to “all points” view with explicit confirmation.

Reproducibility

A curated view is reproducible if:

This enables citations of the form: “As of CuratorSet cochrane-oncology-v3 at checkpoint abc123, point pt_xyz had confidence high.”

7.6.1 Trust-Set Client Model

[NORMATIVE for clients claiming Constellation conformance]

Users interact with views, not raw graphs. Clients MUST implement a standard trust-set model to ensure consistent behavior across implementations and prevent UI-level “truthiness” when the graph is disputed.

Trust Bundle Schema:

TrustBundle {
  id:              TrustBundleID
  name:            Text                    // "Clinical Guidelines Bundle"
  curator_sets:    [CuratorSetRef]         // Ordered by priority
  conflict_policy: ConflictPolicy          // How to handle disagreements
  update_policy:   UpdatePolicy            // How to handle curator set changes
  signature:       Signature               // Publisher signature
  published_at:    Timestamp
  expires_at:      Timestamp?              // Optional expiry
}

CuratorSetRef {
  curator_set_id:  CuratorSetID
  version:         Version                 // Pin to specific version
  trust_level:     TrustLevel              // primary | secondary | informational
}

TrustLevel =
  | primary        // Points from this set shown by default
  | secondary      // Points shown with "secondary source" indicator
  | informational  // Points available but not shown by default

ConflictPolicy =
  | show_all       // Display all conflicting assessments
  | prefer_primary // Show primary, note conflicts exist
  | require_consensus // Only show if all curator sets agree

UpdatePolicy =
  | auto_update    // Accept new versions automatically
  | notify         // Notify user, require confirmation
  | pin            // Never update without explicit action

Client Requirements:

  1. Trust bundle import:

    // Client MUST support importing trust bundles
    import_trust_bundle(bundle: TrustBundle) → Result
    
    // Client MUST verify bundle signature before import
    // Client MUST check bundle expiry
    // Client MUST store bundle version for audit
  2. Conflict display:

    // When points have conflicting states across curator sets:
    ConflictDisplay {
      point_id:       PointID
      assessments:    [CuratorAssessment]    // One per curator set
      display_state:  DisplayState           // Computed per conflict policy
      user_override:  Boolean                // User explicitly chose a view
    }
    
    CuratorAssessment {
      curator_set:    CuratorSetID
      state:          PointState
      confidence:     ConfidenceLevel
      last_updated:   Timestamp
    }
  3. Conflict UI requirements:

    • Clients MUST NOT display a single “truth” when curator sets disagree
    • Clients MUST show a conflict indicator when assessments differ
    • Clients MUST allow users to see all assessments on demand
    • Clients SHOULD show which curator set each assessment comes from
  4. Curator set revocation:

    CuratorSetRevocation {
      curator_set_id:  CuratorSetID
      revoked_at:      Timestamp
      reason:          Text
      successor:       CuratorSetID?         // Replacement if available
      signature:       Signature             // Maintainer or governance signature
    }

    When a curator set is revoked:

    • Clients MUST stop using the revoked set for new queries
    • Clients MUST notify users who have the set in their trust bundle
    • Clients SHOULD suggest migration to successor if available
    • Clients MUST NOT silently continue using revoked sets
  5. Truthiness prevention:

    Clients MUST NOT:

    • Display disputed points without conflict indicators
    • Hide the source of assessments (which curator set)
    • Present confidence scores as “ground truth”
    • Auto-resolve conflicts without user awareness

    Clients MUST:

    • Show provenance for all displayed states
    • Indicate when confidence is computed vs. curator-assigned
    • Distinguish “no data” from “contested” from “validated”
    • Preserve user’s trust bundle choices across sessions

Example client flow:

// User queries a point
query_result = query(point_id, trust_bundle)

if query_result.has_conflicts:
  // Display with conflict indicator
  show_point(
    state: query_result.display_state,
    conflict_badge: true,
    tooltip: "2 curator sets disagree on this point's status"
  )
  
  // On click, show full breakdown
  show_conflict_detail(
    assessments: query_result.assessments,
    policy: trust_bundle.conflict_policy
  )
else:
  // Display normally with provenance
  show_point(
    state: query_result.state,
    source: query_result.curator_set.name,
    confidence: query_result.confidence
  )

Well-known trust bundles:

The protocol defines three well-known bundle identifiers that clients SHOULD recognize:

Bundle IDPurposeTypical Curator Sets
constellation:clinical-conservativeClinical decision supportCochrane, NICE, USPSTF
constellation:research-broadResearch explorationOpenAlex-derived, preprint-inclusive
constellation:regulatory-auditCompliance/audit trailFDA-aligned, full provenance required

8. Identity and Attribution

[PROFILE]

8.1 Contributors

Contributors are identified by cryptographic keys, optionally linked to verified identity:

Contributor {
  id:              ContributorID    // Derived from public key
  public_key:      PublicKey
  display_name:    Text?
  orcid:           ORCID?           // Verified ORCID linkage
  affiliations:    [Affiliation]?
  expertise:       [ExpertiseArea]
  reputation:      ReputationScore
  created_at:      Timestamp
}

ExpertiseArea {
  domain:          Text    // "oncology", "genomics", "cardiology", etc.
  weight:          Float   // 0.0 to 1.0
  attestations:    [Attestation]  // How expertise was established
}

Attestation {
  type:    AttestationType  // credential | peer | contribution | orcid
  source:  Text
  date:    Date
  proof:   Text?            // For ORCID: signed challenge-response
}

8.2 ORCID Attestation

For regulatory contexts (EU AI Act, FDA AI/ML guidance) and high-stakes domains (clinical, pharmaceutical), identity attestation is critical. The protocol supports ORCID linkage:

Attestation flow:

  1. Contributor generates key pair, creating ContributorID
  2. Contributor initiates ORCID attestation via OAuth flow
  3. Protocol gateway issues signed challenge containing ContributorID
  4. Contributor signs challenge with ORCID-authorized key
  5. Gateway verifies signature and records ORCID linkage
  6. Linkage is stored as Attestation with type: orcid

What ORCID linkage enables:

ORCID linkage is optional for general contribution but may be required for specific domains or operations.

8.3 Expertise Weighting

Validation weight depends on domain expertise. A hematologist’s validation of a hematology point carries more weight than a layperson’s.

Initial expertise can be established by:

Expertise weight affects:

8.4 Pseudonymity

Real-world identity is optional. Contributors may use:

All contributions are signed. Reputation accrues to keys, not names.


9. Interfaces

[PROFILE]

9.1 Query Interface

query(
  entities:        [EntityRef]?,     // Points about these entities
  confidence_min:  Float?,           // Minimum confidence score
  confidence_level: [ConfidenceLevel]?, // Filter by level
  states:          [PointState]?,    // Filter by state
  evidence_types:  [EvidenceStrength]?, // Filter by evidence quality
  created_after:   Timestamp?,
  created_before:  Timestamp?,
  text_search:     Text?,            // Full-text search in statements
  limit:           Int?,
  offset:          Int?
) → QueryResult

QueryResult {
  points:      [Point]
  total_count: Int
  facets: {
    by_state:      Map<PointState, Int>
    by_confidence: Map<ConfidenceLevel, Int>
    by_entity:     Map<EntityID, Int>
  }
}

Example queries:

// All high-confidence points about BRAF mutations
query(
  entities: [{ entity_id: "ent_braf", role: "subject" }],
  confidence_level: [very_high, high],
  states: [validated]
)

// Contested points in oncology from the last year
query(
  text_search: "melanoma OR carcinoma",
  states: [contested],
  created_after: "2025-01-01"
)

9.2 Extraction Interface

For LLM-assisted point extraction from documents:

extract(
  source:      SourceRef,
  content:     Text,           // Full text or relevant section
  extractor:   ExtractorConfig
) → ExtractionResult

ExtractorConfig {
  model:           Text        // LLM model identifier
  prompt_version:  Text        // Extraction prompt version
  confidence_threshold: Float  // Minimum confidence to include
}

ExtractionResult {
  proposed_points: [ProposedPoint]
  extraction_metadata: {
    model:        Text
    duration_ms:  Int
    tokens_used:  Int
  }
}

ProposedPoint {
  statement:     Text
  entities:      [EntityRef]    // Extracted entity references
  evidence_text: Text           // Supporting text from source
  constraints:   [Text]?        // Identified constraints
  confidence:    Float          // Extraction confidence
  needs_review:  [ReviewFlag]   // What needs human attention
}

ReviewFlag =
  | entity_ambiguous     // Entity reference unclear
  | confidence_low       // Extraction confidence below threshold
  | constraint_complex   // Constraints need expert review
  | potential_duplicate  // Similar point may exist

Extraction produces proposed points. Humans validate or reject. The bottleneck shifts from reading to review.

9.3 Validation Interface

submit_validation(
  point_id:      PointID,
  decision:      ValidationDecision,
  attestation:   Text,
  corrections:   [Correction]?,
  contributor:   ContributorID,
  signature:     Signature
) → ValidationResult

ValidationDecision =
  | approve           // Point is accurate as stated
  | approve_with_corrections  // Point is accurate with corrections
  | reject            // Point is inaccurate or unsupported
  | defer             // Cannot assess, need additional expertise

Correction {
  field:     Text     // Which field to correct
  original:  Text     // Original value
  corrected: Text     // Corrected value
  reason:    Text     // Why correction is needed
}

ValidationResult {
  point:           Point           // Updated point
  state_changed:   Boolean
  new_state:       PointState?
  validation_recorded: Boolean
}

9.4 Agent Interface (MCP)

The constellation exposes itself to AI agents via the Model Context Protocol (MCP), the emerging standard for connecting AI systems to external tools and data.

MCP Resources:

The constellation exposes three resource types:

Resource: constellation://points/{point_id}
  Returns: Point with evidence, confidence, and state
  
Resource: constellation://entities/{entity_id}
  Returns: Entity with aliases, external references, equivalences
  
Resource: constellation://trails/{trail_id}
  Returns: Trail with steps and reasoning path

MCP Tools:

Tool: query_points
  Parameters: entities, confidence_level, states, text_search, created_after
  Returns: Matching points with metadata

Tool: find_related
  Parameters: point_id, relationship_types, max_hops
  Returns: Related points via link traversal

Tool: check_frontier
  Parameters: entity_id or point_id
  Returns: Frontier distance, nearby contested points

Tool: analyze_gaps
  Parameters: entity_id, gap_type (structural | predictive | coverage)
  Returns: Ranked gap analysis for entity
  
Tool: submit_point
  Parameters: statement, entities, evidence, source
  Returns: Proposed point ID, validation requirements

Why MCP matters:

AI agents like Claude Code, Codex, and research assistants operate by calling tools. MCP standardizes how they discover and invoke those tools. A constellation MCP server enables any MCP-compatible agent to:

Without MCP, each agent needs custom integration. With MCP, one implementation serves the entire ecosystem of AI tools.

AI Transparency Support:

When AI agents submit points through MCP, the constellation records extraction provenance—which model, what prompt, what source. The created_by field identifies AI contributors distinctly from human contributors. This creates an audit trail for AI-generated knowledge claims, supporting the emerging interpretability-as-governance paradigm where AI actions must be traceable and verifiable. As AI-generated science grows, this transparency becomes essential for trust.

Full MCP server specification deferred to companion document. Reference implementation: github.com/borrowed-light/constellation-mcp-server/

9.5 Preprint Integration

The 2025 shift to preprint-first publishing—driven by HHMI, Gates Foundation, and NIH policies—creates a structured extraction pipeline.

Sources:

Extraction Pipeline:

1. Monitor preprint servers for new submissions (RSS, API)
2. Extract structured claims from abstracts and results sections
3. Propose points with source.type = "preprint"
4. Track version updates as preprints are revised
5. Link peer review comments as validation or dissent evidence
6. Update confidence when journal publication occurs

Policy Alignment:

The constellation becomes the structured layer that preprints lack—turning rapid dissemination into navigable, correctable knowledge. A preprint is a document; a point extracted from it is an addressable, versionable assertion.


10. Security and Privacy

[PROFILE]

An open knowledge graph is an attractive target. Spam, misinformation, and manipulation are not theoretical risks—they are guaranteed. The protocol’s security model assumes adversarial actors from day one.

10.1 Threat Model

ThreatMitigation
Spam pointsReputation-weighted submission; validation required
Malicious validationExpertise weighting; multiple validators for high-stakes points
Point manipulationContent-addressable IDs; cryptographic signatures
Network attacksDistributed architecture; no single point of failure
Privacy leakagePHI never enters constellation; trails reference points, not patients

10.2 Signatures

All writes are signed by contributor keys:

Nodes verify signatures before accepting writes.

10.3 Write Admission

Signatures prove authorship. They do not prove trustworthiness. An open protocol with unrestricted writes becomes a spam swamp.

Protocol requirement: All writes MUST be signed. Indexers MUST verify signatures.

Policy flexibility: The protocol does NOT specify rate limits, reputation formulas, or admission tiers. These are indexer policies, not protocol invariants. Different indexers can implement different policies while remaining protocol-compliant.

Why this matters: Reputation systems and admission policies are contentious and will evolve. Embedding specific formulas in the protocol core would:

What the protocol DOES specify:

WriteRequest {
  event:      Event           // The event being submitted
  signature:  Signature       // Proof of authorship
  // No reputation score, no tier - those are indexer concerns
}

WriteResponse {
  accepted:   Boolean
  event_id:   EventID?        // If accepted
  reason:     Text?           // If rejected
}

What indexers decide:

Reference profile: A recommended admission policy is documented at github.com/borrowed-light/constellation-protocol/profiles/admission-policy.md. Indexers MAY adopt it, adapt it, or ignore it.

10.4 Trust Boundary

The trust boundary in Constellation is the curator set (§7.6), not the indexer. Users trust curator sets, which specify which contributors and validation standards they accept. This is analogous to Git’s trust model: you trust the repository you cloned, not “Git” abstractly.

10.5 Access Control

Read access: Public by default. Points are open knowledge.

Write access: Authenticated contributors only. Indexer policies determine rate limits and capabilities.

Moderation: Disputed content can be flagged. Resolution requires evidence, not authority.

10.6 PHI and Privacy

The constellation stores knowledge, not patient data.

Copyright and licensing determine institutional participation more than most technical decisions. The protocol takes explicit positions:

What is stored

Content TypeStorage PolicyRationale
Bibliographic metadataStored verbatimFacts not copyrightable; Crossref/OpenAlex precedent
Point statementsOriginal text, not copiedAssertions are authored by extractors/contributors
Evidence excerptsShort quotes only (<100 words)Fair use for commentary/criticism
Full textNever storedSource reference only; reader fetches from publisher

Paraphrase-first policy: When extracting claims from sources, extractors SHOULD paraphrase rather than quote. The Point statement is the extractor’s formulation of the claim, not copied text. This reduces copyright exposure and forces extractors to demonstrate understanding.

Source licensing requirements

Source TypeIngestion Policy
Open access (CC-BY, CC0)Full extraction permitted
Public access (NIH, preprints)Metadata + abstract extraction; full text via API
PaywalledMetadata only; no excerpt storage
Unknown licenseMetadata only; conservative default

Excerpt guidelines

When excerpts are stored (in LinkMetadata):

Institutional participation

Institutions joining as indexer operators or major contributors SHOULD:

The protocol does not provide legal advice. These policies reflect conservative interpretations intended to enable broad participation while respecting intellectual property.

10.8 Compliance Appendix: Deployment Playbook

This section provides operational guidance for institutional deployment.

What Constellation Stores

STORED:
├── Point statements (original text by contributors, not copied from sources)
├── Entity definitions (names, identifiers, relationships)
├── Link metadata (type, relation, strength — NOT full excerpts from paywalled sources)
├── Event log (signed state transitions)
├── Source references (DOIs, PMIDs, URLs — NOT full text)
└── Contributor identifiers (public keys, optional ORCID linkage)

NOT STORED:
├── Full text of any published article
├── Protected health information (PHI)
├── Personally identifiable information beyond public contributor profiles
├── Copyrighted excerpts > 100 words
└── Content from paywalled sources without explicit license

Takedown Procedure

If a rights holder claims content infringement:

  1. Receipt: Log takedown request with timestamp, claimant identity, specific content identified
  2. Review (48 hours): Verify claim specificity; request clarification if needed
  3. Assessment: Determine if content falls under:
    • Bibliographic metadata (not copyrightable)
    • Original Point statement (not copied)
    • Fair use excerpt (<100 words, commentary purpose)
    • Potential infringement
  4. Action:
    • If clearly non-infringing: Respond with explanation
    • If uncertain: Remove pending review; notify contributor
    • If infringing: Remove; notify contributor; log for audit
  5. Appeal: Contributor may appeal with counter-evidence
  6. Restoration: If counter-claim valid, restore within 14 days

Jurisdictional Considerations

JurisdictionKey RequirementsConstellation Approach
US (DMCA)Safe harbor requires takedown procedureImplement §512 compliant process
EU (DSA)Transparency, illegal content removalPublish transparency reports; curator set moderation
EU (GDPR)Right to erasure for personal dataMinimal PII storage; contributor deletion supported
UK (Online Safety)Duty of care for user-generated contentCurator set moderation; clear reporting
ChinaData localization requirementsRegional nodes if operating in-country

Pre-Deployment Checklist

For institutions deploying Constellation indexers:

LEGAL REVIEW:
[ ] Copyright policy reviewed by institutional counsel
[ ] Takedown procedure documented
[ ] Data processing agreement drafted (if handling third-party data)
[ ] Privacy policy published (if accepting user accounts)

TECHNICAL CONTROLS:
[ ] Excerpt length enforcement (<100 words)
[ ] License detection in extraction pipeline
[ ] Audit logging for all content ingestion
[ ] Backup and recovery procedures

OPERATIONAL:
[ ] Designated copyright agent (DMCA requirement)
[ ] Abuse reporting channel
[ ] Incident response procedure
[ ] Annual compliance review scheduled

Risk Assessment Template

RISK: Publisher legal challenge
Likelihood: Medium (precedent: Google Scholar, Semantic Scholar operate without challenge)
Impact: High (could force content removal)
Mitigation: Paraphrase-first policy; no full text storage; prompt takedown response
Residual risk: Low if policies followed

RISK: GDPR complaint for contributor data
Likelihood: Low (minimal PII stored)
Impact: Medium (fines, remediation)
Mitigation: Data minimization; deletion capability; clear privacy policy
Residual risk: Very low

RISK: PHI exposure via clinical trails
Likelihood: Very low (PHI not stored by design)
Impact: Very high (HIPAA penalties)
Mitigation: Technical controls preventing PHI ingestion; training
Residual risk: Negligible if controls enforced

Audit Trail Requirements

Constellation’s event log provides built-in audit capability:

For regulatory audits, export:

constellation-export --format=audit --since=2025-01-01 --include=events,sources,contributors

11. Versioning

[NORMATIVE]

11.1 Protocol Version

Every message includes protocol version:

Message {
  protocol_version: "0.8"
  // ... rest of message
}

Nodes reject messages from incompatible versions.

11.2 Compatibility

Version ChangeCompatibility
Patch (0.1.x)Fully backward compatible
Minor (0.x.0)Backward compatible; new features optional
Major (x.0.0)May break compatibility; migration required

11.3 Deprecation

Features are deprecated before removal:

  1. Announce deprecation (minimum 6 months notice)
  2. Log warnings on deprecated usage
  3. Remove in next major version

12. Implementation Notes

[GUIDANCE — except §12.1 Conformance Requirements which is NORMATIVE]

Git succeeded because independent implementations could interoperate. Linus wrote the first; others followed; all produced identical results for identical inputs. The protocol layer was solid enough that the implementation layer could vary.

Constellation requires the same property. A reference implementation is available at github.com/borrowed-light/constellation-protocol, but the spec must be precise enough that any conforming implementation produces identical hashes, identical event ordering, identical materialized views.

12.1 Conformance Requirements

[NORMATIVE]

For interoperability, independent implementations must produce identical results. The protocol defines:

Conformance levels:

LevelRequirementsUse Case
ReaderParse events, verify signatures, materialize viewsLight clients, query tools
WriterReader + create valid events with correct canonicalizationContributors, extractors
IndexerWriter + sync protocol, event ordering, full materializationFull nodes

Test vectors:

The reference repository includes:

Conformance test suite:

constellation-conformance-test --level=writer --implementation=./my-impl

Implementations MUST pass all test vectors for their conformance level before claiming protocol compliance. The test suite is versioned with the protocol.

12.2 Benchmark Suite

To beat the “LLMs + RAG is enough” argument, Constellation must demonstrate measurable superiority on correction propagation tasks. This section specifies concrete datasets, metrics, and baselines.

The core claim to prove: Long-context LLMs and RAG systems cannot reliably propagate corrections because they lack explicit dependency graphs, stable identity, and deterministic state transitions. Constellation can. This must be quantified.

Concrete Datasets

All benchmark datasets are published at github.com/borrowed-light/constellation-benchmarks under CC-BY license.

Dataset 1: Retraction Propagation Corpus (RPC-2025)

ComponentSizeSourceLicense
Retracted papers1,247Retraction Watch 2020-2025CC-BY
Citation graph2.3M edgesOpenAlex snapshot 2025-01CC0
Dependency annotations150 papersExpert annotation (3 annotators, adjudicated)CC-BY
Guideline impact47 guidelinesManual trace from NICE, USPSTFCC-BY

Annotation protocol:

Dataset 2: Living Review Update Corpus (LRUC-2025)

ComponentSizeSourceLicense
Living reviews53Cochrane Living Reviews 2022-2025CC-BY-NC
Update logs127 updatesCochrane change documentationCC-BY-NC
Evidence timeline15K papersPubMed/Cochrane linkagePublic domain
Ground truth changes850 items”What should have changed when” annotationsCC-BY

Dataset 3: Claim Contradiction Corpus (CCC-2025)

ComponentSizeSourceLicense
Extracted claims12,500PubMed abstracts (oncology, cardiology)Fair use
Contradiction pairs523Expert-annotated contradictionsCC-BY
Near-duplicates1,247Same claim, different phrasingCC-BY
Consistent pairs5,000Verified non-contradictionsCC-BY

Benchmark 1: Retraction Propagation Accuracy

Task: Given a retracted paper, identify all downstream artifacts that depend on it.

Evaluation procedure:

for each retracted_paper in RPC-2025.retracted:
  ground_truth = RPC-2025.dependency_annotations[retracted_paper]
  
  # System under test
  predicted = system.propagate_retraction(retracted_paper)
  
  # Metrics
  precision = |predicted ∩ ground_truth| / |predicted|
  recall = |predicted ∩ ground_truth| / |ground_truth|
  latency = time(retraction_event) - time(all_alerts_sent)

Baselines (concrete implementations):

BaselineImplementationExpected Performance
Citation-onlyOpenAlex citation graph, 1-hopHigh recall (~95%), low precision (~15%)
RAG + GPT-4LangChain + GPT-4-turbo, 128K contextMedium precision (~72%), medium recall (~65%)
RAG + ClaudeAnthropic RAG pipeline, 200K contextMedium precision (~75%), medium recall (~68%)
scite APIscite citation context classificationMedium precision (~60%), low recall (~40%)

Why RAG fails:

Target metrics for Constellation:

MetricMinimumTarget”Beat RAG” threshold
Precision85%92%> GPT-4 RAG by 15+ points
Recall80%90%> GPT-4 RAG by 15+ points
Latency (p99)< 1 hour< 15 minN/A for RAG (requires full reindex)
Trace completeness95%99%Full dependency chain vs “found it somewhere”

Benchmark 2: Living Review Update

Task: Given a living systematic review and a stream of evidence changes, generate a structured change log.

Evaluation procedure:

for each review in LRUC-2025.reviews:
  for each time_window in review.update_periods:
    evidence_changes = get_changes(time_window)
    ground_truth = LRUC-2025.ground_truth_changes[review, time_window]
    
    predicted = system.generate_change_log(review, evidence_changes)
    
    # Metrics
    change_detection_accuracy = score(predicted.changes, ground_truth.changes)
    impact_accuracy = score(predicted.affected_conclusions, ground_truth.affected_conclusions)
    time_savings = ground_truth.manual_hours - system.compute_hours

Baselines:

BaselineImplementationExpected Performance
Manual reviewExpert systematic reviewer100% accuracy, 8-40 hours per update
PubMed alerts + manualEmail alerts, human triage85% change detection, 4-20 hours
Covidence + AICommercial tool with AI assist90% change detection, 2-10 hours

Target metrics:

MetricTargetComparison
Change detection> 95%Match or exceed manual
Impact accuracy> 90%Better than alert-based
Time to complete< 30 min10-50x faster than manual

Benchmark 3: Claim Consistency

Task: Identify contradictory claims across a corpus.

Evaluation procedure:

for each claim_pair in CCC-2025.all_pairs:
  predicted_relation = system.classify(claim_pair)
  # contradiction | consistent | near_duplicate | unrelated
  
  ground_truth = CCC-2025.labels[claim_pair]
  
# Aggregate metrics
contradiction_precision = TP_contra / (TP_contra + FP_contra)
contradiction_recall = TP_contra / (TP_contra + FN_contra)

Baselines:

BaselineImplementationContradiction F1
Embedding similarityada-002, cosine > 0.90.45
NLI modelDeBERTa-v3-large fine-tuned0.62
LLM pairwiseGPT-4 with CoT prompting0.71

Target: Constellation achieves F1 > 0.80 by leveraging typed entity links and dependency structure.

Benchmark 4: Extraction Quality

[Existing content preserved - already concrete]

Task: Evaluate accuracy of point extraction from scientific text.

Dataset:

Metrics:

MetricDescription
Point extraction precisionWhat fraction of extracted points are valid claims?
Point extraction recallWhat fraction of annotated claims are extracted?
Entity linking accuracyAre extracted entities correctly linked to identifiers?
Constraint completenessAre qualifications and conditions captured?
Extraction stabilitySame input → same output across model versions?

Baselines:

Target thresholds for production extraction:

MetricMinimumTarget
Point precision85%92%
Point recall70%82%
Entity linking F180%88%
Constraint completeness60%75%
Cross-version stability95%99%

Why this matters: If extraction pipelines introduce errors faster than humans can correct them, the graph becomes unreliable. Published extraction accuracy benchmarks enable users to calibrate trust in automated contributions.

Running Benchmarks

# Run all benchmarks
constellation-benchmark --suite=all --output=results/

# Run specific benchmark
constellation-benchmark --suite=retraction-propagation --baseline=rag-gpt4

# Run extraction quality benchmark
constellation-benchmark --suite=extraction-quality --extractor=./my-extractor

# Compare implementations
constellation-benchmark --compare=impl-a,impl-b --suite=living-review

Results are published quarterly at constellation-protocol.org/benchmarks with methodology, datasets, and reproducibility scripts.

12.2 Interoperability with Existing Standards

The protocol bridges existing scientific infrastructure rather than replacing it.

Nanopublication Mapping

Nanopublications are the closest prior art: atomic assertions with provenance in RDF. The mapping:

ConstellationNanopublicationNotes
PointAssertion graphStatement + entities
Source + Evidence LinksProvenance graphWhere the assertion came from
Contributor + SignaturePublication infoWho published, when, signature
PointIDNanopub URIContent-derived identifier

Bidirectional conversion:

// Constellation → Nanopublication
nanopub = {
  "@id": "http://purl.org/np/" + point.id,
  "np:hasAssertion": {
    // Point statement as RDF triple or reified statement
  },
  "np:hasProvenance": {
    // Evidence links, source references
  },
  "np:hasPublicationInfo": {
    // Contributor, timestamp, signature
  }
}

// Nanopublication → Constellation
point = extract_assertion(nanopub)
links = extract_provenance(nanopub)
event = create_proposed_event(point, contributor_from_pubinfo(nanopub))

Structural differences (not just syntax):

The differentiation is not “JSON vs RDF.” Nanopublications and Constellation differ in what they model:

CapabilityNanopublicationsConstellation
Atomic assertions
Content-addressed identity✓ (trusty URIs)✓ (PointID)
Provenance✓ (prov graph)✓ (evidence links)
State machine✓ (proposed → validated → contested → retracted)
Event history✓ (full event log, replayable)
Conflict representation✓ (disagreements as first-class events)
Propagation semantics✓ (retractions cascade to dependents)
Materialized views✓ (computed from events)

Why this matters:

A nanopublication is immutable once published. To “retract” it, you publish a new nanopub asserting that the old one is retracted. But:

Constellation models the lifecycle of scientific claims, not just their initial assertion. When a source is retracted:

  1. The retraction is an event on the source
  2. All points citing that source automatically receive source_retracted events
  3. Confidence scores recompute
  4. Subscribers are notified
  5. The full history (proposed → validated → source_retracted) is preserved

Interoperability approach: Import nanopubs as points with proposed state. Export points as nanopubs (losing state history). The ecosystems can exchange content while Constellation provides the correction/propagation layer that nanopubs lack.

PROV-O Alignment

The W3C PROV ontology describes provenance. Constellation’s event model aligns:

ConstellationPROV-ONotes
PointContentprov:EntityThe thing being described
PointEventprov:ActivityThe action that changed state
Contributorprov:AgentWho performed the action
causal_depsprov:wasDerivedFromCausal relationships

Full PROV-O export is available via: GET /points/{id}/prov

JSON-LD Context

For Linked Data compatibility, all Constellation objects can include JSON-LD context:

{
  "@context": "https://constellation-protocol.org/context/v0.8.jsonld",
  "@type": "Point",
  "id": "pt_abc123",
  "statement": "..."
}

This enables Constellation data to be consumed by RDF tools without requiring RDF-native storage.


13. Governance

[GUIDANCE]

Governance is not deferred. A protocol that encodes disputes and retractions cannot dodge governance—state transitions are social, not purely technical.

13.1 Governance Model

Multi-stakeholder stewardship: The protocol is governed by a foundation with representation from:

Decision process:

Anti-capture mechanisms:

The protocol is only valuable if it remains neutral. Capture by a single entity (dominant indexer, large funder, commercial vendor) would destroy trust and utility. Explicit mechanisms to prevent capture:

MechanismPurposeImplementation
Seat limitsNo single entity controls governanceMaximum 20% of board seats per organization; maximum 30% per stakeholder category
Veto thresholdMajor changes require broad consensusTechnical changes require 2/3 approval; schema changes require 3/4 approval across categories
Mandatory portabilityUsers can exit without losing dataAll indexers MUST support full export in standard format; CuratorSets portable between indexers
Multi-implementation requirementNo single codebase dependencyProtocol changes only finalized when 2+ independent implementations pass conformance
Transparent roadmapNo surprise changesAll proposed changes published 90 days before vote; rationale required
Conflict disclosureIdentify biased actorsBoard members disclose funding sources and commercial interests annually

What capture would look like (and how it’s blocked):

Capture ScenarioRiskBlocking Mechanism
Dominant indexer controls protocol evolutionIndexer makes changes that lock in their implementationMulti-implementation requirement; schema changes need 3/4 approval
Large funder demands favorable treatmentFunder conditions grants on protocol decisionsTransparent roadmap; conflict disclosure; seat limits
Commercial vendor extracts rentVendor adds proprietary extensions, creates lock-inMandatory portability; all events exportable
Single country’s regulations drive designProtocol becomes unusable elsewhereGeographic diversity in governance seats; veto threshold

Git precedent: Git survived because Linus stepped back from day-to-day control and the protocol stabilized early. Constellation must achieve protocol stability before any single entity becomes dominant.

13.2 Economic Sustainability

Three sustainability models exist for open infrastructure:

Model A: Institutional Membership (Linux Foundation pattern)

Model B: Hosted Services (Red Hat pattern)

Model C: Grant + Public Infrastructure (arXiv pattern)

The protocol itself is agnostic to which model indexers choose. What matters is that the protocol layer remains open, implementations remain interoperable, and no single entity captures the standard.

13.3 Failure Modes and Mitigations

Failure ModeProbabilityMitigation
Empty graph (chicken-egg)High (60-75%)Product-led bootstrap: ship retraction impact tool first; seed from open corpora
Trust collapse (spam, bad extraction)Medium-high (45-65%)Curated views with signed curator sets; indexer-level admission policies
Semantic fragmentationMedium-high (40-60%)same_as link governance (§4.4.1); periodic dedup campaigns; tolerate some duplication
De facto centralizationMedium (35-55%)Mandatory export; standard APIs; multi-stakeholder governance; anti-capture mechanisms
Funding collapseMedium (30-50%)Diversified funding; endowment target; institutional membership transition
Competitive displacementMedium (25-45%)Interoperability with nanopubs, ORKG; focus on flagship workflow differentiation
Licensing/extraction constraintsMedium (30-45%)Paraphrase-first policy; excerpt limits; institutional agreements; focus on open-access corpora

Semantic fragmentation deserves elaboration because it is the slow death. The same finding phrased differently gets different PointIDs. Without active management:

Mitigations:

  1. same_as links (§4.4.1) connect equivalent points when humans or validated systems confirm equivalence
  2. Periodic deduplication campaigns by curators who merge obvious duplicates
  3. Entity normalization reduces fragmentation at the entity layer
  4. Tolerance: some duplication is acceptable; premature merging is worse than fragmentation

14. Bootstrap Strategy

[GUIDANCE]

Protocols bootstrap through demonstrated utility, not specification elegance. Git bootstrapped through the Linux kernel. TCP/IP bootstrapped through ARPANET. The Constellation Protocol requires a similar nucleus.

14.1 Flagship Workflow: Retraction Impact Analysis

The initial implementation focuses on one workflow that demonstrates the protocol’s core value proposition:

The workflow: Given a retracted paper, compute and display all downstream artifacts (points, guidelines, reviews) that depend on it.

Why this workflow:

Implementation:

14.2 First Implementations

Reference implementation: A complete, open-source indexer that passes the conformance suite.

First external implementations: The protocol succeeds when independent teams implement it without coordination. Target communities:

The first independent implementation that syncs correctly with the reference implementation is the proof that the protocol works.

14.2.1 The Contribution Problem

The historical trap: infrastructure adoption requires contribution, but contribution requires immediate personal benefit. Institutional repositories failed because depositing was work with deferred, diffuse benefits.

Protocol-level mitigation: Contribution emerges from use, not from explicit “contribute” actions.

The protocol structures these natural scholarly activities as events that accumulate into the graph.

14.3 Integration Points

Protocol integration patterns:

14.4 Seeding Strategy

The graph must have value before users contribute. Seeding sources:

SourceCoverageQualityEffort
Retraction Watch + CrossrefRetractions, correctionsHighLow
PubMed abstractsBroad biomedicalMediumMedium
Cochrane reviewsGold-standard evidence synthesisVery highMedium
Preprint servers (bioRxiv, medRxiv)Recent, CC-BYVariableLow
OpenAlex/Semantic Scholar APIsBroad coverageMediumLow

Initial seed: All retraction/correction events + citation links. This enables the flagship workflow immediately. Claim extraction from abstracts follows as extraction pipelines mature.

14.5 Source Lifecycle Ingestion (Crossref/PubMed Pipeline)

Constellation’s differentiated value is not “we know a paper was retracted”—Crossref and PubMed already provide that. The value is computing and propagating impacts through derived assertions.

This section specifies how Source lifecycle events are ingested from incumbent metadata providers.

Crossref Integration

Crossref provides retraction/correction metadata via Crossmark and relationship types:

// Crossref API query for updates
GET https://api.crossref.org/works?filter=type-name:retraction,from-update-date:2025-01-01

// Relationship types that trigger Source events:
- "is-retracted-by"     → retraction event
- "is-corrected-by"     → correction event
- "is-expression-of-concern" → concern event
- "is-updated-by"       → update event

Ingestion pipeline:

CrossrefIngestion:
  1. Poll Crossref API daily for new retractions/corrections
  2. For each retraction notice:
     a. Look up SourceID for the retracted DOI
     b. If Source exists in Constellation:
        - Generate SourceEvent { type: retracted, evidence: crossref_notice_doi }
        - Append to event log
        - Trigger propagation to dependent Points
     c. If Source does not exist:
        - Create Source from Crossref metadata
        - Create SourceEvent { type: retracted }
  3. For corrections: similar flow with { type: corrected }
  4. Log ingestion results for audit

Crossref metadata → Source fields:

Crossref FieldConstellation Field
DOIexternal_refs[].id where system=“DOI”
titletitle
authorcontributors (if ORCID available)
published-print/onlinepublication_date
container-titlejournal (in metadata)
typesource_type mapping
relation.is-retracted-bytriggers retraction event

PubMed Integration

PubMed provides retraction data via E-utilities and LinkOut:

// PubMed E-utilities query for retractions
esearch.fcgi?db=pubmed&term=retracted+publication[pt]&datetype=edat&mindate=2025/01/01

// PubMed article types that trigger events:
- "Retracted Publication"       → retraction event
- "Retraction of Publication"   → retraction notice (different Source)
- "Published Erratum"           → correction event
- "Expression of Concern"       → concern event

Ingestion pipeline:

PubMedIngestion:
  1. Query PubMed E-utilities daily for new retractions
  2. For each retracted PMID:
     a. Fetch full article metadata via efetch
     b. Look up SourceID for PMID
     c. Generate SourceEvent with evidence from retraction notice
     d. If retraction notice has DOI, link to Crossref data
  3. Cross-reference with Crossref to avoid duplicates
  4. Log ingestion with source attribution

Retraction Watch Integration

Retraction Watch maintains the most comprehensive retraction database with editorial context:

RetractionWatchIngestion:
  1. Ingest Retraction Watch database (via partnership or scraping with attribution)
  2. For each entry:
     a. Extract DOI/PMID identifiers
     b. Extract retraction reason (fraud, error, plagiarism, etc.)
     c. Create/update SourceEvent with detailed note field
     d. Link to original Retraction Watch entry for provenance

Why multiple sources: Each source has different coverage and latency:

The ingestion pipeline reconciles across sources and produces a unified event stream.

14.6 Adoption Dynamics

TCP/IP had a forcing function: ARPANET’s NCP shutdown on January 1, 1983. Everyone migrated or lost connectivity. Protocol adoption typically requires external pressure that makes non-adoption costly.

Structural forces favoring adoption:

Research funding requirements: Funders already require data management plans and FAIR compliance. The logical extension is requiring correction propagation for living evidence artifacts. When funders mandate the capability, the protocol that provides it most easily wins.

Institutional liability: When a clinical guideline recommends a treatment based on retracted evidence, and harm occurs, “we couldn’t have known” becomes less defensible if correction propagation infrastructure exists. Risk management creates adoption pressure independent of protocol advocacy.

AI regulation: EU AI Act requires transparency and traceability for high-risk AI systems. FDA’s PCCP framework requires documentation of how AI-enabled devices change over time. AI systems consuming scientific literature increasingly need verifiable provenance—not for elegance, but for compliance.

Network effects: Once correction propagation becomes expected in some contexts, its absence becomes notable in others. The question shifts from “why should we adopt this” to “why aren’t you using correction propagation.”


15. Future Work

[GUIDANCE]

This specification is v0.8. The hard parts are done: object model, identity convergence, propagation, conflict representation, sync protocol, dependency subtypes, trust-set client model. What remains is execution and adoption.

15.1 Formal Consensus

Mechanism for coordinating validation across nodes in adversarial conditions. The current model relies on curated views and signed events; formal consensus would enable trustless validation in high-stakes domains.

15.2 Domain Extensions

Specialized schemas for clinical trials (phases, endpoints, populations), genomics (variants, pathways, expression), and drug interactions (mechanisms, severity, evidence). The core primitives support these; the work is agreeing on domain vocabularies.

15.3 Cryptographic Evidence Verification

Zero-knowledge proof systems for verifiable extraction, computational integrity, and privacy-preserving validation. Technologies like zkSNARKs/zkSTARKs and folding schemes (Nova, HyperNova) now achieve practical performance. When these mature, Constellation can add cryptographic guarantees to the evidence layer—prove a claim exists in a source without revealing the source, verify statistical analyses without accessing raw data.


16. Conclusion

[GUIDANCE]

The Constellation Protocol provides infrastructure for knowledge that can be navigated, versioned, and corrected. Four core primitives—Source, Entity, Point, Link—with content-addressed identity (PointID from semantic content, evidence via Links), signed events, and materialized views enable a knowledge layer that has not existed.

What this makes possible:

A world where a retraction propagates to everything that cited it—within hours, not decades. Where a clinician at midnight can see not just an assertion but its evidence, constraints, and dissent. Where a researcher discovers that three labs have already tried an approach, and sees exactly why it failed. Where AI agents retrieve structured hypotheses with evidence requirements, not prose that cannot be verified. Where the seventeen-year gap between discovery and practice collapses because knowledge can finally arrive.

What the protocol provides:

The protocol is substrate, not application. Applications will be built on it. But the substrate must exist first, and it must be open, or the map of what humanity knows will be owned by those who can afford to build it closed.

Git transformed software development not because version control was a new idea, but because the Linux kernel needed it and nothing else worked. The Constellation Protocol makes the same bet: that the pain of managing living evidence—retractions, corrections, disputes—will force adoption of structured, propagating knowledge.

The stars are scattered across the archive. This protocol specifies how to draw the lines that make them navigable.

So the light arrives.


References

  1. Borrowed Light. (2026). Constellations of Borrowed Light. https://borrowedlight.org/constellations

  2. Borrowed Light. (2026). Epistemic Systems Engineering: A Mathematical Foundation for Mapping the Frontier of Scientific Knowledge. [Mathematical foundations including provenance algebra, firmness field derivation, stability theorems, and gap detection algorithms.]

  3. Nakamoto, S. (2008). Bitcoin: A Peer-to-Peer Electronic Cash System.

  4. Benet, J. (2014). IPFS - Content Addressed, Versioned, P2P File System.

  5. Sporny, M. et al. (2022). Decentralized Identifiers (DIDs) v1.0. W3C Recommendation.

  6. Model Context Protocol Specification. Anthropic/Agentic AI Foundation. (2024-2025). https://modelcontextprotocol.io

  7. Shannon, C. E. (1948). A Mathematical Theory of Communication. Bell System Technical Journal.

  8. Balas, E. A. and Boren, S. A. (2000). Managing Clinical Knowledge for Health Care Improvement. Yearbook of Medical Informatics.

  9. Morris, Z. S., Wooding, S., and Grant, J. (2011). The answer is 17 years, what is the question: understanding time lags in translational research. Journal of the Royal Society of Medicine, 104(12):510-520.

  10. Edge, D. et al. (2024). From Local to Global: A Graph RAG Approach to Query-Focused Summarization. Microsoft Research. [GraphRAG methodology for knowledge-grounded retrieval.]

  11. Abolhasani, M. and Kumacheva, E. (2023). The rise of self-driving labs in chemical and materials sciences. Nature Synthesis, 2:483-492.

  12. Lu, C. et al. (2024). The AI Scientist: Towards Fully Automated Open-Ended Scientific Discovery. Sakana AI. [Autonomous research systems and their requirements for structured knowledge.]

  13. Wilkinson, M. D. et al. (2016). The FAIR Guiding Principles for scientific data management and stewardship. Scientific Data, 3, 160018.

  14. NIH Office of Data Science Strategy. (2025). NIH Strategic Plan for Data Science, 2025-2030. [FAIR alignment mandates for NIH-funded research.]

  15. ASAPbio. (2025). HHMI Enacts “Immediate Access To Research” Policy. [Preprint-first publishing mandate.]

  16. Sabel, B. & Larhammar, D. (2025). Reformation of science publishing: the Stockholm Declaration. Royal Society Open Science, 12(11), 251805. [Paper mills and scientific fraud.]

  17. Kapoor, S. & Narayanan, A. (2023). Leakage and the Reproducibility Crisis in ML-based Science. Princeton University. [Reproducibility infrastructure requirements.]

  18. Li, L. & Susnjak, T. (2025). Transforming Evidence Synthesis: A Systematic Review of the Evolution of Automated Meta-Analysis in the Age of AI. arXiv:2504.20113.

  19. Google Research. (2025). Accelerating Scientific Breakthroughs with an AI Co-Scientist. [Multi-agent hypothesis generation systems.]

  20. Schmidgall, S. et al. (2025). Agent Laboratory: Using LLM Agents as Research Assistants. [End-to-end AI research workflows.]

  21. Groth, P. et al. (2010). The anatomy of a nanopublication. Information Services & Use, 30(1-2), 51-56. [Atomic assertion model with provenance.]

  22. Open Research Knowledge Graph (ORKG). https://orkg.org/. [Structured research contribution graphs.]

  23. Nicholson, J. M. et al. (2021). scite: A smart citation index that displays the context of citations and classifies their intent using deep learning. Quantitative Science Studies, 2(3), 882-898.

  24. Wang, K. et al. (2023). Semantic Scholar Open Data Platform. Allen Institute for AI. [Large-scale scholarly knowledge graph.]

  25. Priem, J. et al. (2022). OpenAlex: A fully-open index of scholarly works, authors, venues, institutions, and concepts. arXiv:2205.01833.

  26. Kuhn, T. et al. (2021). Decentralized provenance-aware publishing with nanopublications. PeerJ Computer Science, 7:e387. [Decentralized server network for atomic assertions.]


Appendix A: Full Schema Reference

Complete JSON Schema definitions available at: github.com/borrowed-light/constellation-protocol/schemas/


Appendix B: Example Point

{
  "id": "pt_h7k9m2x4",
  "statement": "BRAF V600E mutation predicts response to vemurafenib in metastatic melanoma",
  "entities": [
    { "entity_id": "ent_braf", "role": "subject" },
    { "entity_id": "ent_v600e", "role": "variant" },
    { "entity_id": "ent_vemurafenib", "role": "intervention" },
    { "entity_id": "ent_metastatic_melanoma", "role": "condition" }
  ],
  "evidence": [
    {
      "id": "ev_001",
      "source": {
        "type": "paper",
        "identifier": "10.1056/NEJMoa1103782",
        "title": "Improved Survival with Vemurafenib in Melanoma with BRAF V600E Mutation",
        "authors": ["Chapman, P.B.", "et al."],
        "date": "2011-06-30"
      },
      "relationship": "supports",
      "strength": "randomized_trial",
      "excerpt": "Overall survival at 6 months was 84% in the vemurafenib group",
      "extractor": "contrib_abc123",
      "validator": "contrib_def456",
      "validated_at": "2026-01-15T10:30:00Z"
    }
  ],
  "confidence": {
    "level": "very_high",
    "score": 0.91,
    "factors": {
      "evidence_strength": 0.9,
      "replication_count": 3,
      "dissent_weight": 0.1,
      "recency": 0.8,
      "validation_depth": 2
    },
    "computed_at": "2026-01-15T10:30:00Z"
  },
  "constraints": [
    {
      "condition": "Patients with ECOG performance status 0-1",
      "effect": "Primary efficacy population",
      "source": "ev_001"
    },
    {
      "condition": "Resistance typically develops",
      "effect": "Median progression-free survival ~6 months",
      "source": "ev_002"
    }
  ],
  "dissent": [
    {
      "id": "ds_001",
      "challenge": "Acquired resistance limits long-term benefit",
      "evidence": ["ev_002"],
      "status": "acknowledged",
      "resolution": "Constraint added; combination therapy now preferred"
    }
  ],
  "lineage": {
    "derived_from": ["pt_braf_signaling"],
    "supersedes": [],
    "superseded_by": null
  },
  "state": "validated",
  "history": [
    {
      "from_state": null,
      "to_state": "proposed",
      "reason": "Extracted from Chapman et al. 2011",
      "timestamp": "2026-01-10T09:00:00Z",
      "actor": "contrib_abc123"
    },
    {
      "from_state": "proposed",
      "to_state": "validated",
      "reason": "Confirmed by oncology specialist",
      "timestamp": "2026-01-15T10:30:00Z",
      "actor": "contrib_def456"
    }
  ],
  "created_at": "2026-01-10T09:00:00Z",
  "created_by": "contrib_abc123",
  "source": {
    "type": "paper",
    "identifier": "10.1056/NEJMoa1103782"
  }
}

Appendix C: Healthcare Regulatory Compliance Profile

[PROFILE — for deployments in regulated healthcare contexts]

This appendix specifies how Constellation aligns with healthcare regulatory requirements. The core protocol is domain-neutral; this profile adds constraints for clinical and regulatory use.

C.1 Regulatory Landscape

RegulationScopeKey RequirementsConstellation Alignment
EU AI ActAI systems in EUTransparency, traceability, human oversightEvent log = audit trail; curator sets = human oversight
FDA PCCPAI-enabled medical devices (US)Change management, performance monitoringPointEvents document changes; propagation = monitoring
MDR (EU)Medical devicesClinical evidence traceabilitySource → Point → Guideline dependency chain
GDPRPersonal data (EU)Data minimization, right to erasureNo PHI storage; contributor deletion supported
HIPAAProtected health info (US)Privacy, securityPHI excluded by design; no patient data in Points

C.2 EU AI Act Alignment

The EU AI Act (Regulation 2024/1689) requires high-risk AI systems to maintain:

Constellation provides:

// EU AI Act Article 11: Technical Documentation
constellation_documentation = {
  knowledge_sources:    "All Sources with ingestion timestamps",
  evidence_chains:      "All evidence Links from Source → Point",
  change_history:       "Full event log with signed transitions",
  validation_records:   "All validation events with contributor attestation"
}

// EU AI Act Article 14: Human Oversight
human_oversight = {
  curator_sets:         "Human-defined trust boundaries",
  validation_events:    "Human validation required for clinical curator sets",
  conflict_display:     "Disputed points surfaced, not hidden",
  intervention:         "Humans can contest, retract, supersede"
}

// EU AI Act Article 61: Post-market Monitoring  
monitoring = {
  retraction_propagation: "Automatic alerting when sources retracted",
  evidence_updates:       "New evidence triggers re-evaluation",
  performance_tracking:   "Benchmark suite measures ongoing accuracy"
}

C.3 FDA PCCP Framework Alignment

FDA’s Predetermined Change Control Plan framework allows AI-enabled devices to specify allowed modifications without re-submission. Constellation supports this:

Allowed changes that don’t require new approval:

Changes requiring notification/review:

Audit trail requirements:

PCCP_AuditRecord {
  device_id:          DeviceID
  knowledge_version:  CheckpointID          // Constellation checkpoint
  curator_set:        CuratorSetID          // Trust boundary
  change_events:      [EventID]             // Since last report
  impact_assessment:  ImpactReport          // Auto-generated
  review_status:      ReviewStatus          // pending | approved | escalated
}

C.4 Clinical Decision Support Requirements

For Constellation integration with Clinical Decision Support (CDS) systems:

Required metadata for clinical Points:

ClinicalPointExtension {
  evidence_quality:    GRADELevel           // high | moderate | low | very_low
  population:          PopulationDescriptor // Who the evidence applies to
  intervention:        InterventionDescriptor
  comparator:          ComparatorDescriptor?
  outcome:             OutcomeDescriptor
  certainty_factors:   [CertaintyFactor]    // Risk of bias, inconsistency, etc.
  recommendation_strength: RecommendationStrength? // strong | conditional
}

GRADELevel = high | moderate | low | very_low

RecommendationStrength = 
  | strong_for
  | conditional_for
  | conditional_against
  | strong_against

Propagation behavior for clinical curator sets:

EventClinical BehaviorNon-Clinical Behavior
Source retractedImmediate alert to all subscribers; require acknowledgmentAlert, no acknowledgment required
Point contestedFlag in UI; require review before displayShow with conflict indicator
Evidence downgradedRecalculate recommendation strength; notifyUpdate confidence only

C.5 Audit Trail Export

For regulatory audits, Constellation exports in standardized formats:

# Export for EU AI Act compliance
constellation-export \
  --format=eu-ai-act \
  --scope=curator-set:clinical-conservative \
  --since=2025-01-01 \
  --output=audit-2025.json

# Export for FDA PCCP
constellation-export \
  --format=fda-pccp \
  --device-id=K123456 \
  --checkpoint=abc123 \
  --output=pccp-report.xml

Export includes:


Appendix D: Institution Consumer Mode

[PROFILE — for institutions adopting Constellation without running infrastructure]

Most institutions want risk reduction without infrastructure burden. This appendix specifies “consumer mode” — using Constellation without becoming a publisher or node operator.

D.1 Consumer Architecture

┌─────────────────────────────────────────────────────────────┐
│  INSTITUTION (Consumer Mode)                                 │
│                                                              │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐     │
│  │ Guideline   │    │ Evidence    │    │ Risk Mgmt  │     │
│  │ Authors     │    │ Librarians  │    │ Office     │     │
│  └──────┬──────┘    └──────┬──────┘    └──────┬──────┘     │
│         │                  │                  │              │
│         └──────────────────┼──────────────────┘              │
│                            ▼                                 │
│                  ┌─────────────────┐                        │
│                  │ Constellation   │                        │
│                  │ Client (Local)  │                        │
│                  └────────┬────────┘                        │
│                           │                                  │
└───────────────────────────┼──────────────────────────────────┘
                            │ HTTPS/API

              ┌─────────────────────────┐
              │ Hosted Indexer          │
              │ (Borrowed Light Cloud   │
              │  or Institutional       │
              │  Consortium Node)       │
              └─────────────────────────┘

D.2 Consumer Capabilities

CapabilityConsumer ModePublisher Mode
Query points
Receive alerts
Subscribe to curator sets
Propose new points
Validate points
Run indexer node
Define curator sets

D.3 Local Policy Overlay

Institutions can apply local policies without modifying the protocol:

InstitutionPolicy {
  institution_id:     InstitutionID
  name:               "Memorial Health System"
  
  // Trust configuration
  trust_bundle:       TrustBundleID           // Which curator sets to use
  additional_filters: [Filter]                // Local restrictions
  
  // Alert routing
  alert_destinations: [AlertDestination]      // Where to send alerts
  escalation_rules:   [EscalationRule]        // When to escalate
  
  // Audit requirements
  audit_retention:    Duration                // How long to keep logs
  export_schedule:    CronExpression          // When to export for compliance
  
  // Access control (local)
  user_roles:         [RoleDefinition]        // Who can do what locally
}

Filter {
  type:               FilterType
  criteria:           FilterCriteria
}

FilterType =
  | exclude_domains([Text])          // Don't show oncology points
  | require_local_review             // All points need local sign-off
  | delay_propagation(Duration)      // Buffer before showing alerts
  | require_evidence_level(GRADELevel)

D.4 Integration Patterns

Pattern 1: Alert-only integration

Minimal integration — just receive alerts:

// Webhook configuration
POST /institutions/{id}/webhooks
{
  "url": "https://institution.org/constellation-alerts",
  "events": ["source_retracted", "point_contested"],
  "filter": {
    "curator_set": "clinical-conservative",
    "entities": ["ent_cardiology_*"]
  }
}

// Institution receives
{
  "event_type": "source_retracted",
  "source_id": "src_trial_123",
  "affected_points": ["pt_efficacy_456", "pt_safety_789"],
  "affected_guidelines": ["guideline_af_2024"],
  "action_required": "Review 2 recommendations citing retracted evidence"
}

Pattern 2: Embedded client

Integrate Constellation client into existing tools:

// In guideline authoring tool
const constellation = new ConstellationClient({
  indexer: "https://api.constellation-protocol.org",
  trustBundle: "clinical-conservative",
  institutionPolicy: localPolicyConfig
});

// When author cites a source
async function onCitationAdded(doi) {
  const status = await constellation.checkSource(doi);
  
  if (status.state === "retracted") {
    showWarning("This source has been retracted");
  } else if (status.alerts.length > 0) {
    showInfo(`${status.alerts.length} alerts for this source`);
  }
}

// Subscribe to updates for this guideline's evidence
constellation.subscribe({
  sources: guideline.evidenceTable.map(e => e.doi),
  onAlert: (alert) => notifyAuthors(alert)
});

Pattern 3: Batch audit

Periodic audit of entire corpus:

# Weekly audit script
constellation-audit \
  --institution=memorial-health \
  --corpus=file://guidelines/*.json \
  --trust-bundle=clinical-conservative \
  --output=audit-report.html \
  --notify=guideline-committee@memorial.org

Appendix E: Constellation Core 1.0

[NORMATIVE — minimal specification for protocol conformance]

This appendix distills the essential requirements for a conforming Constellation implementation. If you implement only this appendix, you are Constellation-compatible.

E.1 Core Objects (4 primitives)

Source {
  id:          SourceID = Hash(type + identifier)
  type:        paper | trial | protocol | dataset | other
  identifier:  Text                    // DOI, PMID, URL
  metadata:    JSON?                   // Optional additional data
}

Entity {
  id:          EntityID = Hash(canonical_name + type)
  type:        gene | drug | disease | outcome | method | population | other
  canonical_name: Text
  external_refs: [{ system: Text, id: Text }]?
}

Point {
  id:          PointID = Hash(Canonicalize(statement + entities))
  statement:   Text
  entities:    [{ entity_id: EntityID, role: Text }]
}

Link {
  id:          LinkID = Hash(from + to + type + relation)
  from:        ObjectID
  to:          ObjectID
  type:        evidence | dependency | dissent | supersession | same_as
  relation:    JSON?                   // Type-specific qualifiers
}

E.2 Canonicalization (required for PointID)

Canonicalize(statement, entities):
  1. statement = NFC(statement)                    // Unicode normalization
  2. statement = collapse_whitespace(statement)   // Single spaces, trimmed
  3. statement = normalize_quotes(statement)      // ASCII straight quotes
  4. statement = normalize_dashes(statement)      // Hyphen-minus only
  5. entities = sort_by_id(entities)              // Lexicographic
  6. entities = lowercase_roles(entities)
  7. return UTF8(statement) + 0x00 + JSON(entities)
  
PointID = "pt_" + SHA256(Canonicalize(...))[0:16]

E.3 Events (state changes)

Event {
  id:          EventID = Hash(content)
  type:        EventType
  target:      ObjectID
  actor:       PublicKey
  timestamp:   ISO8601
  signature:   Ed25519Signature
  payload:     JSON
}

EventType =
  | proposed       // New Point created
  | validated      // Point validated by actor
  | contested      // Point challenged
  | retracted      // Point/Source withdrawn
  | superseded     // Point replaced by another

// Signature covers: type + target + actor + timestamp + payload
Signature = Ed25519_Sign(private_key, Hash(type + target + actor + timestamp + payload))

E.4 Materialization (computing state from events)

materialize(event_log, object_id):
  events = filter(event_log, target = object_id)
  events = sort_by_timestamp(events)
  
  state = { status: "proposed", validations: [], contests: [] }
  
  for event in events:
    match event.type:
      proposed   → state.status = "proposed"
      validated  → state.validations.append(event)
      contested  → state.status = "contested"; state.contests.append(event)
      retracted  → state.status = "retracted"
      superseded → state.status = "superseded"
  
  return state

E.5 Sync Protocol (minimal)

Request checkpoint:

GET /sync/checkpoint
Response: { checkpoint_id, event_count, merkle_root, timestamp }

Request events:

POST /sync/events
Body: { since_checkpoint, max_events }
Response: { events: [...], has_more, next_cursor }

Verify event:

verify(event):
  1. Recompute EventID from content → must match event.id
  2. Verify signature against actor's public key → must be valid
  3. Check timestamp is reasonable (not future, not ancient)
  return valid | invalid

E.6 Conformance Test (pass this = compatible)

TEST 1: Canonicalization
  Input: "BRAF  V600E   responds" with entities [{id:"gene:BRAF", role:"Subject"}]
  Expected PointID: pt_[specific hash]
  
TEST 2: Event signature
  Create event, sign with test key, verify signature
  
TEST 3: Materialization determinism
  Given event log [e1, e2, e3], compute state
  Shuffle to [e2, e3, e1], compute state
  States must be identical
  
TEST 4: Sync round-trip
  Node A creates events, Node B syncs
  Both nodes must have identical materialized views

E.7 What Is NOT Required for Core Conformance

These are important for production deployments but not required to claim “Constellation Core 1.0 compatible.”

E.8 Implementation Checklist

□ Parse and create Source, Entity, Point, Link objects
□ Compute PointID using specified canonicalization
□ Create and sign Events
□ Verify Event signatures
□ Materialize state from event log
□ Implement /sync/checkpoint endpoint
□ Implement /sync/events endpoint
□ Pass all 4 conformance tests

Estimated implementation time: 1-2 weeks for experienced developer.

Reference implementations:


Protocol version: 0.8 Last updated: January 2026 License: CC BY 4.0