Graph Schema
Neo4j schema DDL is defined in src/graphbase_memories/graph/queries/schema.cypher and runs automatically on server startup (idempotent — all statements use IF NOT EXISTS).
Constraints
Uniqueness constraints enforce primary keys and create implicit B-tree indexes:
CREATE CONSTRAINT project_id_unique IF NOT EXISTS
FOR (p:Project) REQUIRE p.id IS UNIQUE;
CREATE CONSTRAINT global_scope_unique IF NOT EXISTS
FOR (g:GlobalScope) REQUIRE g.id IS UNIQUE;
CREATE CONSTRAINT focus_id_unique IF NOT EXISTS
FOR (f:FocusArea) REQUIRE f.id IS UNIQUE;
CREATE CONSTRAINT session_id_unique IF NOT EXISTS
FOR (s:Session) REQUIRE s.id IS UNIQUE;
CREATE CONSTRAINT decision_id_unique IF NOT EXISTS
FOR (d:Decision) REQUIRE d.id IS UNIQUE;
CREATE CONSTRAINT pattern_id_unique IF NOT EXISTS
FOR (p:Pattern) REQUIRE p.id IS UNIQUE;
CREATE CONSTRAINT context_id_unique IF NOT EXISTS
FOR (c:Context) REQUIRE c.id IS UNIQUE;
CREATE CONSTRAINT entity_fact_id_unique IF NOT EXISTS
FOR (e:EntityFact) REQUIRE e.id IS UNIQUE;
CREATE CONSTRAINT governance_token_id_unique IF NOT EXISTS
FOR (t:GovernanceToken) REQUIRE t.id IS UNIQUE;
Full-text indexes
Used by DedupEngine (similarity search) and keyword retrieval:
CREATE FULLTEXT INDEX decision_fulltext IF NOT EXISTS
FOR (d:Decision) ON EACH [d.title, d.rationale];
CREATE FULLTEXT INDEX pattern_fulltext IF NOT EXISTS
FOR (p:Pattern) ON EACH [p.trigger, p.repeatable_steps];
CREATE FULLTEXT INDEX context_fulltext IF NOT EXISTS
FOR (c:Context) ON EACH [c.content, c.topic];
CREATE FULLTEXT INDEX entity_fulltext IF NOT EXISTS
FOR (e:EntityFact) ON EACH [e.entity_name, e.fact];
Property indexes
// Exact hash dedup for Decision (O(1) lookup)
CREATE INDEX decision_content_hash IF NOT EXISTS
FOR (d:Decision) ON (d.content_hash);
// TTL cleanup for GovernanceToken
CREATE INDEX governance_token_expires_at IF NOT EXISTS
FOR (t:GovernanceToken) ON (t.expires_at);
Node property schemas
Singleton initialization
// Ensure GlobalScope singleton exists on startup
MERGE (:GlobalScope {id: "global"});
This runs every startup — MERGE is idempotent, so it is safe to run repeatedly.