Skip to content

Data model (MER)

Generated from source — do not edit

Emitted by scripts/gen_data_model_docs.py from the live Kernel.auto() registry and the SQLAlchemy table model. scripts/data_model_guard.py fails CI when this page and a fresh regeneration disagree. Edit the generator, never this file.

DNA's data model has two levels. The logical model — Kinds and the references between them — carries the meaning. The physical model is a generic instance store that tells you almost nothing about the domain, and this page says so rather than dressing it up.

One database, four schema owners

A MER showing only the SDK's tables and stopping there misleads by omission. A single Postgres instance is shared by four independent schema owners, each migrating only its own tables:

Owner Migrates On this page
DNA SDK (this repo) the instance-store tables below, via its own Alembic tree yes — fully
dna-cloud portal its Prisma schema (accounts, plans, billing — real relational tables with real foreign keys) no — separate repo, separate migration tool
Copilot service copilot_thread and friends no
LangGraph runtime checkpoint* / store* no

The SDK's Alembic run is explicitly told not to have opinions about tables it does not own — otherwise autogenerate would propose dropping another owner's data. That exclusion list is machine- readable, so it is reproduced from source rather than asserted:

Excluded from the SDK's autogenerate
alembic_version
dna_schema_migrations
dna_search_docs
dna_search_docs_1024
dna_search_docs_1536
dna_search_docs_3072
dna_search_docs_384
dna_search_docs_768
dna_search_meta
dna_search_migrations
schema_migrations
search_docs
search_fts
search_meta
search_vec
sqlite_sequence

Logical model — Kinds and their references

89 Kinds are registered. Each is an instance, not a table: a Kind costs a YAML descriptor and zero migrations, which is the point of an open type system. The cost is that references between Kinds are not database foreign keys — they are fields holding a name.

How to read the edges

Not every line here is equally trustworthy, and pretending otherwise would be the whole problem. Two tiers, and one flag that matters more than either:

Tier What it means
Declared The Kind's spec.relations says so — name, target, cardinality, and (where there is one) the inverse.
Composition (dep) dep_filters names the target Kind. A real declaration, but it drives prompt composition and is never checked against stored data.

Solid line = the kernel resolves it at write time. Dashed = it does not. That is the enforced flag, and it is not the same as the tier: a relation addressed by a domain key (by: workspace_id) or carrying its Kind in the value (to: *) is fully declared and deliberately not followed — resolving by key needs an index the store does not have, and a second resolution rule beside a live one can veto data the live one accepts.

* on a label marks a polymorphic relation (several possible target Kinds, or one chosen per value). [key] marks the addressing when it is not the instance name.

159 edges: 115 declared, 44 composition-only — of which 41 are ENFORCED at write time. 42 of 89 Kinds declare at least one relation, and 2 fields are listed below as gaps.

Declared is not enforced

dep_filters declares a target Kind; nothing validates the value. A Feature.owner naming an Actor that does not exist is written without complaint. And a relation addressed by a key says what the value MEANS without teaching the kernel to follow it. A line therefore means "the model knows what this points at", and only a SOLID one means "the runtime checks it".

Overview — how the groups reference each other

Kinds are grouped by alias prefix (sdlc-, helix-, …) — a grouping that comes from the data. Arrows are counts of edges between groups; self-references are omitted here and shown in the detail diagrams.

Relations whose target is chosen per VALUE (to: *) are omitted from this view — they belong to no group, and inventing one for them would be the projection guessing again. They appear in the detail diagrams against ANY_KIND and in the declared-relations table.

flowchart LR
    agentskills["agentskills (1 Kind)"]
    artifact["artifact (2 Kinds)"]
    cloud["cloud (2 Kinds)"]
    eval["eval (4 Kinds)"]
    federation["federation (1 Kind)"]
    guardrails["guardrails (1 Kind)"]
    helix["helix (15 Kinds)"]
    intel["intel (2 Kinds)"]
    modelreg["modelreg (1 Kind)"]
    portfolio["portfolio (5 Kinds)"]
    presidio["presidio (1 Kind)"]
    research["research (1 Kind)"]
    runtime["runtime (3 Kinds)"]
    sdlc["sdlc (26 Kinds)"]
    soulspec["soulspec (1 Kind)"]
    tenant["tenant (6 Kinds)"]
    testkit["testkit (2 Kinds)"]
    federation -->|2| portfolio
    helix -->|2| agentskills
    helix -->|2| guardrails
    helix -->|1| modelreg
    helix -->|1| presidio
    helix -->|3| sdlc
    helix -->|2| soulspec
    helix -->|1| tenant
    portfolio -->|1| cloud
    portfolio -->|1| intel
    portfolio -->|1| tenant
    runtime -->|2| helix
    sdlc -->|8| helix
    sdlc -->|1| research
    tenant -->|1| portfolio
    testkit -->|16| sdlc

