Skip to main content

validate_loaded_relations

Function validate_loaded_relations 

Source
pub fn validate_loaded_relations(
    store: &mut Store,
    schemas: &HashMap<String, Arc<Schema>>,
    mount_caps: &HashMap<String, MountCapability>,
    warnings: &mut Vec<WarningHint>,
)
Expand description

Validate every loaded entity’s ## Relationships entries against the source mem’s schema and the wiki-link grammar. Invalid relations are dropped from both the store’s edge index and the entity’s in-memory relationships list; each drop emits a PARSED_RELATION_INVALID warning naming the offending entity, rel-type, target, and reason.

Four reasons fire today:

  • grammar — the target id’s path does not match the wiki-link grammar (^[a-z0-9-]+(/[a-z0-9-]+)*$).
  • unknown_rel_type — the rel-type is not declared in the mem’s schema and the schema is in strict mode. Open-mode schemas admit the relation without a warning (mirrors the mutation surface).
  • shape — the (source_type, target_type) pair is not allowed by the declared source_types / target_types. target_type is looked up from the store post-load, so the check sees the real type for any target — including cross-mem targets loaded from another mount. Stub targets (no entity_type) skip the target-side check; the relation lands and the shape will be re-verified when the stub is promoted to a real entity.
  • cycle — the relation closes a cycle in an acyclic: true rel-type’s subgraph. Emitted by the second pass after grammar / rel-type / shape drops; the two-pass structure runs cycle detection after the initial relation-load so loading order doesn’t determine which edge gets blamed. Each cycle drops exactly one back-edge per DFS visit; multiple independent cycles each lose one edge.

Runs once at boot after every mount’s entities are pushed into the store. Mutation paths do not call this — they pre-validate via validate_rel_type + validate_rel_shape before the write, and every edge-writing verb (relate, create.relations[], update.declare_relations, and the batch paths) runs the shared cycle family (validate_edge_acyclicity: self-loop on listed no-self-loop rel-types, would_cycle on acyclic ones) in the same call. This sweep therefore covers pre-existing on-disk data only — entities written before the write-path gates closed, or edited out-of-band.