Saltar al contenido principal

Graph Data Pillar

AlphaSwarm's relationship, temporal-fact and provenance capability is one governed pillar, not four parallel stacks. This page is the map: which repo owns what, which vocabulary everyone speaks, and where the boundaries are.

Status

The umbrella decision is ADR 032 — Graph as a first-class data-layer pillar, Proposed and awaiting human ratification. The ten program-level records (GDP-ADR-001..010) sit under it in alphaswarm_internal/docs/architecture/graph-data-pillar/ and are likewise Proposed.

The contracts described below are implemented and shipped; the decisions governing them still await ratification.

The problem it solves​

Four repos carried graph code, and three of them described alphaswarm_graph as "the thing they mirror" — by copy, not by import. That produced:

  • the node/edge taxonomy written out three times,
  • the bitemporal envelope in at least six shapes, across two different vocabularies,
  • the Cypher read-guard deny-list implemented three times — where a clause present in one copy and missing from another is a write path that one boundary permits and the others reject,
  • a label fork inside a single repo: alphaswarm_kb writes :KBDataPoint and its own graph-retrieval channel queries :SokgNode.

None of these were caught by a test, because nothing compared the copies.

Two things, deliberately separated​

alphaswarm_graph is the graph plane​

The SOKG service owns the running graph: the store, the governance model (stage → quarantine → promote → release), tenancy enforcement, the growth loop, retrieval profiles and the schema registry. Its invariants are the platform's graph invariants. Other services reach it over HTTP only (ADR-005 / ADR-014 / ADR-0021) — never by importing it.

alphaswarm_core.graph is the vocabulary​

Because the service boundary is HTTP-only, the shapes crossing it still have to be shared. Every participating repo already depends on alphaswarm_core, which makes it the one place a contract can live without breaching a boundary.

ModuleOwns
taxonomy.pyNodeKind (111) / EdgeKind (75) StrEnums, a JSON-exportable registry, and the structural minimum consumers cannot derive — which relations are exclusive, which identity standard anchors a kind
envelope.pyBitemporalStamp, ProvenanceStamp, EvidenceClass / QualityStatus, canonical field-name constants, legacy aliases for boundary adapters
wire.pyThe shapes that cross seams: SokgSeedBatch and its records, staged assertion/event candidates, the KB handoff assertions
citation.pyGraphCitation — one citation shape for every retrieval channel
guard.pyRead-path invariants: the write-clause deny-list, READ_LIMIT_CAP, and the as-of / no-look-ahead discipline

The package is dependency-light on purpose: pydantic and the standard library only. No driver, no Cypher, no I/O. Evolution is additive — members and fields may be added; renames and removals require a major-version migration plan.

One bitemporal vocabulary​

valid_from / valid_to / tx_from / tx_to. Half-open intervals [from, to). Timezone-aware UTC, normalized on construction.

Two independent axes:

  • valid time — when the fact is true in the world. valid_to is None means still true.
  • transaction time — when the platform recorded or retracted it. tx_to is None means still the current record.

Conflicts invalidate, never delete: superseding a fact stamps the prior fact's valid_to/tx_to rather than removing it, so "what did we believe at backtest date T?" stays answerable.

Legacy vocabularies (the Graphiti-style valid_at/invalid_at/created_at/ expired_at) survive only inside boundary adapters, which translate at the edge and are deleted once their source migrates. See Bi-temporal PermissionedDataPoint for the KB's envelope and how it maps.

The as-of discipline​

Every research- or training-facing read must call the core guard, or reproduce it under test:

  • visible_as_of(record, t, t_known) — the point-in-time filter (valid_from <= t < valid_to AND tx_from <= t_known < tx_to).
  • assert_no_lookahead(records, as_of) — the defensive proof that the filter worked.

These are separate on purpose. The filter is the intent; the assertion is the evidence. A leaked future-dated fact is a silent correctness failure in a training fold, not a crash, so the export path has to prove itself rather than be trusted.

Why this is a contract, not a helper

The predecessor of assert_no_lookahead compared ISO-8601 strings lexicographically. That is only correct when both sides carry the same UTC offset. A stamp written 2023-06-01T08:00:00-05:00 is 13:00 UTC — genuinely after a 12:00 UTC cutoff — yet sorts below it as text, so the leak passed the guard. The core version parses both sides to aware datetimes.

How each repo participates​

RepoRole
alphaswarm_graphThe authoritative plane. Re-exports the core taxonomy so its own public API is unchanged; its seed / assertion / event models are the core wire types
alphaswarm_kbSOKG projection models re-based on core wire; SecurityCitation is a GraphCitation subclass; alphaswarm_kb.ontology re-exports the taxonomy and adds KB-local identifier validators (LEI, FIGI, MIC, GICS)
alphaswarm_learningBitemporal re-bases on BitemporalStamp; the read guard takes its deny-list and caps from core. Keeps service-local vocabulary (code graph, pedagogy) with a parity test pinning the overlap
alphaswarm_dataStays self-contained by design, so it converges through an optional bridge plus parity tests rather than a hard dependency — including one asserting the payload it POSTs parses as a core SokgSeedBatch

Boundaries that do not move​

  • HTTP-only between services. No repo imports alphaswarm_graph or alphaswarm_kb; none imports the alphaswarm monolith.
  • Cross-service writes go through sanctioned paths only — durable outbox projections delivering idempotent SokgSeedBatches, or the staged assertion/event governance path. Direct Bolt into another service's graph is prohibited.
  • The taxonomy is closed. The growth loop quarantines any extracted triple whose kinds are not members — that is the entity-grounding guardrail. Adding a kind is a governance act: propose it in alphaswarm_core/docs/graph-taxonomy-proposals.md, obtain alphaswarm-graph-expert review, land it in core, then bump the pin.