Detail by group

All 89 Kinds in one diagram is an unreadable hairball, so each group with at least 2 edges gets its own. A group carrying more than 20 edges is split again by tier, which keeps the enforced edges legible instead of losing them among the unvalidated ones. A box from another group appearing here is a cross-group reference.

artifact (2 edges)

erDiagram
    ANY_KIND
    KnowledgeChunk
    SourceArtifact
    KnowledgeChunk }o..|| SourceArtifact : "source_sha256 [sha256]"
    SourceArtifact }o..}o ANY_KIND : "derived_refs [{kind, name}] *"

eval (4 edges)

erDiagram
    EvalBaseline
    EvalCase
    EvalRun
    EvalSuite
    EvalBaseline }o--|| EvalRun : "run_name"
    EvalBaseline }o--|| EvalSuite : "suite"
    EvalRun }o--|| EvalSuite : "suite"
    EvalSuite }o--}o EvalCase : "cases"

federation (2 edges)

erDiagram
    MCPFederation
    Role
    MCPFederation }o..|| Role : "min_role [role_id]"
    MCPFederation }o..|| Role : "min_role_write [role_id]"

helix — declared (12 edges)

erDiagram
    ANY_KIND
    Agent
    App
    Copilot
    Engram
    Epic
    Feature
    Genome
    ModelProfile
    Roadmap
    Solution
    Workspace
    App }o--}o Copilot : "copilots"
    Copilot }o--|| Copilot : "created_by"
    Copilot }o--|| App : "runs_in"
    Engram }o..}o ANY_KIND : "affect_evidence_refs [Kind/name] *"
    Engram }o..|| Epic : "area [Kind/name] *"
    Engram }o..|| Feature : "area [Kind/name] *"
    Engram }o..|| Roadmap : "area [Kind/name] *"
    Engram }o..}o ANY_KIND : "source_refs [Kind/name] *"
    Genome }o--|| Agent : "default_agent"
    Genome }o..|| ModelProfile : "default_llm [model_id]"
    Genome }o..|| Workspace : "owner_tenant [workspace_id]"
    Solution }o--}o App : "apps"

helix — composition (13 edges)

erDiagram
    Actor
    Agent
    Guardrail
    Recognizer
    SafetyPolicy
    Skill
    Soul
    Tool
    UseCase
    Agent }o..|| Actor : "actors (dep)"
    Agent }o..}o Guardrail : "guardrails (dep)"
    Agent }o..}o Skill : "skills (dep)"
    Agent }o..|| Soul : "soul (dep)"
    Agent }o..}o Tool : "tools (dep)"
    SafetyPolicy }o..}o Recognizer : "recognizers (dep)"
    UseCase }o..}o Agent : "agents (dep)"
    UseCase }o..}o Guardrail : "guardrails (dep)"
    UseCase }o..|| Actor : "primary_actor (dep)"
    UseCase }o..}o Skill : "skills (dep)"
    UseCase }o..|| Soul : "soul (dep)"
    UseCase }o..}o Actor : "supporting_actors (dep)"
    UseCase }o..}o Tool : "tools (dep)"

portfolio (8 edges)

erDiagram
    IntelSource
    Membership
    Organization
    PricingPlan
    Project
    Repo
    Role
    Workspace
    Membership }o..|| Role : "role [role_id]"
    Membership }o--|| Organization : "scope_ref *"
    Membership }o--|| Project : "scope_ref *"
    Organization }o..|| PricingPlan : "plan_ref [tier_id]"
    Project }o--}o IntelSource : "intel_source_refs"
    Project }o--|| Organization : "org_ref"
    Project }o--}o Repo : "repo_refs"
    Project }o..|| Workspace : "workspace_id [workspace_id]"

runtime (3 edges)

erDiagram
    Agent
    GenUIBinding
    GenUIComponent
    RuntimeBinding
    GenUIBinding }o--|| Agent : "agent"
    GenUIBinding }o--}o GenUIComponent : "components"
    RuntimeBinding }o--|| Agent : "agent"

