validate_graph
Walk the loaded graph and return a per-class, per-node report of schema drift plus anti-pattern violations from `UPG_ANTI_PATTERNS`. Schema-drift classes: non-canonical entity types, non-canonical edge types, top-level fields outside `UPGBaseNode`, invalid status values, self-referential `source_id`/`source_type`, properties matching `UPG_PROPERTY_MIGRATIONS` rules. Anti-patterns: catalog entries that fired against the live graph, sorted high → medium → low. Each entry carries `suggested_migration` (drift) or `remediation` (anti-pattern). Top-level `valid` is true iff drift is empty AND no violations fired. Read-only; pairs with `migrate_type`, `rename_edge_type`, `get_anti_pattern_violations_for`.
Arguments
scopestringoptionalWhich drift class(es) to include in the response (default "all"). Counts in `summary` are always returned for every class.
limitnumberoptionalMax entries per class (default 100, max 1000)
severitystringoptionalFilter anti-pattern violations to one severity tier.
anti_pattern_idsarrayoptionalRestrict anti-pattern evaluation to a subset of catalog ids (e.g. ["features-without-hypotheses"]).
skip_driftbooleanoptionalSkip the schema-drift block. Only returns anti-pattern violations.
skip_anti_patternsbooleanoptionalSkip anti-pattern evaluation. Only returns schema drift.
if_changed_sincestringoptionalHash from a previous response. Returns { changed: false } if graph unchanged.
include_polymorphic_upgradesbooleanoptionalWhen true, include a `polymorphic_with_typed_alternative` array listing polymorphic edges (e.g. node_owned_by_person, node_constrains_node) that have a more-specific typed alternative for their actual source/target pair. Opt-in only; omitted by default to avoid cluttering routine validation output. Does not affect `valid`; these are advisory suggestions.
Returns
{ valid, summary, entity_drift?, edge_drift?, property_drift?, top_level_drift?, lifecycle_drift?, self_referential?, anti_pattern_violations?, notes?, _hash }scope includes that class.limit (default 100).Examples
Live call against the Notion example graph.
Output
{
"valid": false,
"summary": {
"entity_drift": 0,
"edge_drift": 0,
"top_level_drift": 0,
"lifecycle_drift": 0,
"self_referential": 0,
"property_drift": 164,
"total_nodes": 2054,
"total_edges": 3216,
"spec_version": "0.7.3",
"scope": "all",
"limit": 100,
"anti_pattern_violations_high": 0,
"anti_pattern_violations_medium": 1,
"anti_pattern_violations_low": 0,
"edge_type_pair_drift": 100,
"graph_topology_self_loops": 0,
"property_type_drift": 100
},
"_hash": "c0f701e327319f2e",
"entity_drift": [],
"edge_drift": [],
"top_level_drift": [],
"lifecycle_drift": [],
"self_referential": [],
"property_drift": [
{
"id": "ec3d5479-4947-4bd9-9e77-b5ee01beb851",
"type": "product",
"property": "stage",
"via": "UPG_PROPERTY_MIGRATIONS['0.2.13']"
},
{
"id": "3f1c1804-b33b-4b1f-9094-c91cc8957912",
"type": "assumption",
"property": "validation_status",
"via": "UPG_PROPERTY_MIGRATIONS['0.5.0']"
},
{
"id": "6719fce7-61e7-44df-b6cf-92f7c7312554",
"type": "assumption",
"property": "validation_status",
"via": "UPG_PROPERTY_MIGRATIONS['0.5.0']"
},
{
"id": "7b22f5f3-b344-4e49-8d5a-35cf9087dc6c",
"type": "assumption",
"property": "validation_status",
"via": "UPG_PROPERTY_MIGRATIONS['0.5.0']"
… (truncated)Warnings
Top-level `valid` is true ONLY when both drift is empty AND no anti-pattern violations fired. Set `skip_anti_patterns: true` for a pure spec-shape check; `skip_drift: true` for catalog-only.