Skip to content

Ontological Graph

From Files to Triples

CKP v3.5 defines the ontology in Turtle files. v3.6 loads those files into Jena Fuseki, making them queryable. This is the step from "the ontology is a file on disk" to "the ontology is a knowledge graph you can ask questions about."

The difference matters because:

  • Files support grep. Graphs support inference. You can grep for ckp:Kernel in a Turtle file. You can SPARQL for "all kernels that transitively COMPOSE a kernel with STRICT governance" in a graph.
  • Files are local. Graphs are networked. A SPARQL endpoint can be queried by any kernel, any tool, any browser.
  • Files are snapshots. Graphs can be updated. When a new kernel deploys, its metadata becomes triples. The graph reflects the live fleet, not just the spec.

Jena Fuseki /ckp Dataset

CK.Operator publishes to a Jena Fuseki dataset at /ckp. Each project's fleet is stored in a named graph: urn:ckp:fleet:{hostname}.

FactValue
Endpointjena.conceptkernel.dev/ckp/sparql
Internal endpointjena-fuseki.jena.svc:3030/ckp/sparql
Triples loaded2,797
Source modules10 of 17 spec-declared Turtle modules

Modules Loaded

ModuleContentTriples
core.ttlCore classes: Kernel, Action, Instance, Edge~400
proof.ttlProofRecord, ProofCheck, ProofOutcome~150
base-instances.ttlDefault kernel instances, system kernel declarations~300
kernel-metadata.ttlKernel type qualities, governance modes~200
processes.ttlOccurrent classes, action lifecycle~250
rbac.ttlGrants, access levels, role mappings~200
relations.ttlEdge predicates: COMPOSES, TRIGGERS, PRODUCES, CONSUMES, EXTENDS~150
self-improvement.ttlConsensus, governance, evolution classes~200
shapes.ttlSHACL shapes for instance validation~350
workflow.ttlTask lifecycle, execution, provenance~200

Modules Not Yet Published

Seven modules declared in the spec are not yet published as Turtle:

ModuleContentStatus
instance.ttlInstance lifecycle, sealing, amendmentDocs stub only
action.ttlAction types, parameters, access levelsDocs stub only
identity.ttlURN scheme, SPIFFE mapping, GUID assignmentDocs stub only
governance.ttlGovernance modes, escalation, directionDocs stub only
lifecycle.ttlKernel lifecycle: mint, deploy, evolve, retireDocs stub only
economic.ttlValueFlows/REA economic eventsDocs stub only
topology.ttlFleet topology, namespace mapping, volume layoutDocs stub only

Known Issue

kernel-entity-template.ttl was skipped due to a parse error (HTTP 400 from Fuseki). The template file contains placeholder syntax that is not valid Turtle. This needs to be either fixed or excluded from the Turtle publication set.

Published Triples

The graph materialises three levels of information from conceptkernel.yaml files:

Per Project

turtle
<ckp://Project#delvinator.tech.games> a ckp:Project ;
    rdfs:label "delvinator.tech.games" ;
    ckp:hasNamespace "ck-delvinator" .

Per Kernel

turtle
<ckp://Kernel#Delvinator.Core:v1.0> a ckp:Kernel, bfo:0000040 ;
    rdfs:label "Delvinator.Core" ;
    ckp:hasType "node:cold" ;
    ckp:belongsToProject <ckp://Project#delvinator.tech.games> .

Per Edge

turtle
<ckp://Kernel#Delvinator.Core:v1.0> ckp:composes <ckp://Kernel#CK.ComplianceCheck:v1.0> .
<ckp://Kernel#Delvinator.Core:v1.0> ckp:produces <ckp://Kernel#Delvinator.TaxonomySynthesis:v1.0> .

Fleet Graph Materialisation

The deploy.graph step in the CK.Operator reconciliation lifecycle publishes kernel metadata and edges as RDF triples to the /ckp dataset after successful deployment.

Kernel as BFO:0000040 Node

Each deployed kernel becomes a ckp:Kernel individual, typed as a BFO:0000040 Material Entity:

turtle
<ckp://Kernel#Delvinator.Core:v1.0> a ckp:Kernel, bfo:0000040 ;
    rdfs:label "Delvinator.Core" ;
    ckp:hasType "node:cold" ;
    ckp:hasGovernance "STRICT" ;
    ckp:belongsToProject <ckp://Project#delvinator.tech.games> .

Edges as RDF Object Properties

Edge predicates from conceptkernel.yaml become RDF triples:

turtle
<ckp://Kernel#Delvinator.Core:v1.0>
    ckp:composes <ckp://Kernel#CK.ComplianceCheck:v1.0> ;
    ckp:produces <ckp://Kernel#Delvinator.TaxonomySynthesis:v1.0> ;
    ckp:extends  <ckp://Kernel#CK.Claude:v1.0> .

Project as Named Graph

Each project's fleet is stored in a named graph:

turtle
GRAPH <urn:ckp:fleet:delvinator-tech-games> {
    <ckp://Project#delvinator.tech.games> a ckp:Project ;
        rdfs:label "delvinator.tech.games" ;
        ckp:hasNamespace "ck-delvinator" .

    <ckp://Kernel#Delvinator.Core:v1.0> a ckp:Kernel, bfo:0000040 ;
        ckp:belongsToProject <ckp://Project#delvinator.tech.games> ;
        ...
}

Named graphs enable per-project SPARQL queries. You can ask "show me all kernels in the delvinator fleet" without scanning the entire graph.

SPARQL Query Examples