sdlc — declared (56 edges)

erDiagram
    ANY_KIND
    ADR
    AgentSession
    Bug
    Epic
    Feature
    Initiative
    Issue
    Kaizen
    Narrative
    Plan
    Research
    Roadmap
    Spec
    Spike
    Sprint
    StatusReport
    Story
    Task
    WorkflowEvent
    ADR }o--}o Feature : "covers_features"
    ADR }o--|| Narrative : "narrative_origin"
    ADR }o--|| ADR : "superseded_by"
    ADR }o--}o ADR : "supersedes"
    AgentSession }o..}o ANY_KIND : "produced_artifacts [{kind, name}] *"
    Bug }o..}o ANY_KIND : "produces [{kind, name}] *"
    Epic }o--}o Feature : "features"
    Epic }o..}o ANY_KIND : "produces [{kind, name}] *"
    Feature }o--|| Epic : "epic"
    Feature }o..}o ANY_KIND : "produces [{kind, name}] *"
    Feature }o--|| Sprint : "sprint_ref"
    Feature }o--}o Story : "stories"
    Initiative }o--}o Epic : "epics"
    Initiative }o..}o ANY_KIND : "produces [{kind, name}] *"
    Issue }o..}o ANY_KIND : "produces [{kind, name}] *"
    Kaizen }o..|| Bug : "work_item [Kind/name] *"
    Kaizen }o..|| Epic : "work_item [Kind/name] *"
    Kaizen }o..|| Feature : "work_item [Kind/name] *"
    Kaizen }o..|| Initiative : "work_item [Kind/name] *"
    Kaizen }o..|| Issue : "work_item [Kind/name] *"
    Kaizen }o..|| Spike : "work_item [Kind/name] *"
    Kaizen }o..|| Story : "work_item [Kind/name] *"
    Kaizen }o..|| Task : "work_item [Kind/name] *"
    Plan }o--|| Epic : "epic"
    Plan }o--|| Spec : "spec_ref"
    Spec }o--|| Epic : "epic"
    Spec }o--|| Spec : "supersedes"
    Spike }o..}o ANY_KIND : "produces [{kind, name}] *"
    Spike }o--}o Research : "research_refs"
    StatusReport }o..}o ANY_KIND : "evidence_refs [Kind/name] *"
    Story }o--}o Story : "dependencies"
    Story }o--|| Feature : "feature"
    Story }o..}o ANY_KIND : "produces [{kind, name}] *"
    Story }o--}o Spec : "spec_refs"
    Story }o--|| Sprint : "sprint_ref"
    Task }o..}o ANY_KIND : "produces [{kind, name}] *"
    Task }o--|| Story : "story_ref"
    WorkflowEvent }o--|| Epic : "epic_ref"
    WorkflowEvent }o--|| Feature : "feature_ref"
    WorkflowEvent }o..|| AgentSession : "parent_ref [Kind/name] *"
    WorkflowEvent }o..|| Epic : "parent_ref [Kind/name] *"
    WorkflowEvent }o..|| Feature : "parent_ref [Kind/name] *"
    WorkflowEvent }o..|| Narrative : "parent_ref [Kind/name] *"
    WorkflowEvent }o..|| Plan : "parent_ref [Kind/name] *"
    WorkflowEvent }o..|| Roadmap : "parent_ref [Kind/name] *"
    WorkflowEvent }o..|| Spec : "parent_ref [Kind/name] *"
    WorkflowEvent }o..|| Story : "parent_ref [Kind/name] *"
    WorkflowEvent }o..|| AgentSession : "ref [Kind/name] *"
    WorkflowEvent }o..|| Epic : "ref [Kind/name] *"
    WorkflowEvent }o..|| Feature : "ref [Kind/name] *"
    WorkflowEvent }o..|| Narrative : "ref [Kind/name] *"
    WorkflowEvent }o..|| Plan : "ref [Kind/name] *"
    WorkflowEvent }o..|| Roadmap : "ref [Kind/name] *"
    WorkflowEvent }o..|| Spec : "ref [Kind/name] *"
    WorkflowEvent }o..|| Story : "ref [Kind/name] *"
    WorkflowEvent }o--|| WorkflowEvent : "transitioned_from"

sdlc — composition (31 edges)

