@unified-product-graph/core 0.11.2 → 0.11.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -129,7 +129,7 @@ interface UPGBaseNode {
129
129
  * AUTO-GENERATED by scripts/generate-property-registry.ts
130
130
  * Do not edit manually. Run: npx tsx scripts/generate-property-registry.ts
131
131
  *
132
- * Generated: 2026-06-14T07:17:48.412Z
132
+ * Generated: 2026-06-14T09:18:17.518Z
133
133
  * Entity types with properties: 319
134
134
  */
135
135
  interface PropertyDefinition {
@@ -11046,6 +11046,17 @@ interface ClassificationAxisProperties {
11046
11046
  * `continuous` = numeric range (latency budget, price points).
11047
11047
  */
11048
11048
  axis_kind?: 'categorical' | 'ordinal' | 'continuous';
11049
+ /**
11050
+ * How many values a subject may hold on this axis at once (UPG 0.11.3).
11051
+ * `single` (default) = a subject sits at exactly one value; a re-classification
11052
+ * to a new value SUPERSEDES the prior one (the classify writer retires the old
11053
+ * same-axis edge and records the move in the reclassification history).
11054
+ * `multi` = a subject may legitimately hold several values at once (e.g. an
11055
+ * axis like "supported frameworks"); re-classifying ADDS a value and does not
11056
+ * supersede. A separate axis from `axis_kind`: an axis can be `categorical`
11057
+ * (unordered) yet `single`-select, or `categorical` yet `multi`-select.
11058
+ */
11059
+ cardinality?: 'single' | 'multi';
11049
11060
  /** Product id when product-specific. Axes are usually product-agnostic; leave empty for shared taxonomies. */
11050
11061
  owner_product?: string;
11051
11062
  }
@@ -18996,6 +19007,25 @@ interface UPGTreeChild {
18996
19007
  * when present and are silent when absent.
18997
19008
  */
18998
19009
  required?: boolean;
19010
+ /**
19011
+ * The node property `get_tree` sorts this slot's children by (ascending,
19012
+ * nodes lacking it last). Ordering is a property of the DATA, not the viewer,
19013
+ * so the server returns children pre-sorted rather than leaving every client
19014
+ * to re-sort (UPG-663 sequence scalars: `phase_order`, `step_order`,
19015
+ * `action_order`, `state_order`). Omitted -> children keep declared slot order.
19016
+ */
19017
+ order_by?: string;
19018
+ /**
19019
+ * Spine resolution for a DAG. When this slot reaches the SAME node redundantly
19020
+ * with a path through a sibling type (e.g. `user_journey -> journey_step`
19021
+ * directly AND `user_journey -> journey_phase -> journey_step`), name that
19022
+ * sibling type here. A child also reachable as a grandchild through a
19023
+ * `prefer_via`-typed child renders under that spine, NOT here -- collapsing the
19024
+ * redundant path so the node is neither silently dropped (G5) nor
19025
+ * double-counted (J1). A child not on the spine still renders here, so the
19026
+ * direct path remains the fallback when the grouping layer is absent.
19027
+ */
19028
+ prefer_via?: string;
18999
19029
  }
19000
19030
  /** How a pattern decides what counts as a structural gap. */
19001
19031
  type UPGTreeGapPolicy = 'required-children-only' | 'all-optional';
@@ -19065,6 +19095,10 @@ interface UPGTreePatternEdge {
19065
19095
  /** The edge's classification (hierarchy, semantic, cross-domain, ...), or null. */
19066
19096
  kind: string | null;
19067
19097
  required: boolean;
19098
+ /** Node scalar this slot's children are sorted by, when declared (J2). */
19099
+ order_by?: string;
19100
+ /** Sibling type whose path is the canonical spine for this child (J1), when declared. */
19101
+ prefer_via?: string;
19068
19102
  }
19069
19103
  /** A pattern with its child map resolved to concrete edges (for introspection). */
19070
19104
  interface UPGTreePatternDetail extends UPGTreePattern {
@@ -21549,7 +21583,7 @@ declare function isCanonical(text: string): boolean;
21549
21583
  * it stamps the `upg_version` field of every `.upg` file written by the SDK.
21550
21584
  * The `check:version-lockstep` gate enforces this at release time.
21551
21585
  */
21552
- declare const UPG_VERSION: "0.11.2";
21586
+ declare const UPG_VERSION: "0.11.4";
21553
21587
  /**
21554
21588
  * The `.upg` JSON document format version. Written to the `upg_version` field.
21555
21589
  * Evolves independently from `UPG_VERSION` (the catalogue version).
package/dist/index.d.ts CHANGED
@@ -129,7 +129,7 @@ interface UPGBaseNode {
129
129
  * AUTO-GENERATED by scripts/generate-property-registry.ts
130
130
  * Do not edit manually. Run: npx tsx scripts/generate-property-registry.ts
131
131
  *
132
- * Generated: 2026-06-14T07:17:48.412Z
132
+ * Generated: 2026-06-14T09:18:17.518Z
133
133
  * Entity types with properties: 319
134
134
  */
135
135
  interface PropertyDefinition {
@@ -11046,6 +11046,17 @@ interface ClassificationAxisProperties {
11046
11046
  * `continuous` = numeric range (latency budget, price points).
11047
11047
  */
11048
11048
  axis_kind?: 'categorical' | 'ordinal' | 'continuous';
11049
+ /**
11050
+ * How many values a subject may hold on this axis at once (UPG 0.11.3).
11051
+ * `single` (default) = a subject sits at exactly one value; a re-classification
11052
+ * to a new value SUPERSEDES the prior one (the classify writer retires the old
11053
+ * same-axis edge and records the move in the reclassification history).
11054
+ * `multi` = a subject may legitimately hold several values at once (e.g. an
11055
+ * axis like "supported frameworks"); re-classifying ADDS a value and does not
11056
+ * supersede. A separate axis from `axis_kind`: an axis can be `categorical`
11057
+ * (unordered) yet `single`-select, or `categorical` yet `multi`-select.
11058
+ */
11059
+ cardinality?: 'single' | 'multi';
11049
11060
  /** Product id when product-specific. Axes are usually product-agnostic; leave empty for shared taxonomies. */
11050
11061
  owner_product?: string;
11051
11062
  }
@@ -18996,6 +19007,25 @@ interface UPGTreeChild {
18996
19007
  * when present and are silent when absent.
18997
19008
  */
18998
19009
  required?: boolean;
19010
+ /**
19011
+ * The node property `get_tree` sorts this slot's children by (ascending,
19012
+ * nodes lacking it last). Ordering is a property of the DATA, not the viewer,
19013
+ * so the server returns children pre-sorted rather than leaving every client
19014
+ * to re-sort (UPG-663 sequence scalars: `phase_order`, `step_order`,
19015
+ * `action_order`, `state_order`). Omitted -> children keep declared slot order.
19016
+ */
19017
+ order_by?: string;
19018
+ /**
19019
+ * Spine resolution for a DAG. When this slot reaches the SAME node redundantly
19020
+ * with a path through a sibling type (e.g. `user_journey -> journey_step`
19021
+ * directly AND `user_journey -> journey_phase -> journey_step`), name that
19022
+ * sibling type here. A child also reachable as a grandchild through a
19023
+ * `prefer_via`-typed child renders under that spine, NOT here -- collapsing the
19024
+ * redundant path so the node is neither silently dropped (G5) nor
19025
+ * double-counted (J1). A child not on the spine still renders here, so the
19026
+ * direct path remains the fallback when the grouping layer is absent.
19027
+ */
19028
+ prefer_via?: string;
18999
19029
  }
19000
19030
  /** How a pattern decides what counts as a structural gap. */
19001
19031
  type UPGTreeGapPolicy = 'required-children-only' | 'all-optional';
@@ -19065,6 +19095,10 @@ interface UPGTreePatternEdge {
19065
19095
  /** The edge's classification (hierarchy, semantic, cross-domain, ...), or null. */
19066
19096
  kind: string | null;
19067
19097
  required: boolean;
19098
+ /** Node scalar this slot's children are sorted by, when declared (J2). */
19099
+ order_by?: string;
19100
+ /** Sibling type whose path is the canonical spine for this child (J1), when declared. */
19101
+ prefer_via?: string;
19068
19102
  }
19069
19103
  /** A pattern with its child map resolved to concrete edges (for introspection). */
19070
19104
  interface UPGTreePatternDetail extends UPGTreePattern {
@@ -21549,7 +21583,7 @@ declare function isCanonical(text: string): boolean;
21549
21583
  * it stamps the `upg_version` field of every `.upg` file written by the SDK.
21550
21584
  * The `check:version-lockstep` gate enforces this at release time.
21551
21585
  */
21552
- declare const UPG_VERSION: "0.11.2";
21586
+ declare const UPG_VERSION: "0.11.4";
21553
21587
  /**
21554
21588
  * The `.upg` JSON document format version. Written to the `upg_version` field.
21555
21589
  * Evolves independently from `UPG_VERSION` (the catalogue version).
package/dist/index.js CHANGED
@@ -9637,6 +9637,7 @@ var UPG_PROPERTY_SCHEMA = {
9637
9637
  // ClassificationAxisProperties: ClassificationAxis: a dimension along which subjects are classified.
9638
9638
  classification_axis: {
9639
9639
  axis_kind: { type: "string", enum: ["categorical", "ordinal", "continuous"], description: "Structural kind of values on this axis. `categorical` = discrete, unordered (most common; CMS architectures). `ordinal` = discrete, ordered (maturity tiers, T-shirt sizes). `continuous` = numeric range (latency budget, price points)." },
9640
+ cardinality: { type: "string", enum: ["single", "multi"], description: 'How many values a subject may hold on this axis at once (UPG 0.11.3). `single` (default) = a subject sits at exactly one value; a re-classification to a new value SUPERSEDES the prior one (the classify writer retires the old same-axis edge and records the move in the reclassification history). `multi` = a subject may legitimately hold several values at once (e.g. an axis like "supported frameworks"); re-classifying ADDS a value and does not supersede. A separate axis from `axis_kind`: an axis can be `categorical` (unordered) yet `single`-select, or `categorical` yet `multi`-select.' },
9640
9641
  owner_product: { type: "string", description: "Product id when product-specific. Axes are usually product-agnostic; leave empty for shared taxonomies." }
9641
9642
  },
9642
9643
  // ClassificationValueProperties: ClassificationValue: a value on a classification axis.
@@ -19939,8 +19940,8 @@ function buildTypeAliases() {
19939
19940
  var UPG_TYPE_ALIASES = buildTypeAliases();
19940
19941
 
19941
19942
  // src/presentation/tree-patterns.ts
19942
- var req = (type) => ({ type, required: true });
19943
- var opt = (type) => ({ type });
19943
+ var req = (type, order_by) => order_by ? { type, required: true, order_by } : { type, required: true };
19944
+ var opt = (type, order_by) => order_by ? { type, order_by } : { type };
19944
19945
  var UPG_TREE_PATTERNS = [
19945
19946
  {
19946
19947
  id: "ost",
@@ -20126,11 +20127,18 @@ var UPG_TREE_PATTERNS = [
20126
20127
  anchor_type: "user_journey",
20127
20128
  fallback_anchors: ["user_flow"],
20128
20129
  child_map: {
20129
- user_journey: [opt("journey_phase"), opt("journey_step")],
20130
- journey_phase: [opt("journey_step")],
20131
- journey_step: [opt("journey_action"), opt("screen")],
20130
+ // The phase is the grouping layer: a step reachable through a phase
20131
+ // renders under the phase, not twice (J1). `prefer_via` collapses the
20132
+ // redundant direct path; a step in NO phase still renders here. Children
20133
+ // are returned in `*_order` sequence (J2), not storage order.
20134
+ user_journey: [
20135
+ opt("journey_phase", "phase_order"),
20136
+ { type: "journey_step", prefer_via: "journey_phase", order_by: "step_order" }
20137
+ ],
20138
+ journey_phase: [opt("journey_step", "step_order")],
20139
+ journey_step: [opt("journey_action", "action_order"), opt("screen")],
20132
20140
  user_flow: [opt("screen")],
20133
- screen: [opt("screen_state")]
20141
+ screen: [opt("screen_state", "state_order")]
20134
20142
  },
20135
20143
  natural_depth: 3
20136
20144
  },
@@ -20168,7 +20176,10 @@ function resolveTreePatternEdges(pattern) {
20168
20176
  for (const [parent, children] of Object.entries(pattern.child_map)) {
20169
20177
  for (const c of children) {
20170
20178
  const e = resolvePatternEdge(parent, c.type);
20171
- out.push({ parent, child: c.type, via: e?.via ?? null, kind: e?.kind ?? null, required: !!c.required });
20179
+ const row = { parent, child: c.type, via: e?.via ?? null, kind: e?.kind ?? null, required: !!c.required };
20180
+ if (c.order_by) row.order_by = c.order_by;
20181
+ if (c.prefer_via) row.prefer_via = c.prefer_via;
20182
+ out.push(row);
20172
20183
  }
20173
20184
  }
20174
20185
  return out;
@@ -28555,7 +28566,7 @@ function isCanonical(text) {
28555
28566
  }
28556
28567
 
28557
28568
  // src/index.ts
28558
- var UPG_VERSION = "0.11.2";
28569
+ var UPG_VERSION = "0.11.4";
28559
28570
  var UPG_FORMAT_VERSION = "0.4.0";
28560
28571
  var MARKDOWN_FORMAT_VERSION = "0.1";
28561
28572
  var UPG_TYPES = getTypes();