All Kernels in a Project

sparql
SELECT ?kernel ?type WHERE {
  GRAPH <urn:ckp:fleet:delvinator-tech-games> {
    ?kernel a ckp:Kernel ; ckp:hasType ?type .
  }
}

All Edges Across the Entire Fleet

sparql
SELECT ?source ?predicate ?target WHERE {
  ?source ?predicate ?target .
  ?source a ckp:Kernel .
  ?target a ckp:Kernel .
}

Find All Instances Produced by a Kernel

sparql
SELECT ?instance ?time WHERE {
  ?instance prov:wasAttributedTo ?kernel ;
            prov:generatedAtTime ?time .
  ?kernel ckp:hasUrn "ckp://Kernel#Delvinator.Core:v1.0" .
}

This query leverages PROV-O provenance triples to find all instances attributed to a specific kernel.

Trace Provenance Chain for an Instance

sparql
SELECT ?action ?agent ?time WHERE {
  ?instance prov:wasGeneratedBy ?action .
  ?action prov:wasAssociatedWith ?agent ;
          prov:startedAtTime ?time .
}

Kernels That EXTEND CK.Claude

sparql
SELECT ?kernel ?persona WHERE {
  ?kernel ckp:extends <ckp://Kernel#CK.Claude:v1.0> .
  OPTIONAL { ?kernel ckp:hasPersona ?persona }
}

Transitive COMPOSES Chain

sparql
SELECT ?kernel ?composed WHERE {
  ?kernel ckp:composes+ ?composed .
}

This finds all kernels in the transitive closure of COMPOSES -- if A COMPOSES B and B COMPOSES C, this returns (A, B), (A, C), and (B, C). Useful for understanding the full capability inheritance chain.

Kernels with Failing Proof

sparql
SELECT ?kernel ?checks ?passed WHERE {
  ?kernel a ckp:Kernel ;
          ckp:proofTotalChecks ?checks ;
          ckp:proofTotalPassed ?passed .
  FILTER(?passed < ?checks)
}

Existing Fuseki State

The cluster already runs Jena Fuseki in the jena namespace:

DatasetTriplesContent
/ontosys~335,000Legacy ontosys.io ontology (pre-CKP)
/dataset~3,000General purpose
/ckp~2,800CKP v3.5-alpha6 ontology (10 modules)

Admin credentials are stored in the jena-fuseki-admin secret in the jena namespace. The SPARQL endpoint is publicly readable; updates require authentication.

Why Jena Fuseki

The choice of Jena Fuseki over other triple stores:

ConcernJena FusekiAlternatives
SPARQL 1.1Full support including UPDATE, named graphs, property pathsMost stores support this
Turtle loadingNative format, bulk upload via HTTP POSTSome stores require conversion
Named graphsFirst-class support -- each project gets its own graphSome stores simulate with contexts
LightweightSingle JAR, ~100MB memory for small datasetsComparable to Blazegraph; lighter than Virtuoso
Already deployedRunning in the cluster since pre-CKPNo new infrastructure needed

The critical feature is named graphs. Without them, fleet-scoped queries would require filtering by project on every query -- adding complexity and reducing performance.

Architectural Consistency Check

Logical Analysis: Graph Design

Question: Is the graph a mirror of conceptkernel.yaml, or does it add information?

Answer: Currently, it is a projection. Every triple in the fleet graph can be derived from the conceptkernel.yaml files on disk. The graph adds no new information -- it adds new access patterns. You cannot do transitive queries on YAML files. You cannot do cross-fleet joins on YAML files. The graph materialises what the files declare.

In the future (v3.5.13), the graph will add information: instance provenance chains, consensus decision links, and runtime status. At that point, the graph becomes a union of declaration (from YAML) and observation (from runtime), which cannot be derived from files alone.

Question: What happens if the graph gets out of sync with the cluster?

Answer: The deploy.graph step runs after every successful deployment. If a deployment does not trigger graph materialisation (e.g., Fuseki is unreachable), the graph becomes stale. This is explicitly acceptable: deploy.graph is best-effort. The deployment succeeds even if Fuseki is down. The graph is an index, not a source of truth -- conceptkernel.yaml files are always authoritative.

Question: Why not use FerretDB or MongoDB for the graph?

Answer: Because graph queries (transitive closure, path finding, inference) are fundamentally different from document queries (filter, aggregate, project). FerretDB is used for instance storage (the ABox -- what DOES exist). Fuseki is used for ontology storage (the TBox/RBox -- what CAN exist and HOW things relate). This maps directly to the Description Logic box model: document store for ABox, graph store for TBox+RBox.

Gap identified: The 7 unpublished Turtle modules (instance, action, identity, governance, lifecycle, economic, topology) represent a significant portion of the CKP ontology. Without them, the /ckp dataset covers the core and system concepts but misses the domain-level and lifecycle classes. Publishing these modules is a prerequisite for the graph materialisation feature (v3.5.13) to be fully useful.

Conformance Requirements

  • CK.Operator SHOULD publish kernel metadata to Jena after successful deploy
  • Each kernel MUST be typed as ckp:Kernel and bfo:0000040
  • Edges MUST use CKP predicates (ckp:composes, ckp:triggers, ckp:produces, ckp:extends)
  • Graph materialisation is best-effort -- deploy succeeds even if Jena is unreachable
  • Named graphs MUST use the convention urn:ckp:fleet:{hostname-slug}
  • The SPARQL endpoint MUST be publicly readable; updates MUST require authentication

Released under the MIT License.