erDiagram
    ADR
    Actor
    AgentSession
    Bug
    Epic
    Feature
    Initiative
    Issue
    Kaizen
    Narrative
    Postmortem
    Reference
    Retrospective
    RiskRegister
    Roadmap
    Spec
    Spike
    Story
    Task
    UseCase
    AgentSession }o..}o Actor : "participants (dep)"
    Bug }o..|| ADR : "fix_adr (dep)"
    Bug }o..|| Feature : "related_feature (dep)"
    Bug }o..|| Story : "related_story (dep)"
    Feature }o..|| Actor : "owner (dep)"
    Feature }o..}o UseCase : "use_cases (dep)"
    Initiative }o..|| Actor : "owner (dep)"
    Issue }o..|| Actor : "owner (dep)"
    Issue }o..|| Feature : "related_feature (dep)"
    Kaizen }o..|| Issue : "issue (dep)"
    Narrative }o..}o Epic : "covers_epics (dep)"
    Narrative }o..}o Feature : "covers_features (dep)"
    Narrative }o..}o Story : "covers_stories (dep)"
    Postmortem }o..}o Feature : "related_features (dep)"
    Postmortem }o..}o Story : "related_stories (dep)"
    Retrospective }o..}o Epic : "covers_epics (dep)"
    Retrospective }o..}o Feature : "covers_features (dep)"
    Retrospective }o..|| AgentSession : "covers_session (dep)"
    Retrospective }o..}o Story : "covers_stories (dep)"
    RiskRegister }o..|| Actor : "owner (dep)"
    RiskRegister }o..}o Epic : "related_epics (dep)"
    RiskRegister }o..}o Feature : "related_features (dep)"
    Roadmap }o..|| Epic : "epics (dep)"
    Spike }o..|| Feature : "feature (dep)"
    Spike }o..|| ADR : "follow_up_adr (dep)"
    Spike }o..|| Spec : "follow_up_spec (dep)"
    Spike }o..|| Story : "follow_up_story (dep)"
    Spike }o..}o Reference : "references (dep)"
    Spike }o..}o Spike : "related_spikes (dep)"
    Story }o..|| Actor : "owner (dep)"
    Task }o..|| Actor : "owner (dep)"

tenant (5 edges)

erDiagram
    KindNamespace
    Role
    Tenant
    TenantMembership
    Workspace
    WorkspaceMembership
    WorkspaceScopeGrant
    KindNamespace }o..|| Workspace : "owner [workspace_id]"
    TenantMembership }o..|| Tenant : "tenant_slug [slug]"
    WorkspaceMembership }o..|| Role : "role [role_id]"
    WorkspaceMembership }o..|| Workspace : "workspace_id [workspace_id]"
    WorkspaceScopeGrant }o..|| Workspace : "workspace_id [workspace_id]"

testkit (18 edges)

erDiagram
    ANY_KIND
    Bug
    Epic
    Feature
    Initiative
    Issue
    Spike
    Story
    Task
    TestGuide
    TestRun
    TestGuide }o..}o Bug : "verifies [Kind/name] *"
    TestGuide }o..}o Epic : "verifies [Kind/name] *"
    TestGuide }o..}o Feature : "verifies [Kind/name] *"
    TestGuide }o..}o Initiative : "verifies [Kind/name] *"
    TestGuide }o..}o Issue : "verifies [Kind/name] *"
    TestGuide }o..}o Spike : "verifies [Kind/name] *"
    TestGuide }o..}o Story : "verifies [Kind/name] *"
    TestGuide }o..}o Task : "verifies [Kind/name] *"
    TestRun }o..}o ANY_KIND : "evidence [Kind/name] *"
    TestRun }o--|| TestGuide : "guide_ref"
    TestRun }o..}o Bug : "verifies [Kind/name] *"
    TestRun }o..}o Epic : "verifies [Kind/name] *"
    TestRun }o..}o Feature : "verifies [Kind/name] *"
    TestRun }o..}o Initiative : "verifies [Kind/name] *"
    TestRun }o..}o Issue : "verifies [Kind/name] *"
    TestRun }o..}o Spike : "verifies [Kind/name] *"
    TestRun }o..}o Story : "verifies [Kind/name] *"
    TestRun }o..}o Task : "verifies [Kind/name] *"

Groups with fewer than 2 edges (listed, not drawn): cloud, collab, evidence, intel, research.

Declared relations (spec.relations)

What each Kind says it points at. Enforced is the column that matters: yes means the kernel resolves the target at write time and the graph gets a data edge; blank means the relation is declared and the runtime does not follow it — read By for why.

