from @unified-product-graph/core/grammar · re-exported by @sdk
Grammar
Lifecycle definitions, hierarchy rules, scale enumerations, and edge migrations.
97 exports · 20 const · 8 type · 26 interface · 43 fn
Since v0.2.0Quick import
import { UPG_MIGRATIONS, UPG_LIFECYCLES } from '@unified-product-graph/core'Example
// Inspect what changed across spec versions
import { UPG_MIGRATIONS, UPG_LIFECYCLES } from '@unified-product-graph/core'
console.log(Object.keys(UPG_MIGRATIONS))
// → ['0.9.0', '0.7.0', '0.4.0', '0.2.8', '0.1.0', '0.2.0']
const opportunity = UPG_LIFECYCLES.find(l => l.entity_type === 'opportunity')
console.log(opportunity?.initial_phase) // → 'identified'Lifecycle definitions, hierarchy rules, scale enumerations, and edge migrations. Use when generating canonical edge keys (resolveContainmentEdge), applying v-to-v migration maps to legacy graphs, or validating that a node's lifecycle value is within spec.
Exports
Constants
ReadonlySet<NonNullable<"property-type" | "property-enum" | "self-loop" | "framework-score" | undefined>>Types
type Configuration = Readonly<Record<string, string>>A configuration: axis node id to the single value that holds on it.
type ConfigurationDriftKind = | 'axis_values_empty' | 'axis_default_not_a_value' | 'present_under_empty' | 'present_under_unknown_value' | 'qualifi...The kinds of configuration drift the validator reports.
type CrossProductScope = 'curated' | 'provisional' | 'resident'The three cross-product states a directed relationship can occupy.
type StatusCategory = | 'triage' | 'backlog' | 'unstarted' | 'started' | 'completed' | 'cancelled'The near-universal PM-tool status bucket a phase belongs to (0.25.1 feedback 1ee70102) — the same six-bucket system Linear, Jira, Asana, and GitHub Projects converge on.
type UPGEdgeMigration = | { kind: 'rename' /** The old edge type key. */ from: string /** The new canonical edge type key. */ to: string /** ...A single edge-key migration rule.
type UPGPropertyMigration = | { kind: 'drop_props' /** The entity type whose properties are being migrated. */ type: string /** Property keys to ...A property-level migration applied at load time.
type UPGPropertyMigrationChange = | { kind: 'dropped'; key: string } | { kind: 'renamed_top_level'; from: string; to: string; value_changed: boolean } ...A single property-migration change applied during `migrateNodeProperties`.
type WalkMigrationChainResult = | { kind: 'canonical'; to: string } | { kind: 'drop' } | { kind: 'dead_end'; last: string } | { kind: 'cycle'; visite...Walk the edge-migration chain for `edge_type` until reaching a value that exists in `UPG_EDGE_CATALOG` (the current canonical name) or the chain dead-ends.
Interfaces
interface LifecycleRenderShapeA flattened, render-ready shape derived from a single `UPGLifecycle`.
interface LifecycleRenderStateA render-ready lifecycle state (one phase of the underlying lifecycle).
interface LifecycleRenderTransitionA render-ready transition between two lifecycle states.
interface ProjectionResultResult of a projection: the surviving nodes and edges, plus what it dropped.
interface UPGEdgeMigrationEndpointsEndpoint context for `migrateEdge` guard evaluation.
interface UPGLifecycleA lifecycle defines the valid phase-and-state journey for an entity type.
interface UPGScalarToEdgeMigrationPromote a scalar property that names a first-class entity into a canonical edge.
interface UPGScaleDefinitionA scale definition provides the vocabulary for assessments
interface UPGSplitEdgeA canonical edge to emit between spawned targets, gated by a condition.
interface UPGSplitRouteTargetPer-target route plan: what to spawn and what overrides apply.
Functions
(childType: string, parentType: string) => booleanReturns `true` if `childType` is a permitted direct child of `parentType` according to the UPG hierarchy.
(nodes: ProjectableNode[], edges: ProjectableEdge[]) => ConfigurationDriftFinding[]Check every configuration declaration in a graph.
(nodes: readonly Pick<UPGBaseNode, 'type' | 'slug' | 'aliases'>[], type: string) => Set<string>Build the existing-slug set for a `(type)` cohort within a single product.
(a: string, b: string) => numberCompare two semver-style version strings of the form `MAJOR.MINOR.PATCH`.
(edgeType: string) => CrossProductScopeClassify an edge TYPE into the 3-state cross-product model.
(nodes: ProjectableNode[]) => { axis?: string | undefined; value?: string | undefined; configuration: Readonly<Record<string, string>>; }[]Every configuration this graph can be projected onto, one axis at a time.
() => { entity_type: string; from: string; to: string; reason: "no_lifecycle" | "unknown_phase"; }[]Spec-coherence helper: returns the entity types in `UPG_STATUS_MIGRATIONS` whose registered canonical replacements are NOT valid phases in the type's lifecycle.
(scaleId: string, word: string) => { value: number; label: string; scale_id: string; } | nullResolve a friendly word (e.g.
(name: string) => UPGEnumScaleDefinition | undefinedLook up a full enum scale definition by its type name.
(scaleName: string, value: string) => UPGEnumScaleValue | undefinedLook up per-value metadata within a named enum scale.
(entityType: string) => UPGLifecycle | undefinedReturns the lifecycle definition for a given entity type, or `undefined` if the type does not have a lifecycle.
(entityType: string) => LifecycleRenderShape | nullReturns a render-ready `{ states, transitions }` shape for an entity type's lifecycle, or `null` if the type is intentionally lifecycle-free (see {@link UPG_LIFECYCLE_FREE_TYPES}).
(fromVersion: string, toVersion: string) => Record<string, string>Build a flat old→new type name map for a specific version upgrade.
(scaleId: string) => string[]Inverse of `PROPERTY_SCALE_MAP`: the canonical property names that default to a given scale, in declaration order.
(entityType: string, propertyName: string) => stringReturn the default scale ID for a given entity-type / property-name pair.
(fromVersion: string, toVersion: string) => UPGPropertyMigration[]Returns every property migration entry between two versions; useful for load-time warning generation and audit reports.
(fromVersion: string, toVersion: string) => UPGScalarToEdgeMigration[]Get all scalar→edge promotions between two versions.
(scaleId: string) => UPGScaleDefinition | undefinedLook up a scale definition by its ID.
(fromVersion: string, toVersion: string) => UPGSplitMigration[]Get all 1→N split migrations between two versions.
(fromVersion: string, toVersion: string) => UPGEdgeMigration[]Get all edge migration rules between two versions, in version order.
(entityType: string) => readonly string[]Returns the list of valid child entity types for the given parent type.
(entityType: string, currentStatus: string) => booleanReturn true when the (entityType, currentStatus) pair has a registered canonical replacement that ALSO differs from the current value.
(entityType: string) => booleanReturns `true` if `entityType` is containment-free, i.e.
(sourceType: string, targetType: string) => booleanThe shared-tier GATE: is a directed edge between these endpoint types authorable across product graphs at all?
(edgeType: string) => booleanTrue if this cross-edge type is in the curated canonical set (`UPG_CROSS_EDGE_TYPES`, the 61).
(entityType: string) => booleanReturns `true` if an entity type is intentionally lifecycle-free (see {@link UPG_LIFECYCLE_FREE_TYPES} for the full list and rationale).
(entityType: string) => booleanReturns `true` if an entity type has a lifecycle planned for a later phase (see {@link UPG_LIFECYCLE_PLANNED_TYPES}).
(doc: unknown) => booleanType guard: returns true if the document is a valid UPGDocument.
() => { entity_type: string; from: string; to: string; }[]Audit helper: enumerate every (entityType, legacyStatus, canonicalStatus) triple in the registry.
(edge: T, fromVersion: string, toVersion: string, endpoints?: UPGEdgeMigrationEndpoints) => T | nullApply edge migrations to a single edge.
(node: T, fromVersion: string, toVersion: string) => TApply migrations to a single node, converting its type and merging default properties.
(node: T, fromVersion: string, toVersion: string) => { node: T; changes: UPGPropertyMigrationChange[]; }Apply property migrations to a single node.
(entityType: string, currentStatus: string) => string | nullLook up the canonical replacement for a legacy status value on the given entity type.
(nodes: N[], edges: E[], configuration: Configuration) => ProjectionResult<N, E>Project a graph onto one configuration.
(edge: ProjectableEdge) => { axis: string; values: string[]; } | undefinedRead an `active_when` qualifier, or undefined when the edge carries none or carries something malformed.
(properties: Record<string, unknown> | undefined, key: string) => string[] | undefinedRead a string array property defensively; anything else reads as absent.
(base: string, existing: ReadonlySet<string>) => stringResolve a base slug against an existing-slug set, appending `-2`, `-3`, etc.
(node: T, next: string) => TRotate a slug rename: push the old slug into `aliases[]` (deduped) and set the new slug.
(doc: unknown) => UPGValidationResultValidates a UPGDocument against the UPG v0.2 specification.