@unified-product-graph/core 0.16.2 → 0.17.1

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.cjs CHANGED
@@ -36,6 +36,7 @@ __export(index_exports, {
36
36
  BUSINESS_MARKETING_AUDIENCE_FIRST_PLAYBOOK: () => BUSINESS_MARKETING_AUDIENCE_FIRST_PLAYBOOK,
37
37
  CLASSIFICATION_EDGE_PROPERTY_SCHEMA: () => CLASSIFICATION_EDGE_PROPERTY_SCHEMA,
38
38
  CONTENT_DEPTH_WARNING_RULES: () => CONTENT_DEPTH_WARNING_RULES,
39
+ COVERAGE_ANTI_PATTERNS: () => COVERAGE_ANTI_PATTERNS,
39
40
  DEFAULT_ENTITY_EMOJI: () => DEFAULT_ENTITY_EMOJI,
40
41
  DEFERRED_PROPOSED_BY_CONTRACT: () => DEFERRED_PROPOSED_BY_CONTRACT,
41
42
  DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK: () => DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK,
@@ -55,8 +56,10 @@ __export(index_exports, {
55
56
  REFLECT_MODES: () => REFLECT_MODES,
56
57
  REGISTRY_PRODUCT_ID: () => REGISTRY_PRODUCT_ID,
57
58
  STRATEGY_OUTCOMES_PLAYBOOK: () => STRATEGY_OUTCOMES_PLAYBOOK,
59
+ THIN_GRAPH_THRESHOLD: () => THIN_GRAPH_THRESHOLD,
58
60
  UPG_ACTIVE_TYPES: () => UPG_ACTIVE_TYPES,
59
61
  UPG_ANTI_PATTERNS: () => UPG_ANTI_PATTERNS,
62
+ UPG_ANTI_PATTERN_CONCERNS: () => UPG_ANTI_PATTERN_CONCERNS,
60
63
  UPG_APPROACHES: () => UPG_APPROACHES,
61
64
  UPG_APPROACHES_BY_ID: () => UPG_APPROACHES_BY_ID,
62
65
  UPG_AREA_TAXONOMY: () => UPG_AREA_TAXONOMY,
@@ -95,6 +98,7 @@ __export(index_exports, {
95
98
  UPG_MIGRATIONS: () => UPG_MIGRATIONS,
96
99
  UPG_PLAYBOOKS: () => UPG_PLAYBOOKS,
97
100
  UPG_POLYMORPHIC_EDGE_KEYS: () => UPG_POLYMORPHIC_EDGE_KEYS,
101
+ UPG_PORTFOLIO_KINDS: () => UPG_PORTFOLIO_KINDS,
98
102
  UPG_PRODUCT_STAGES: () => UPG_PRODUCT_STAGES,
99
103
  UPG_PRODUCT_STAGE_COERCION_MAP: () => UPG_PRODUCT_STAGE_COERCION_MAP,
100
104
  UPG_PROPERTY_MIGRATIONS: () => UPG_PROPERTY_MIGRATIONS,
@@ -117,6 +121,7 @@ __export(index_exports, {
117
121
  UPG_TYPE_LABELS: () => UPG_TYPE_LABELS,
118
122
  UPG_TYPE_LABELS_MAP: () => UPG_TYPE_LABELS_MAP,
119
123
  UPG_TYPE_NAMES: () => UPG_TYPE_NAMES,
124
+ UPG_VALIDATION_PROFILES: () => UPG_VALIDATION_PROFILES,
120
125
  UPG_VALID_CHILDREN: () => UPG_VALID_CHILDREN,
121
126
  UPG_VERSION: () => UPG_VERSION,
122
127
  UPG_WILDCARD_ENDPOINT: () => UPG_WILDCARD_ENDPOINT,
@@ -129,6 +134,9 @@ __export(index_exports, {
129
134
  collectSlugsForType: () => collectSlugsForType,
130
135
  compareVersions: () => compareVersions,
131
136
  computeBodyChecksum: () => computeBodyChecksum,
137
+ concernEvaluatedFor: () => concernEvaluatedFor,
138
+ concernFor: () => concernFor,
139
+ concernGatesFor: () => concernGatesFor,
132
140
  describeTreePattern: () => describeTreePattern,
133
141
  edgeCarriesProperties: () => edgeCarriesProperties,
134
142
  evaluateAntiPatterns: () => evaluateAntiPatterns,
@@ -203,6 +211,7 @@ __export(index_exports, {
203
211
  isRegisteredPolymorphicEdge: () => isRegisteredPolymorphicEdge,
204
212
  isRuntimeStateShapedProperty: () => isRuntimeStateShapedProperty,
205
213
  isSubSequenceStep: () => isSubSequenceStep,
214
+ isThinCoverageAdvisory: () => isThinCoverageAdvisory,
206
215
  isUPGDocument: () => isUPGDocument,
207
216
  listPropertiesByModifier: () => listPropertiesByModifier,
208
217
  listStatusMigrations: () => listStatusMigrations,
@@ -228,6 +237,7 @@ __export(index_exports, {
228
237
  validateProductStageStrict: () => validateProductStageStrict,
229
238
  validateUPGDocument: () => validateUPGDocument,
230
239
  validateUPGFramework: () => validateUPGFramework,
240
+ validationProfileFor: () => validationProfileFor,
231
241
  walkMigrationChainToCanonical: () => walkMigrationChainToCanonical
232
242
  });
233
243
  module.exports = __toCommonJS(index_exports);
@@ -3408,9 +3418,13 @@ var UPG_CROSS_EDGE_TYPES = [
3408
3418
  "screen_targets_competitor",
3409
3419
  "feature_surfaces_product",
3410
3420
  "feature_uses_design_component",
3411
- "product_implements_design_system"
3421
+ "product_implements_design_system",
3422
+ // Org-link (0.17.0): dual-registered ownership edges (see UPGCrossEdgeType above).
3423
+ "node_owned_by_team",
3424
+ "node_owned_by_department"
3412
3425
  ];
3413
3426
  var REGISTRY_PRODUCT_ID = "registry";
3427
+ var UPG_PORTFOLIO_KINDS = ["owned", "watched", "strategic", "internal", "gtm"];
3414
3428
 
3415
3429
  // src/registry/entity-type-resolution.ts
3416
3430
  var TYPES = getTypes();
@@ -23603,7 +23617,8 @@ var TEAM_ORG_GUIDE = {
23603
23617
  anti_patterns: [
23604
23618
  { description: "Teams without OKRs: every team needs clear goals" },
23605
23619
  { description: "Dependencies without both teams linked: a dependency must connect blocker and blocked" },
23606
- { description: "Retrospectives without action items: reflection without action is just venting" }
23620
+ { description: "Retrospectives without action items: reflection without action is just venting" },
23621
+ { description: "Double-modelling the org as product_area and team_org: a product_area is the classification axis ON products (which area a product belongs to, the axis used to group products); a team_org department/team is the people structure (the org chart, who reports to whom). Use product_area to classify products and department/team for the org chart, and relate them through the team that owns an area rather than restating one as the other." }
23607
23622
  ]
23608
23623
  };
23609
23624
  var PROGRAM_MGMT_GUIDE = {
@@ -23712,7 +23727,8 @@ var PORTFOLIO_GUIDE = {
23712
23727
  ],
23713
23728
  anti_patterns: [
23714
23729
  { description: "Products without a product area: every product should be classified" },
23715
- { description: "Portfolios without strategic alignment: portfolio decisions should reflect strategy" }
23730
+ { description: "Portfolios without strategic alignment: portfolio decisions should reflect strategy" },
23731
+ { description: "Confusing product_area with the org chart: product_area is the classification axis on products (how products are grouped), not the people structure. Model who reports to whom with team_org department/team; relate the two through the team that owns an area." }
23716
23732
  ]
23717
23733
  };
23718
23734
  var WORKSPACE_GUIDE = {
@@ -26529,6 +26545,54 @@ var UPG_ANTI_PATTERNS = [
26529
26545
  severity: "medium",
26530
26546
  source: { kind: "practitioner", attribution: "Marty Cagan, Inspired (product discovery)" }
26531
26547
  },
26548
+ // ── Operating-function layer (0.17.0): member_kind: operating_function ─────
26549
+ // Carry concern 'operating' (UPG_ANTI_PATTERN_CONCERNS) and are evaluated ONLY
26550
+ // for operating_function graphs — a function a team operates (revenue / success
26551
+ // / finance / people / marketing), not a product it ships. The product-spine
26552
+ // patterns above are not evaluated for that kind (category errors); these assert
26553
+ // the function spine instead.
26554
+ {
26555
+ id: "operating-function-without-north-star",
26556
+ since: "0.17.0",
26557
+ name: "Operating function without a north-star metric",
26558
+ description: "An operating function graph has real content but no north-star metric to operate toward. A function (sales, finance, people, marketing) is run against one headline number it moves and that rolls up to the company tree. With no north-star metric the function has direction but nothing to steer by.",
26559
+ structured_condition: {
26560
+ operator: "and",
26561
+ checks: [
26562
+ { check: { type: "total_entity_count", comparison: "gt", threshold: 3 } },
26563
+ { check: { type: "entity_count", entity_type: "metric", filter: { property: "designation", value: "north_star" }, comparison: "zero" } }
26564
+ ]
26565
+ },
26566
+ why_it_matters: "A function with no north-star metric cannot be steered, prioritised, or rolled into the company metric tree. Operating work becomes activity without a measured target.",
26567
+ remediation: "Add the one `metric` the function operates toward and mark it `designation: north_star`, then wire it to the company metric tree via `metric_decomposes_into_metric`.",
26568
+ stages: ["concept", "validation", "build", "beta", "launch", "growth", "mature", "maintenance", "sunset"],
26569
+ severity: "high",
26570
+ source: { kind: "fundamental" }
26571
+ },
26572
+ {
26573
+ id: "operating-function-without-operating-content",
26574
+ since: "0.17.0",
26575
+ name: "Operating function without operating content",
26576
+ description: "An operating function graph has more than a few entities but none in any operating domain (sales, go-to-market, customer success, growth, marketing, business model, pricing). It carries direction and people but no operating substance: the work the function actually runs.",
26577
+ structured_condition: {
26578
+ operator: "and",
26579
+ checks: [
26580
+ { check: { type: "total_entity_count", comparison: "gt", threshold: 3 } },
26581
+ { check: { type: "domain_population", domain_id: "sales", comparison: "zero" } },
26582
+ { check: { type: "domain_population", domain_id: "go_to_market", comparison: "zero" } },
26583
+ { check: { type: "domain_population", domain_id: "customer_success", comparison: "zero" } },
26584
+ { check: { type: "domain_population", domain_id: "growth", comparison: "zero" } },
26585
+ { check: { type: "domain_population", domain_id: "marketing", comparison: "zero" } },
26586
+ { check: { type: "domain_population", domain_id: "business_model", comparison: "zero" } },
26587
+ { check: { type: "domain_population", domain_id: "pricing", comparison: "zero" } }
26588
+ ]
26589
+ },
26590
+ why_it_matters: "A function graph that is all strategy and org chart with no operating domain is a stub: it states intent but models none of the work the function runs, so it answers no operating questions.",
26591
+ remediation: "Populate at least one operating domain appropriate to the function (e.g. Field \u2192 `sales` / `go_to_market` / `customer_success`; Finance \u2192 `business_model` / `pricing`). Start from the matching template via `/upg-new-from-template`.",
26592
+ stages: ["concept", "validation", "build", "beta", "launch", "growth", "mature", "maintenance", "sunset"],
26593
+ severity: "medium",
26594
+ source: { kind: "fundamental" }
26595
+ },
26532
26596
  // ── Foundations layer (0.9.13): portfolio-scoped, registry-aware ──────────
26533
26597
  // These read the shared registry + cross-product edges, so they are evaluated
26534
26598
  // by portfolio_validate, not the single-graph evaluator. They carry no
@@ -26569,6 +26633,23 @@ var UPG_ANTI_PATTERNS = [
26569
26633
  stages: ["build", "beta", "launch", "growth", "mature"],
26570
26634
  severity: "low",
26571
26635
  source: { kind: "fundamental" }
26636
+ },
26637
+ // ── Operating-function org link (0.17.0): portfolio-scoped ─────────────────
26638
+ // Cross-product detector (in portfolio_validate): an operating_function graph
26639
+ // should reference the org unit it operates under, which lives once in the
26640
+ // rollup's team_org map. Carries no structured_condition — the org link is a
26641
+ // cross-product edge in portfolio.upg, not a single-graph shape.
26642
+ {
26643
+ id: "operating-function-without-org-link",
26644
+ since: "0.17.0",
26645
+ scope: "portfolio",
26646
+ name: "Operating function without an org link",
26647
+ description: "An operating_function graph does not reference the org unit it operates under. The department/team hierarchy lives once in the rollup (org_rollup) as team_org entities; a function should point its spine at the department or team that owns it (node_owned_by_department / node_owned_by_team), so the operating layer hangs off the canonical org map rather than re-stating it.",
26648
+ why_it_matters: "A function with no org link floats free of the org chart: its work cannot be rolled up by department, and the single source of truth for who owns what is bypassed.",
26649
+ remediation: "Add a cross-product node_owned_by_department (or node_owned_by_team) edge from the function spine to its department/team in the rollup. Mint the org unit once in the org_rollup graph; functions reference it.",
26650
+ stages: ["concept", "validation", "build", "beta", "launch", "growth", "mature", "maintenance", "sunset"],
26651
+ severity: "medium",
26652
+ source: { kind: "fundamental" }
26572
26653
  }
26573
26654
  ];
26574
26655
  function getAntiPatternById(id) {
@@ -26581,6 +26662,45 @@ function getAntiPatternsBySeverity(severity) {
26581
26662
  return UPG_ANTI_PATTERNS.filter((ap) => ap.severity === severity);
26582
26663
  }
26583
26664
 
26665
+ // src/intelligence/validation-profiles.ts
26666
+ var UPG_ANTI_PATTERN_CONCERNS = {
26667
+ // universal — kind-independent graph hygiene + strategy discipline
26668
+ "objective-without-key-results": "universal",
26669
+ "single-domain-graph": "universal",
26670
+ "orphan-loose-thoughts": "universal",
26671
+ // operating — only evaluated for operating_function graphs
26672
+ "operating-function-without-north-star": "operating",
26673
+ "operating-function-without-operating-content": "operating"
26674
+ // everything else defaults to 'product_spine'
26675
+ };
26676
+ function concernFor(antiPatternId) {
26677
+ return UPG_ANTI_PATTERN_CONCERNS[antiPatternId] ?? "product_spine";
26678
+ }
26679
+ var UPG_VALIDATION_PROFILES = {
26680
+ product: { evaluate_concerns: ["product_spine", "universal"], gating_concerns: ["product_spine", "universal"] },
26681
+ watched: { evaluate_concerns: ["product_spine", "universal"], gating_concerns: [] },
26682
+ org_rollup: { evaluate_concerns: ["product_spine", "universal"], gating_concerns: ["universal"] },
26683
+ operating_function: { evaluate_concerns: ["universal", "operating"], gating_concerns: ["universal", "operating"] }
26684
+ };
26685
+ function validationProfileFor(kind) {
26686
+ return UPG_VALIDATION_PROFILES[kind ?? "product"] ?? UPG_VALIDATION_PROFILES.product;
26687
+ }
26688
+ function concernEvaluatedFor(kind, concern) {
26689
+ return validationProfileFor(kind).evaluate_concerns.includes(concern);
26690
+ }
26691
+ function concernGatesFor(kind, concern) {
26692
+ return validationProfileFor(kind).gating_concerns.includes(concern);
26693
+ }
26694
+ var COVERAGE_ANTI_PATTERNS = /* @__PURE__ */ new Set([
26695
+ "single-domain-graph",
26696
+ "persona-count-below-stage-benchmark",
26697
+ "competitors-missing-past-validation"
26698
+ ]);
26699
+ var THIN_GRAPH_THRESHOLD = 8;
26700
+ function isThinCoverageAdvisory(antiPatternId, totalEntityCount) {
26701
+ return COVERAGE_ANTI_PATTERNS.has(antiPatternId) && totalEntityCount < THIN_GRAPH_THRESHOLD;
26702
+ }
26703
+
26584
26704
  // src/intelligence/evaluator.ts
26585
26705
  var SEVERITY_ORDER = {
26586
26706
  high: 0,
@@ -26598,8 +26718,10 @@ function evaluateAntiPatterns(inputs, options) {
26598
26718
  if (inputs.productStage && !ap.stages.includes(inputs.productStage)) {
26599
26719
  continue;
26600
26720
  }
26721
+ const concern = concernFor(ap.id);
26722
+ if (!concernEvaluatedFor(inputs.memberKind, concern)) continue;
26601
26723
  if (evaluateCondition(ap.structured_condition, inputs)) {
26602
- fires.push(buildViolation(ap));
26724
+ fires.push(buildViolation(ap, concern));
26603
26725
  }
26604
26726
  }
26605
26727
  fires.sort((a, b) => {
@@ -26668,11 +26790,12 @@ function compareNumber(value, comparison, threshold) {
26668
26790
  }
26669
26791
  }
26670
26792
  function evaluateEntityCount(check, inputs) {
26671
- const statusFilter = check.filter && typeof check.filter.status === "string" ? check.filter.status : void 0;
26793
+ const filter = check.filter;
26672
26794
  let count = 0;
26673
- if (statusFilter) {
26674
- const byStatus = inputs.countsByTypeAndStatus?.[check.entity_type];
26675
- count = byStatus?.[statusFilter] ?? 0;
26795
+ if (filter && typeof filter.property === "string" && typeof filter.value === "string") {
26796
+ count = inputs.countsByTypeAndProperty?.[check.entity_type]?.[filter.property]?.[filter.value] ?? 0;
26797
+ } else if (filter && typeof filter.status === "string") {
26798
+ count = inputs.countsByTypeAndStatus?.[check.entity_type]?.[filter.status] ?? 0;
26676
26799
  } else {
26677
26800
  count = inputs.countsByType[check.entity_type] ?? 0;
26678
26801
  }
@@ -26739,11 +26862,12 @@ function evaluateDomainPopulation(check, inputs) {
26739
26862
  function evaluateOrphanCount(check, inputs) {
26740
26863
  return compareNumber(inputs.orphanCount, check.comparison, check.threshold);
26741
26864
  }
26742
- function buildViolation(ap) {
26865
+ function buildViolation(ap, concern) {
26743
26866
  return {
26744
26867
  anti_pattern_id: ap.id,
26745
26868
  name: ap.name,
26746
26869
  severity: ap.severity,
26870
+ concern,
26747
26871
  target_entities: collectTargetEntities(ap.structured_condition),
26748
26872
  description: ap.description,
26749
26873
  why_it_matters: ap.why_it_matters,
@@ -29571,7 +29695,7 @@ function serializeSingleWithHeader(doc, opts) {
29571
29695
  const summary = deriveSummary(product.description);
29572
29696
  if (summary) header.summary = summary;
29573
29697
  header.counts = { nodes: doc.nodes?.length ?? 0, edges: doc.edges?.length ?? 0 };
29574
- if (doc.member_kind === "org_rollup" || doc.member_kind === "watched") {
29698
+ if (doc.member_kind === "org_rollup" || doc.member_kind === "watched" || doc.member_kind === "operating_function") {
29575
29699
  header.member_kind = doc.member_kind;
29576
29700
  }
29577
29701
  header.provenance = buildProvenance(doc, opts);
@@ -29597,10 +29721,12 @@ function serializePortfolioWithHeader(doc, opts) {
29597
29721
  const memberKindOf = (p) => p.member_kind ?? "product";
29598
29722
  const watchedCount = members.filter((p) => memberKindOf(p) === "watched").length;
29599
29723
  const rollupCount = members.filter((p) => memberKindOf(p) === "org_rollup").length;
29724
+ const operatingFunctionCount = members.filter((p) => memberKindOf(p) === "operating_function").length;
29600
29725
  header.counts = {
29601
29726
  products: members.filter((p) => memberKindOf(p) === "product").length,
29602
29727
  ...watchedCount > 0 ? { watched_products: watchedCount } : {},
29603
29728
  ...rollupCount > 0 ? { org_rollups: rollupCount } : {},
29729
+ ...operatingFunctionCount > 0 ? { operating_functions: operatingFunctionCount } : {},
29604
29730
  product_areas: doc.product_areas?.length ?? 0,
29605
29731
  portfolios: doc.portfolios?.length ?? 0,
29606
29732
  cross_edges: doc.cross_edges?.length ?? 0
@@ -29659,7 +29785,9 @@ function normalizeDocument(obj) {
29659
29785
  edges: raw.edges ?? []
29660
29786
  };
29661
29787
  const memberKind = header?.member_kind ?? raw.member_kind;
29662
- if (memberKind === "org_rollup" || memberKind === "watched") out.member_kind = memberKind;
29788
+ if (memberKind === "org_rollup" || memberKind === "watched" || memberKind === "operating_function") {
29789
+ out.member_kind = memberKind;
29790
+ }
29663
29791
  if (_integrity) out._integrity = _integrity;
29664
29792
  return out;
29665
29793
  }
@@ -29672,7 +29800,7 @@ function isCanonical(text) {
29672
29800
  }
29673
29801
 
29674
29802
  // src/index.ts
29675
- var UPG_VERSION = "0.16.2";
29803
+ var UPG_VERSION = "0.17.1";
29676
29804
  var UPG_FORMAT_VERSION = "0.4.0";
29677
29805
  var MARKDOWN_FORMAT_VERSION = "0.1";
29678
29806
  var UPG_TYPES = getTypes();
@@ -29743,6 +29871,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
29743
29871
  BUSINESS_MARKETING_AUDIENCE_FIRST_PLAYBOOK,
29744
29872
  CLASSIFICATION_EDGE_PROPERTY_SCHEMA,
29745
29873
  CONTENT_DEPTH_WARNING_RULES,
29874
+ COVERAGE_ANTI_PATTERNS,
29746
29875
  DEFAULT_ENTITY_EMOJI,
29747
29876
  DEFERRED_PROPOSED_BY_CONTRACT,
29748
29877
  DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK,
@@ -29762,8 +29891,10 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
29762
29891
  REFLECT_MODES,
29763
29892
  REGISTRY_PRODUCT_ID,
29764
29893
  STRATEGY_OUTCOMES_PLAYBOOK,
29894
+ THIN_GRAPH_THRESHOLD,
29765
29895
  UPG_ACTIVE_TYPES,
29766
29896
  UPG_ANTI_PATTERNS,
29897
+ UPG_ANTI_PATTERN_CONCERNS,
29767
29898
  UPG_APPROACHES,
29768
29899
  UPG_APPROACHES_BY_ID,
29769
29900
  UPG_AREA_TAXONOMY,
@@ -29802,6 +29933,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
29802
29933
  UPG_MIGRATIONS,
29803
29934
  UPG_PLAYBOOKS,
29804
29935
  UPG_POLYMORPHIC_EDGE_KEYS,
29936
+ UPG_PORTFOLIO_KINDS,
29805
29937
  UPG_PRODUCT_STAGES,
29806
29938
  UPG_PRODUCT_STAGE_COERCION_MAP,
29807
29939
  UPG_PROPERTY_MIGRATIONS,
@@ -29824,6 +29956,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
29824
29956
  UPG_TYPE_LABELS,
29825
29957
  UPG_TYPE_LABELS_MAP,
29826
29958
  UPG_TYPE_NAMES,
29959
+ UPG_VALIDATION_PROFILES,
29827
29960
  UPG_VALID_CHILDREN,
29828
29961
  UPG_VERSION,
29829
29962
  UPG_WILDCARD_ENDPOINT,
@@ -29836,6 +29969,9 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
29836
29969
  collectSlugsForType,
29837
29970
  compareVersions,
29838
29971
  computeBodyChecksum,
29972
+ concernEvaluatedFor,
29973
+ concernFor,
29974
+ concernGatesFor,
29839
29975
  describeTreePattern,
29840
29976
  edgeCarriesProperties,
29841
29977
  evaluateAntiPatterns,
@@ -29910,6 +30046,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
29910
30046
  isRegisteredPolymorphicEdge,
29911
30047
  isRuntimeStateShapedProperty,
29912
30048
  isSubSequenceStep,
30049
+ isThinCoverageAdvisory,
29913
30050
  isUPGDocument,
29914
30051
  listPropertiesByModifier,
29915
30052
  listStatusMigrations,
@@ -29935,6 +30072,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
29935
30072
  validateProductStageStrict,
29936
30073
  validateUPGDocument,
29937
30074
  validateUPGFramework,
30075
+ validationProfileFor,
29938
30076
  walkMigrationChainToCanonical
29939
30077
  });
29940
30078
  //# sourceMappingURL=index.cjs.map