From Field To Cardinality By Enforced Inverse of Cross-group
ADR covers_features Feature many name yes
ADR narrative_origin Narrative one name yes
ADR superseded_by ADR one name yes supersedes
ADR supersedes ADR many name yes superseded_by
AgentSession produced_artifacts (poly) * many {kind, name}
App copilots Copilot many name yes
Bug produces (poly) * many {kind, name}
Comment target_ref (poly) * one Kind:name
Copilot created_by Copilot one name yes
Copilot runs_in App one name yes
Engram affect_evidence_refs (poly) * many Kind/name
Engram area (poly) Epic one Kind/name yes
Engram area (poly) Feature one Kind/name yes
Engram area (poly) Roadmap one Kind/name yes
Engram source_refs (poly) * many Kind/name
Epic features Feature many name yes epic
Epic produces (poly) * many {kind, name}
EvalBaseline run_name EvalRun one name yes
EvalBaseline suite EvalSuite one name yes
EvalRun suite EvalSuite one name yes
EvalSuite cases EvalCase many name yes
Evidence document_ref (poly) * one Kind:name
Feature epic Epic one name yes features
Feature produces (poly) * many {kind, name}
Feature sprint_ref Sprint one name yes
Feature stories Story many name yes feature
GenUIBinding agent Agent one name yes yes
GenUIBinding components GenUIComponent many name yes
Genome default_agent Agent one name yes
Genome default_llm ModelProfile one model_id yes
Genome owner_tenant Workspace one workspace_id yes
Initiative epics Epic many name yes
Initiative produces (poly) * many {kind, name}
IntelInsight source_ref IntelSource one name yes
Issue produces (poly) * many {kind, name}
Kaizen work_item (poly) Bug one Kind/name
Kaizen work_item (poly) Epic one Kind/name
Kaizen work_item (poly) Feature one Kind/name
Kaizen work_item (poly) Initiative one Kind/name
Kaizen work_item (poly) Issue one Kind/name
Kaizen work_item (poly) Spike one Kind/name
Kaizen work_item (poly) Story one Kind/name
Kaizen work_item (poly) Task one Kind/name
KindNamespace owner Workspace one workspace_id
KnowledgeChunk source_sha256 SourceArtifact one sha256
MCPFederation min_role Role one role_id yes
MCPFederation min_role_write Role one role_id yes
Membership role Role one role_id
Membership scope_ref (poly) Organization one name yes
Membership scope_ref (poly) Project one name yes
Organization plan_ref PricingPlan one tier_id yes
Plan epic Epic one name yes
Plan spec_ref Spec one name yes
PlanBinding tier_id PricingPlan one tier_id
Project intel_source_refs IntelSource many name yes yes
Project org_ref Organization one name yes
Project repo_refs Repo many name yes
Project workspace_id Workspace one workspace_id yes
Research cited_by (poly) * many Kind/name
RuntimeBinding agent Agent one name yes yes
Solution apps App many name yes
SourceArtifact derived_refs (poly) * many {kind, name}
Spec epic Epic one name yes
Spec supersedes Spec one name yes
Spike produces (poly) * many {kind, name}
Spike research_refs Research many name yes yes
StatusReport evidence_refs (poly) * many Kind/name
Story dependencies Story many name yes
Story feature Feature one name yes stories
Story produces (poly) * many {kind, name}
Story spec_refs Spec many name yes
Story sprint_ref Sprint one name yes
Task produces (poly) * many {kind, name}
Task story_ref Story one name yes
TenantMembership tenant_slug Tenant one slug
TestGuide verifies (poly) Bug many Kind/name yes
TestGuide verifies (poly) Epic many Kind/name yes
TestGuide verifies (poly) Feature many Kind/name yes
TestGuide verifies (poly) Initiative many Kind/name yes
TestGuide verifies (poly) Issue many Kind/name yes
TestGuide verifies (poly) Spike many Kind/name yes
TestGuide verifies (poly) Story many Kind/name yes
TestGuide verifies (poly) Task many Kind/name yes
TestRun evidence (poly) * many Kind/name
TestRun guide_ref TestGuide one name yes
TestRun verifies (poly) Bug many Kind/name yes
TestRun verifies (poly) Epic many Kind/name yes
TestRun verifies (poly) Feature many Kind/name yes
TestRun verifies (poly) Initiative many Kind/name yes
TestRun verifies (poly) Issue many Kind/name yes
TestRun verifies (poly) Spike many Kind/name yes
TestRun verifies (poly) Story many Kind/name yes
TestRun verifies (poly) Task many Kind/name yes
WorkflowEvent epic_ref Epic one name yes
WorkflowEvent feature_ref Feature one name yes
WorkflowEvent parent_ref (poly) AgentSession one Kind/name
WorkflowEvent parent_ref (poly) Epic one Kind/name
WorkflowEvent parent_ref (poly) Feature one Kind/name
WorkflowEvent parent_ref (poly) Narrative one Kind/name
WorkflowEvent parent_ref (poly) Plan one Kind/name
WorkflowEvent parent_ref (poly) Roadmap one Kind/name
WorkflowEvent parent_ref (poly) Spec one Kind/name
WorkflowEvent parent_ref (poly) Story one Kind/name
WorkflowEvent ref (poly) AgentSession one Kind/name
WorkflowEvent ref (poly) Epic one Kind/name
WorkflowEvent ref (poly) Feature one Kind/name
WorkflowEvent ref (poly) Narrative one Kind/name
WorkflowEvent ref (poly) Plan one Kind/name
WorkflowEvent ref (poly) Roadmap one Kind/name
WorkflowEvent ref (poly) Spec one Kind/name
WorkflowEvent ref (poly) Story one Kind/name
WorkflowEvent transitioned_from WorkflowEvent one name yes
WorkspaceMembership role Role one role_id yes
WorkspaceMembership workspace_id Workspace one workspace_id
WorkspaceScopeGrant workspace_id Workspace one workspace_id

Composition edges (dep_filters only)

Declared for prompt composition, never validated against stored data. Each row is a candidate for promotion to a relation.

From Field To Cardinality By Enforced Inverse of Cross-group
Agent actors Actor one name
Agent guardrails Guardrail many name yes
Agent skills Skill many name yes
Agent soul Soul one name yes
Agent tools Tool many name
AgentSession participants Actor many name yes
Bug fix_adr ADR one name
Bug related_feature Feature one name
Bug related_story Story one name
Feature owner Actor one name yes
Feature use_cases UseCase many name yes
Initiative owner Actor one name yes
Issue owner Actor one name yes
Issue related_feature Feature one name
Kaizen issue Issue one name
Narrative covers_epics Epic many name
Narrative covers_features Feature many name
Narrative covers_stories Story many name
Postmortem related_features Feature many name
Postmortem related_stories Story many name
Retrospective covers_epics Epic many name
Retrospective covers_features Feature many name
Retrospective covers_session AgentSession one name
Retrospective covers_stories Story many name
RiskRegister owner Actor one name yes
RiskRegister related_epics Epic many name
RiskRegister related_features Feature many name
Roadmap epics Epic one name
SafetyPolicy recognizers Recognizer many name yes
Spike feature Feature one name
Spike follow_up_adr ADR one name
Spike follow_up_spec Spec one name
Spike follow_up_story Story one name
Spike references Reference many name
Spike related_spikes Spike many name
Story owner Actor one name yes
Task owner Actor one name yes
UseCase agents Agent many name
UseCase guardrails Guardrail many name yes
UseCase primary_actor Actor one name
UseCase skills Skill many name yes
UseCase soul Soul one name yes
UseCase supporting_actors Actor many name
UseCase tools Tool many name

What this model cannot express

A MER that implies completeness is worse than none. These are the known gaps, generated alongside everything else so they cannot be quietly dropped.

Gaps

This shrinks when relations get declared, not when the generator gets cleverer.

Origin is the column that keeps the list honest. declared, composition and inverse rows are declarations the model cannot honour — somebody wrote a target, an alias or an inverse and it does not resolve. undeclared rows are fields whose NAME looks like a reference and which nothing declares; they are usually not references at all (an OAuth client_id, a Stripe customer id, an IdP subject), and this generator no longer guesses a target for them. Reading the two alike is how a real broken reference arrives invisible in a list of false alarms.

The known-undeclarable table that used to sit here is gone, and its absence is the point: those were real references the annotation could not express. They are declared relations now, in the table above, with Enforced blank.

An undeclared row can now be ANSWERED rather than only asked — see the next table. What is left here is what somebody decided to leave, with the reason recorded in the Kind and in tests/test_kind_graph_registry.py.

Kind Field Origin Why unresolved
Initiative theme_ref undeclared reference-shaped field name, and neither a relation nor an identifier declares what it is
LayerPolicy layer_id undeclared reference-shaped field name, and neither a relation nor an identifier declares what it is

Fields that are NOT references (20)

The gap list above is short because these fields ANSWERED it. A reference-shaped name with no relation used to be an invitation with no way of being accepted, so two thirds of the rows were permanent by construction. spec.identifiers is how a Kind says a field points nowhere — self for the instance's own key, external plus the minting authority for an id that belongs to another system.

This is not the retired inference denylist: the gap row asserts no target, so nothing false is being silenced, and the answer lives on the Kind beside its schema rather than in a central table that can go stale against a Kind it no longer describes.

Kind Field Role Minted by
AgentCatalogEntry client_id external oauth
AgentCatalogEntry registered_by external idp
AgentGrant client_id external oauth
AgentGrant subject external idp
AgentSession session_id external agent-tool
AuditLog request_id external http-request
GenUIComponent renderer_ref external ui-host
ModelProfile model_id self
PlanBinding account_id self
PlanBinding stripe_customer_id external stripe
PlanBinding stripe_subscription_id external stripe
PricingPlan tier_id self
Role role_id self
Sprint sprint_id self
TenantMembership user_id external idp
UserProfile user_id external idp
UserRoleAssignment user_id self
Workspace account_id external idp
Workspace workspace_id self
WorkspaceMembership identity_oid external entra

Kinds with no reference edge (22)

Standalone instances — configuration, composition-plane behaviour, or record Kinds whose links are simply not modelled yet.

AgentCatalogEntry, AgentDefinition, AgentGrant, AuditLog, Automation, Canvas, Changelog, CognitivePolicy, Doc, EvidencePolicy, Hook, HtmlArtifact, KindDefinition, LayerPolicy, Lesson, Memory, PromptTemplate, RemoteAgent, Setting, Theme, UserProfile, UserRoleAssignment

Physical model — the real tables

This diagram carries little information, by design

11 tables on Postgres (5 on SQLite) and 1 foreign keys. They are a generic instance store: instances holds every Kind, of every type, as JSON in a content column keyed by (scope, kind, name, tenant). Adding a Kind adds rows, never a table — so the physical diagram cannot show you the domain. The logical model above is where the domain lives. This section exists to be accurate, not to look deep.

Postgres

erDiagram
    dna_approval {
        TEXT approval_id PK
        TEXT turn_id
        TEXT thread_id
        TEXT workspace
        TEXT oid
        TEXT actor_email
        TEXT tool
        TEXT arguments
        TEXT decision
        TEXT edited_args
        TEXT reason
        DATETIME requested_at
        DATETIME decided_at
    }
    dna_bundle_entries {
        TEXT scope PK
        TEXT kind PK
        TEXT api_version PK
        TEXT name PK
        TEXT entry_path PK
        TEXT content
        TEXT updated_at
        TEXT tenant PK
        BLOB content_binary
    }
    dna_edges {
        TEXT scope PK
        TEXT tenant PK
        TEXT from_api_version PK
        TEXT from_kind PK
        TEXT from_name PK
        TEXT source_field PK
        INTEGER ordinal PK
        TEXT to_scope
        TEXT to_kind
        TEXT to_name
        TEXT to_id
        TEXT to_api_version
        TEXT declared_to
        INTEGER from_version
        DATETIME updated_at
        DATETIME to_deleted_at
    }
    dna_instances {
        TEXT scope PK
        TEXT kind PK
        TEXT api_version PK
        TEXT name PK
        TEXT id
        TEXT content
        INTEGER version
        TEXT updated_at
        TEXT tenant PK
        TSTZRANGE valid_at
    }
    dna_layer_instances {
        TEXT scope PK
        TEXT layer_id PK
        TEXT layer_value PK
        TEXT kind PK
        TEXT name PK
        TEXT content
        TEXT updated_at
    }
    dna_outbox {
        BIGINT id PK
        DATETIME occurred_at
        TEXT scope
        TEXT tenant
        TEXT kind
        TEXT name
        TEXT op
        INTEGER doc_version
        TEXT actor
        TEXT cause
    }
    dna_quota_counters {
        DATE day PK
        TEXT tenant PK
        TEXT tier PK
        BIGINT calls
    }
    dna_turn {
        TEXT turn_id PK
        TEXT trace_id
        TEXT thread_id
        TEXT workspace
        TEXT oid
        TEXT agent
        TEXT model
        TEXT input_text
        TEXT output_text
        INTEGER input_tokens
        INTEGER output_tokens
        BOOLEAN tokens_partial
        TEXT status
        TEXT outcome
        TEXT lane
        TEXT error
        DATETIME started_at
        DATETIME ended_at
        INTEGER duration_ms
    }
    dna_turn_step {
        TEXT turn_id PK
        INTEGER step_index PK
        TEXT name
        TEXT input
        TEXT output
        TEXT status
        TEXT error
        DATETIME started_at
        INTEGER duration_ms
    }
    dna_versions {
        INTEGER id PK
        TEXT scope
        TEXT kind
        TEXT api_version
        TEXT name
        TEXT content
        INTEGER version
        BOOLEAN is_draft
        TEXT author
        TEXT created_at
        TEXT tenant
        TEXT semver
    }
    dna_versions_seq {
        TEXT scope PK
        TEXT tenant PK
        BIGINT last_id
        DATETIME last_at
    }

No lines connect these boxes because there are no foreign keys to draw. The join key is (scope, kind, name, tenant), applied in application code.

Dialect differences

The dialects are genuinely disjoint — Postgres tables carry a dna_ prefix, SQLite's do not, and Postgres has tables SQLite lacks.

Postgres SQLite
dna_approval
dna_bundle_entries bundle_entries
dna_edges edges
dna_instances instances
dna_layer_instances layer_instances
dna_outbox
dna_quota_counters
dna_turn
dna_turn_step
dna_versions versions
dna_versions_seq

Columns

dna_approval

Column Type Key Nullable
approval_id TEXT PK
turn_id TEXT
thread_id TEXT
workspace TEXT
oid TEXT
actor_email TEXT
tool TEXT
arguments TEXT
decision TEXT
edited_args TEXT
reason TEXT
requested_at DATETIME
decided_at DATETIME yes

dna_bundle_entries

Column Type Key Nullable
scope TEXT PK
kind TEXT PK
api_version TEXT PK
name TEXT PK
entry_path TEXT PK
content TEXT
updated_at TEXT
tenant TEXT PK
content_binary BLOB yes

dna_edges

Column Type Key Nullable
scope TEXT PK
tenant TEXT PK
from_api_version TEXT PK
from_kind TEXT PK
from_name TEXT PK
source_field TEXT PK
ordinal INTEGER PK
to_scope TEXT yes
to_kind TEXT yes
to_name TEXT
to_id TEXT yes
to_api_version TEXT yes
declared_to TEXT
from_version INTEGER
updated_at DATETIME
to_deleted_at DATETIME yes

dna_instances

Column Type Key Nullable
scope TEXT PK
kind TEXT PK
api_version TEXT PK
name TEXT PK
id TEXT yes
content TEXT
version INTEGER
updated_at TEXT
tenant TEXT PK
valid_at TSTZRANGE

dna_layer_instances

Column Type Key Nullable
scope TEXT PK
layer_id TEXT PK
layer_value TEXT PK
kind TEXT PK
name TEXT PK
content TEXT
updated_at TEXT

dna_outbox

Column Type Key Nullable
id BIGINT PK
occurred_at DATETIME
scope TEXT
tenant TEXT
kind TEXT
name TEXT
op TEXT
doc_version INTEGER
actor TEXT yes
cause TEXT yes

dna_quota_counters

Column Type Key Nullable
day DATE PK
tenant TEXT PK
tier TEXT PK
calls BIGINT

dna_turn

Column Type Key Nullable
turn_id TEXT PK
trace_id TEXT
thread_id TEXT
workspace TEXT
oid TEXT
agent TEXT
model TEXT
input_text TEXT yes
output_text TEXT yes
input_tokens INTEGER
output_tokens INTEGER
tokens_partial BOOLEAN yes
status TEXT
outcome TEXT
lane TEXT
error TEXT yes
started_at DATETIME
ended_at DATETIME yes
duration_ms INTEGER

dna_turn_step

Column Type Key Nullable
turn_id TEXT PK
step_index INTEGER PK
name TEXT
input TEXT yes
output TEXT yes
status TEXT
error TEXT yes
started_at DATETIME
duration_ms INTEGER

dna_versions

Column Type Key Nullable
id INTEGER PK
scope TEXT
kind TEXT
api_version TEXT
name TEXT
content TEXT
version INTEGER
is_draft BOOLEAN
author TEXT yes
created_at TEXT
tenant TEXT
semver TEXT yes

dna_versions_seq

Column Type Key Nullable
scope TEXT PK
tenant TEXT PK
last_id BIGINT
last_at DATETIME