@unified-product-graph/core 0.17.2 → 0.17.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/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  The TypeScript core for the **Unified Product Graph (UPG)**, an open specification that gives product tools a shared vocabulary for entities, edges, and frameworks.
9
9
 
10
- 318 entity types across 37 domains. 1017 typed edges. 46 canonical framework definitions, with more added as each is reviewed.
10
+ 319 entity types across 37 domains. 1024 typed edges. 46 canonical framework definitions, with more added as each is reviewed.
11
11
 
12
12
  ## Install
13
13
 
package/dist/index.cjs CHANGED
@@ -39,6 +39,7 @@ __export(index_exports, {
39
39
  COVERAGE_ANTI_PATTERNS: () => COVERAGE_ANTI_PATTERNS,
40
40
  DEFAULT_ENTITY_EMOJI: () => DEFAULT_ENTITY_EMOJI,
41
41
  DEFERRED_PROPOSED_BY_CONTRACT: () => DEFERRED_PROPOSED_BY_CONTRACT,
42
+ DEFER_EDGE_PROPERTY_SCHEMA: () => DEFER_EDGE_PROPERTY_SCHEMA,
42
43
  DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK: () => DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK,
43
44
  ENGINEERING_PLATFORM_PLAYBOOK: () => ENGINEERING_PLATFORM_PLAYBOOK,
44
45
  ENTITY_EMOJI: () => ENTITY_EMOJI,
@@ -68,6 +69,9 @@ __export(index_exports, {
68
69
  UPG_CONTAINMENT_FREE_TYPES: () => UPG_CONTAINMENT_FREE_TYPES,
69
70
  UPG_COUNT_BENCHMARKS: () => UPG_COUNT_BENCHMARKS,
70
71
  UPG_CROSS_EDGE_TYPES: () => UPG_CROSS_EDGE_TYPES,
72
+ UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES: () => UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES,
73
+ UPG_CROSS_ONLY_EDGE_TYPES: () => UPG_CROSS_ONLY_EDGE_TYPES,
74
+ UPG_DELIBERATE_ONLY_EDGE_TYPES: () => UPG_DELIBERATE_ONLY_EDGE_TYPES,
71
75
  UPG_DEPRECATED_TYPES: () => UPG_DEPRECATED_TYPES,
72
76
  UPG_DOMAINS: () => UPG_DOMAINS,
73
77
  UPG_DOMAIN_ACTIVATION: () => UPG_DOMAIN_ACTIVATION,
@@ -198,6 +202,8 @@ __export(index_exports, {
198
202
  isCanonical: () => isCanonical,
199
203
  isCanonicalProductStage: () => isCanonicalProductStage,
200
204
  isContainmentFreeType: () => isContainmentFreeType,
205
+ isCrossProductEligible: () => isCrossProductEligible,
206
+ isDeliberateOnlyEdge: () => isDeliberateOnlyEdge,
201
207
  isDeprecatedType: () => isDeprecatedType,
202
208
  isDomainGuideStep: () => isDomainGuideStep,
203
209
  isEntitySequenceStep: () => isEntitySequenceStep,
@@ -264,7 +270,8 @@ var UPG_DOMAINS = [
264
270
  "strategic_pillar",
265
271
  "assumption",
266
272
  "decision",
267
- "constraint"
273
+ "constraint",
274
+ "strategic_question"
268
275
  ]
269
276
  },
270
277
  {
@@ -783,6 +790,10 @@ var UPG_ENTITY_META = [
783
790
  { name: "assumption", type_id: "ent_014", maturity: "stable", since: "0.1.0" },
784
791
  { name: "decision", type_id: "ent_015", maturity: "stable", since: "0.1.0" },
785
792
  { name: "constraint", type_id: "ent_348", maturity: "stable", since: "0.4.3" },
793
+ // (0.17.4) Strategy-domain sibling of research_question / design_question,
794
+ // completing the domain-question triad. An open coordination/ownership question
795
+ // a plan is exposed to (distinct from `assumption`, which the plan is built on).
796
+ { name: "strategic_question", type_id: "ent_357", maturity: "proposed", since: "0.17.4" },
786
797
  // ── User ──
787
798
  { name: "persona", type_id: "ent_016", maturity: "stable", since: "0.1.0" },
788
799
  { name: "job", type_id: "ent_017", maturity: "stable", since: "0.1.0" },
@@ -1257,6 +1268,12 @@ var CLASSIFICATION_EDGE_PROPERTY_SCHEMA = {
1257
1268
  description: "Optional. A source URL, or a competitor_signal / evidence node id backing the classification. Mirrors feature_rivals_competitor_feature.evidence (free text or a node id)."
1258
1269
  }
1259
1270
  };
1271
+ var DEFER_EDGE_PROPERTY_SCHEMA = {
1272
+ deferred_to: {
1273
+ type: "string",
1274
+ description: 'Target period the parked work is deferred to. Freeform, mirroring strategic_theme.time_horizon. @example "Q4 2026", "FY27", "next release".'
1275
+ }
1276
+ };
1260
1277
  var UPG_EDGE_CATALOG = {
1261
1278
  // ── Part 1: Core Narrative Spine (Ring 1) ──────────────────────────────────
1262
1279
  // 1.1 User Domain
@@ -1273,7 +1290,7 @@ var UPG_EDGE_CATALOG = {
1273
1290
  persona_aspires_to_desired_outcome: { forward_verb: "aspires_to", reverse_verb: "aspirational_for", classification: "hierarchy", source_type: "persona", target_type: "desired_outcome" },
1274
1291
  // Delegation (0.11.6): a persona delegates work to another. The common case is human -> agent
1275
1292
  // (Content Ops Lead -> Content Agent), but it also expresses human -> human (editor -> reviewer).
1276
- persona_delegates_to_persona: { forward_verb: "delegates_to", reverse_verb: "delegated_by", classification: "semantic", source_type: "persona", target_type: "persona" },
1293
+ persona_delegates_to_persona: { forward_verb: "delegates_to", reverse_verb: "delegated_by", classification: "semantic", source_type: "persona", target_type: "persona", cross_product_eligible: true },
1277
1294
  persona_incurs_switching_cost: { forward_verb: "incurs", reverse_verb: "incurred_by", classification: "hierarchy", source_type: "persona", target_type: "switching_cost" },
1278
1295
  job_surfaces_need: { forward_verb: "surfaces", reverse_verb: "surfaces_from", classification: "causal", source_type: "job", target_type: "need" },
1279
1296
  job_motivates_desired_outcome: { forward_verb: "motivates", reverse_verb: "motivated_by", classification: "causal", source_type: "job", target_type: "desired_outcome" },
@@ -1391,15 +1408,15 @@ var UPG_EDGE_CATALOG = {
1391
1408
  // Dual-registered as a cross-edge (UPG_CROSS_EDGE_TYPES) so it also spans our
1392
1409
  // product graph and a watched competitor-intelligence graph. Distinct from
1393
1410
  // `competitor_feature_inspires_feature` (ideation lineage, not parity).
1394
- feature_rivals_competitor_feature: { forward_verb: "rivals", reverse_verb: "is_rivalled_by", classification: "cross-domain", source_type: "feature", target_type: "competitor_feature", carries_properties: true },
1411
+ feature_rivals_competitor_feature: { forward_verb: "rivals", reverse_verb: "is_rivalled_by", classification: "cross-domain", source_type: "feature", target_type: "competitor_feature", carries_properties: true, cross_product_eligible: true },
1395
1412
  // 0.10.0 (spec issue #41): competitor_signal is a dated competitor move (feature
1396
1413
  // launch / pricing change / acquisition / partnership / market entry) emitted by a
1397
1414
  // competitor and mapped onto our portfolio. `emits` is within the watched graph;
1398
1415
  // `maps_to_feature` / `surfaces_opportunity` cross from the watched signal into our
1399
1416
  // product graph (dual-registered as cross-edges in UPG_CROSS_EDGE_TYPES).
1400
1417
  competitor_emits_competitor_signal: { forward_verb: "emits", reverse_verb: "emitted_by", classification: "hierarchy", source_type: "competitor", target_type: "competitor_signal" },
1401
- competitor_signal_maps_to_feature: { forward_verb: "maps_to", reverse_verb: "targeted_by_signal", classification: "cross-domain", source_type: "competitor_signal", target_type: "feature" },
1402
- competitor_signal_surfaces_opportunity: { forward_verb: "surfaces", reverse_verb: "prompted_by_signal", classification: "cross-domain", source_type: "competitor_signal", target_type: "opportunity" },
1418
+ competitor_signal_maps_to_feature: { forward_verb: "maps_to", reverse_verb: "targeted_by_signal", classification: "cross-domain", source_type: "competitor_signal", target_type: "feature", cross_product_eligible: true },
1419
+ competitor_signal_surfaces_opportunity: { forward_verb: "surfaces", reverse_verb: "prompted_by_signal", classification: "cross-domain", source_type: "competitor_signal", target_type: "opportunity", cross_product_eligible: true },
1403
1420
  competitive_analysis_analyses_competitor: { forward_verb: "analyses", reverse_verb: "analysed_in", classification: "hierarchy", source_type: "competitive_analysis", target_type: "competitor" },
1404
1421
  competitive_analysis_identifies_market_trend: { forward_verb: "identifies", reverse_verb: "identified_in", classification: "hierarchy", source_type: "competitive_analysis", target_type: "market_trend" },
1405
1422
  competitive_analysis_scopes_market_segment: { forward_verb: "scopes", reverse_verb: "scoped_in", classification: "hierarchy", source_type: "competitive_analysis", target_type: "market_segment" },
@@ -1432,13 +1449,13 @@ var UPG_EDGE_CATALOG = {
1432
1449
  // competitor can be classified directly against a `registry/{classification_value}`
1433
1450
  // canonical, eliminating the per-graph taxonomy node. Within-graph (the catalogue
1434
1451
  // case) here; cross-product against the registry canonical via create_cross_product_edge.
1435
- competitor_classified_as_classification_value: { forward_verb: "classified_as", reverse_verb: "classification_of", classification: "semantic", source_type: "competitor", target_type: "classification_value", carries_properties: true, property_schema: CLASSIFICATION_EDGE_PROPERTY_SCHEMA },
1452
+ competitor_classified_as_classification_value: { forward_verb: "classified_as", reverse_verb: "classification_of", classification: "semantic", source_type: "competitor", target_type: "classification_value", carries_properties: true, property_schema: CLASSIFICATION_EDGE_PROPERTY_SCHEMA, cross_product_eligible: true },
1436
1453
  // 0.10.3: the polymorphic, type-agnostic sibling. ANY node (a feature, a
1437
1454
  // product, a market_segment) classified against a classification_value, so
1438
1455
  // classification is not welded to the competitor type. Also dual-registered as
1439
1456
  // a cross-edge for the registry-canonical case. source_type:'node' (wildcard);
1440
1457
  // listed in UPG_POLYMORPHIC_EDGE_KEYS.
1441
- node_classified_as_classification_value: { forward_verb: "classified_as", reverse_verb: "classification_of", classification: "semantic", source_type: "node", target_type: "classification_value", carries_properties: true, property_schema: CLASSIFICATION_EDGE_PROPERTY_SCHEMA },
1458
+ node_classified_as_classification_value: { forward_verb: "classified_as", reverse_verb: "classification_of", classification: "semantic", source_type: "node", target_type: "classification_value", carries_properties: true, property_schema: CLASSIFICATION_EDGE_PROPERTY_SCHEMA, cross_product_eligible: true },
1442
1459
  persona_anti_fit_for_classification_value: { forward_verb: "is_anti_fit_for", reverse_verb: "should_not_be_picked_by", classification: "semantic", source_type: "persona", target_type: "classification_value" },
1443
1460
  persona_anti_fit_for_product: { forward_verb: "is_anti_fit_for", reverse_verb: "should_not_be_picked_by", classification: "semantic", source_type: "persona", target_type: "product" },
1444
1461
  persona_anti_fit_for_competitor: { forward_verb: "is_anti_fit_for", reverse_verb: "should_not_be_picked_by", classification: "semantic", source_type: "persona", target_type: "competitor" },
@@ -1491,28 +1508,28 @@ var UPG_EDGE_CATALOG = {
1491
1508
  feedback_program_has_beta_program: { forward_verb: "has", reverse_verb: "part_of", classification: "hierarchy", source_type: "feedback_program", target_type: "beta_program" },
1492
1509
  // ── Part 2: Strategic & Execution Spine (Ring 2) ───────────────────────────
1493
1510
  // 2.1 Strategic Domain
1494
- product_pursues_outcome: { forward_verb: "pursues", reverse_verb: "pursued_by", classification: "hierarchy", source_type: "product", target_type: "outcome" },
1495
- product_targets_objective: { forward_verb: "targets", reverse_verb: "targeted_by", classification: "hierarchy", source_type: "product", target_type: "objective" },
1496
- product_guided_by_vision: { forward_verb: "guided_by", reverse_verb: "guides", classification: "hierarchy", source_type: "product", target_type: "vision" },
1511
+ product_pursues_outcome: { forward_verb: "pursues", reverse_verb: "pursued_by", classification: "hierarchy", source_type: "product", target_type: "outcome", cross_product_eligible: true },
1512
+ product_targets_objective: { forward_verb: "targets", reverse_verb: "targeted_by", classification: "hierarchy", source_type: "product", target_type: "objective", cross_product_eligible: true },
1513
+ product_guided_by_vision: { forward_verb: "guided_by", reverse_verb: "guides", classification: "hierarchy", source_type: "product", target_type: "vision", cross_product_eligible: true },
1497
1514
  // product→{mission,strategic_theme,strategic_pillar,initiative,capability,value_stream,assumption}
1498
1515
  // are semantic "how the product relates to the strategic cascade", not containment.
1499
1516
  // The containment chain is product → vision → mission → strategic_pillar → … so these
1500
1517
  // targets are reachable via the vision/mission hierarchy already.
1501
- product_fulfils_mission: { forward_verb: "fulfils", reverse_verb: "fulfilled_by", classification: "semantic", source_type: "product", target_type: "mission" },
1502
- product_organises_around_strategic_theme: { forward_verb: "organises_around", reverse_verb: "organises", classification: "semantic", source_type: "product", target_type: "strategic_theme" },
1503
- product_stands_on_strategic_pillar: { forward_verb: "stands_on", reverse_verb: "supports", classification: "semantic", source_type: "product", target_type: "strategic_pillar" },
1504
- product_invests_in_initiative: { forward_verb: "invests_in", reverse_verb: "investment_of", classification: "semantic", source_type: "product", target_type: "initiative" },
1518
+ product_fulfils_mission: { forward_verb: "fulfils", reverse_verb: "fulfilled_by", classification: "semantic", source_type: "product", target_type: "mission", cross_product_eligible: true },
1519
+ product_organises_around_strategic_theme: { forward_verb: "organises_around", reverse_verb: "organises", classification: "semantic", source_type: "product", target_type: "strategic_theme", cross_product_eligible: true },
1520
+ product_stands_on_strategic_pillar: { forward_verb: "stands_on", reverse_verb: "supports", classification: "semantic", source_type: "product", target_type: "strategic_pillar", cross_product_eligible: true },
1521
+ product_invests_in_initiative: { forward_verb: "invests_in", reverse_verb: "investment_of", classification: "semantic", source_type: "product", target_type: "initiative", cross_product_eligible: true },
1505
1522
  product_develops_capability: { forward_verb: "develops", reverse_verb: "developed_by", classification: "semantic", source_type: "product", target_type: "capability" },
1506
1523
  product_delivers_through_value_stream: { forward_verb: "delivers_through", reverse_verb: "delivers_for", classification: "semantic", source_type: "product", target_type: "value_stream" },
1507
1524
  product_holds_assumption: { forward_verb: "holds", reverse_verb: "held_by", classification: "semantic", source_type: "product", target_type: "assumption" },
1508
- product_measures_with_metric: { forward_verb: "measures_with", reverse_verb: "measures", classification: "hierarchy", source_type: "product", target_type: "metric" },
1509
- outcome_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "hierarchy", source_type: "outcome", target_type: "metric" },
1525
+ product_measures_with_metric: { forward_verb: "measures_with", reverse_verb: "measures", classification: "hierarchy", source_type: "product", target_type: "metric", cross_product_eligible: true },
1526
+ outcome_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "hierarchy", source_type: "outcome", target_type: "metric", cross_product_eligible: true },
1510
1527
  // (UPG-677) outcome_tracked_by_metric retired — near-synonym of
1511
1528
  // outcome_measured_by_metric (the kept canonical key). Captain's lean =
1512
1529
  // collapse. See UPG_EDGE_MIGRATIONS['0.9.9'].
1513
- objective_achieved_through_key_result: { forward_verb: "achieved_through", reverse_verb: "achieves", classification: "hierarchy", source_type: "objective", target_type: "key_result" },
1514
- objective_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "hierarchy", source_type: "objective", target_type: "metric" },
1515
- key_result_quantified_by_metric: { forward_verb: "quantified_by", reverse_verb: "quantifies", classification: "hierarchy", source_type: "key_result", target_type: "metric" },
1530
+ objective_achieved_through_key_result: { forward_verb: "achieved_through", reverse_verb: "achieves", classification: "hierarchy", source_type: "objective", target_type: "key_result", cross_product_eligible: true },
1531
+ objective_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "hierarchy", source_type: "objective", target_type: "metric", cross_product_eligible: true },
1532
+ key_result_quantified_by_metric: { forward_verb: "quantified_by", reverse_verb: "quantifies", classification: "hierarchy", source_type: "key_result", target_type: "metric", cross_product_eligible: true },
1516
1533
  // (UPG-677) key_result_tracked_by_metric retired — near-synonym of
1517
1534
  // key_result_quantified_by_metric (the kept canonical key). Captain's lean =
1518
1535
  // collapse. See UPG_EDGE_MIGRATIONS['0.9.9'].
@@ -1522,7 +1539,7 @@ var UPG_EDGE_CATALOG = {
1522
1539
  strategic_pillar_enables_capability: { forward_verb: "enables", reverse_verb: "enabled_by", classification: "hierarchy", source_type: "strategic_pillar", target_type: "capability" },
1523
1540
  strategic_pillar_delivers_value_stream: { forward_verb: "delivers", reverse_verb: "delivered_by", classification: "hierarchy", source_type: "strategic_pillar", target_type: "value_stream" },
1524
1541
  strategic_pillar_decided_via_decision: { forward_verb: "decided_via", reverse_verb: "decided_for", classification: "hierarchy", source_type: "strategic_pillar", target_type: "decision" },
1525
- strategic_theme_pursues_initiative: { forward_verb: "pursues", reverse_verb: "pursued_under", classification: "hierarchy", source_type: "strategic_theme", target_type: "initiative" },
1542
+ strategic_theme_pursues_initiative: { forward_verb: "pursues", reverse_verb: "pursued_under", classification: "hierarchy", source_type: "strategic_theme", target_type: "initiative", cross_product_eligible: true },
1526
1543
  // v0.9.0 (UPG-660): the soft bridge from the annual strategy focus area to the
1527
1544
  // roadmap grouping that realises it. Semantic, NOT hierarchy: strategic_theme and
1528
1545
  // roadmap_theme sit on different spines (strategy cascade vs roadmap cascade), so
@@ -1550,11 +1567,11 @@ var UPG_EDGE_CATALOG = {
1550
1567
  // surfaces the upward-rollup read. Mirrors `strategic_pillar_organises_
1551
1568
  // strategic_theme` (pillar → theme), completing the strategic cascade:
1552
1569
  // strategic_pillar → strategic_theme → objective → key_result.
1553
- strategic_theme_delivers_outcome: { forward_verb: "delivers", reverse_verb: "delivered_by", classification: "causal", source_type: "strategic_theme", target_type: "outcome" },
1554
- strategic_theme_measured_by_key_result: { forward_verb: "measured_by", reverse_verb: "measures", classification: "causal", source_type: "strategic_theme", target_type: "key_result" },
1555
- strategic_theme_contains_objective: { forward_verb: "contains", reverse_verb: "rolls_up_to", classification: "hierarchy", source_type: "strategic_theme", target_type: "objective" },
1570
+ strategic_theme_delivers_outcome: { forward_verb: "delivers", reverse_verb: "delivered_by", classification: "causal", source_type: "strategic_theme", target_type: "outcome", cross_product_eligible: true },
1571
+ strategic_theme_measured_by_key_result: { forward_verb: "measured_by", reverse_verb: "measures", classification: "causal", source_type: "strategic_theme", target_type: "key_result", cross_product_eligible: true },
1572
+ strategic_theme_contains_objective: { forward_verb: "contains", reverse_verb: "rolls_up_to", classification: "hierarchy", source_type: "strategic_theme", target_type: "objective", cross_product_eligible: true },
1556
1573
  initiative_assumes_assumption: { forward_verb: "assumes", reverse_verb: "assumed_by", classification: "hierarchy", source_type: "initiative", target_type: "assumption" },
1557
- initiative_drives_outcome: { forward_verb: "drives", reverse_verb: "driven_by", classification: "cross-domain", source_type: "initiative", target_type: "outcome" },
1574
+ initiative_drives_outcome: { forward_verb: "drives", reverse_verb: "driven_by", classification: "cross-domain", source_type: "initiative", target_type: "outcome", cross_product_eligible: true },
1558
1575
  capability_enables_value_stream: { forward_verb: "enables", reverse_verb: "enabled_by", classification: "cross-domain", source_type: "capability", target_type: "value_stream" },
1559
1576
  // v0.5.2 (UPG-528): three capability-anchored edges that complete the
1560
1577
  // Wardley-style value chain: need → capability → capability → feature.
@@ -1692,7 +1709,7 @@ var UPG_EDGE_CATALOG = {
1692
1709
  // brand_identity. Dual-registered: also a cross-edge for the common case where the
1693
1710
  // brand is a registry singleton in another graph (the ratified pattern: brand is a
1694
1711
  // singleton expressed, not instance_of-d); this catalog entry is the within-graph case.
1695
- product_expresses_brand_identity: { forward_verb: "expresses", reverse_verb: "expressed_by", classification: "semantic", source_type: "product", target_type: "brand_identity" },
1712
+ product_expresses_brand_identity: { forward_verb: "expresses", reverse_verb: "expressed_by", classification: "semantic", source_type: "product", target_type: "brand_identity", cross_product_eligible: true },
1696
1713
  design_system_encompasses_user_journey: { forward_verb: "encompasses", reverse_verb: "encompassed_in", classification: "hierarchy", source_type: "design_system", target_type: "user_journey" },
1697
1714
  design_system_encompasses_user_flow: { forward_verb: "encompasses", reverse_verb: "encompassed_in", classification: "hierarchy", source_type: "design_system", target_type: "user_flow" },
1698
1715
  design_system_informed_by_insight: { forward_verb: "informed_by", reverse_verb: "informs", classification: "hierarchy", source_type: "design_system", target_type: "insight" },
@@ -1704,12 +1721,12 @@ var UPG_EDGE_CATALOG = {
1704
1721
  design_component_specified_by_interaction_spec: { forward_verb: "specified_by", reverse_verb: "specifies", classification: "hierarchy", source_type: "design_component", target_type: "interaction_spec" },
1705
1722
  design_component_composes_design_component: { forward_verb: "composes", reverse_verb: "composed_in", classification: "hierarchy", source_type: "design_component", target_type: "design_component" },
1706
1723
  prototype_annotated_with_annotation: { forward_verb: "annotated_with", reverse_verb: "annotates", classification: "hierarchy", source_type: "prototype", target_type: "annotation" },
1707
- screen_renders_design_component: { forward_verb: "renders", reverse_verb: "rendered_on", classification: "hierarchy", source_type: "screen", target_type: "design_component" },
1724
+ screen_renders_design_component: { forward_verb: "renders", reverse_verb: "rendered_on", classification: "hierarchy", source_type: "screen", target_type: "design_component", cross_product_eligible: true },
1708
1725
  // Marketing surface to product (0.12.7, UPG-696/698). A marketing/landing screen
1709
1726
  // markets a product. Dual-registered: also a cross-edge (UPG_CROSS_EDGE_TYPES) for
1710
1727
  // the common case where the product lives in another graph; this catalog entry is
1711
1728
  // the within-graph degenerate case (a product's own landing page).
1712
- screen_markets_product: { forward_verb: "markets", reverse_verb: "marketed_by", classification: "semantic", source_type: "screen", target_type: "product" },
1729
+ screen_markets_product: { forward_verb: "markets", reverse_verb: "marketed_by", classification: "semantic", source_type: "screen", target_type: "product", cross_product_eligible: true },
1713
1730
  // Connective cross-product references (0.13.1, Data's connective-layer brief).
1714
1731
  // Dual-registered (also in UPG_CROSS_EDGE_TYPES) for the common cross-graph case;
1715
1732
  // these catalog entries are the within-graph degenerate case.
@@ -1725,10 +1742,10 @@ var UPG_EDGE_CATALOG = {
1725
1742
  // system (the adoption semantic, mirroring product_implements_specification). Distinct
1726
1743
  // from the hierarchy `product_systematised_in_design_system` (structural containment):
1727
1744
  // same pattern as brand (branded_as = hierarchy, expresses = semantic).
1728
- screen_targets_competitor: { forward_verb: "targets", reverse_verb: "targeted_by", classification: "semantic", source_type: "screen", target_type: "competitor" },
1729
- feature_surfaces_product: { forward_verb: "surfaces", reverse_verb: "surfaced_by", classification: "semantic", source_type: "feature", target_type: "product" },
1730
- feature_uses_design_component: { forward_verb: "uses", reverse_verb: "used_by", classification: "semantic", source_type: "feature", target_type: "design_component" },
1731
- product_implements_design_system: { forward_verb: "implements", reverse_verb: "implemented_by", classification: "semantic", source_type: "product", target_type: "design_system" },
1745
+ screen_targets_competitor: { forward_verb: "targets", reverse_verb: "targeted_by", classification: "semantic", source_type: "screen", target_type: "competitor", cross_product_eligible: true },
1746
+ feature_surfaces_product: { forward_verb: "surfaces", reverse_verb: "surfaced_by", classification: "semantic", source_type: "feature", target_type: "product", cross_product_eligible: true },
1747
+ feature_uses_design_component: { forward_verb: "uses", reverse_verb: "used_by", classification: "semantic", source_type: "feature", target_type: "design_component", cross_product_eligible: true },
1748
+ product_implements_design_system: { forward_verb: "implements", reverse_verb: "implemented_by", classification: "semantic", source_type: "product", target_type: "design_system", cross_product_eligible: true },
1732
1749
  screen_navigates_to_screen: { forward_verb: "navigates_to", reverse_verb: "navigated_from", classification: "hierarchy", source_type: "screen", target_type: "screen" },
1733
1750
  screen_surfaces_feature: { forward_verb: "surfaces", reverse_verb: "surfaced_on", classification: "cross-domain", source_type: "screen", target_type: "feature" },
1734
1751
  screen_wireframed_as_wireframe: { forward_verb: "wireframed_as", reverse_verb: "wireframes", classification: "hierarchy", source_type: "screen", target_type: "wireframe" },
@@ -2580,10 +2597,10 @@ var UPG_EDGE_CATALOG = {
2580
2597
  experiment_run_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "hierarchy", source_type: "experiment_run", target_type: "metric" },
2581
2598
  solution_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "hierarchy", source_type: "solution", target_type: "metric" },
2582
2599
  // ── Cross-domain: Ownership ──────────────────────────────────────────────────
2583
- node_owned_by_team: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "team" },
2600
+ node_owned_by_team: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "team", cross_product_eligible: true },
2584
2601
  node_owned_by_role: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "role" },
2585
2602
  node_owned_by_stakeholder: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "stakeholder" },
2586
- node_owned_by_department: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "department" },
2603
+ node_owned_by_department: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "department", cross_product_eligible: true },
2587
2604
  node_owned_by_person: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "person" },
2588
2605
  // ── Cross-domain: Architecture (DDD) ─────────────────────────────────────────
2589
2606
  // Service, domain_event, domain_entity, aggregate, read_model, api_contract,
@@ -3247,7 +3264,7 @@ var UPG_EDGE_CATALOG = {
3247
3264
  // not the outcome it exists to move; the strategic spine was severed at its
3248
3265
  // anchor (0 outbound to outcome). An objective ADVANCES an outcome. Intra-
3249
3266
  // domain (both in strategy) and directional → causal.
3250
- objective_advances_outcome: { forward_verb: "advances", reverse_verb: "advanced_by", classification: "causal", source_type: "objective", target_type: "outcome" },
3267
+ objective_advances_outcome: { forward_verb: "advances", reverse_verb: "advanced_by", classification: "causal", source_type: "objective", target_type: "outcome", cross_product_eligible: true },
3251
3268
  // ── F6: Priority 2 — scored / synthesis / verdict dead-end leaves (P-A) ─────
3252
3269
  // desired_outcome (Ulwick-scored: importance × satisfaction) had 0 outbound —
3253
3270
  // the scores could not flow anywhere. An under-served desired_outcome REVEALS
@@ -3330,9 +3347,61 @@ var UPG_EDGE_CATALOG = {
3330
3347
  specification_governed_by_organization: { forward_verb: "governed_by", reverse_verb: "governs", classification: "semantic", source_type: "specification", target_type: "organization" },
3331
3348
  // Operating-lifecycle cross-edges (0.11.6): a product's journey phase realises a canonical
3332
3349
  // operating stage (the cross-surface join key); a stage is measured by a rollup metric (loop close).
3333
- journey_phase_realises_operating_stage: { forward_verb: "realises", reverse_verb: "realised_by", classification: "cross-domain", source_type: "journey_phase", target_type: "operating_stage" },
3334
- operating_stage_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "cross-domain", source_type: "operating_stage", target_type: "metric" }
3350
+ journey_phase_realises_operating_stage: { forward_verb: "realises", reverse_verb: "realised_by", classification: "cross-domain", source_type: "journey_phase", target_type: "operating_stage", cross_product_eligible: true },
3351
+ operating_stage_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "cross-domain", source_type: "operating_stage", target_type: "metric" },
3352
+ // ── OKR planning coverage (0.17.4) ──────────────────────────────────────────
3353
+ // Reconciling the strategy graph against a live planning doc surfaced texture
3354
+ // the objective — the node every OKR doc organises itself around — could not
3355
+ // reach: cross-team dependencies and deferred (out-of-scope) work.
3356
+ // objective ↔ dependency. Every OKR in the source doc carries a dependency
3357
+ // table ("which other team's work this depends on"). `dependency` (team_org)
3358
+ // already carries dependency_type / criticality / target_date; it was
3359
+ // reachable only from `team`. An objective DEPENDS ON a dependency; the
3360
+ // dependency BLOCKS the objective (explicit mirror, not left implicit).
3361
+ // Cross-domain, not hierarchy: a dependency is parented under its owning team,
3362
+ // so an objective references it laterally rather than containing it. Both are
3363
+ // cross_product_eligible — a Studio objective can depend on a dependency owned
3364
+ // by another team's graph within the portfolio (0.17.3 locked predicate).
3365
+ objective_depends_on_dependency: { forward_verb: "depends_on", reverse_verb: "dependency_of", classification: "cross-domain", source_type: "objective", target_type: "dependency", cross_product_eligible: true },
3366
+ dependency_blocks_objective: { forward_verb: "blocks", reverse_verb: "blocked_by", classification: "cross-domain", source_type: "dependency", target_type: "objective", cross_product_eligible: true },
3367
+ // objective / initiative → strategic_question. A planning doc's "Risks & Open
3368
+ // Questions" section names unresolved coordination questions the plan is
3369
+ // exposed to (who owns a capability across teams after a reorg). The
3370
+ // strategy-domain sibling of research_question / design_question. The question
3371
+ // is raised under (contained by) the objective or initiative that surfaces it,
3372
+ // so hierarchy — mirroring initiative_assumes_assumption. Within-graph: the
3373
+ // question node is authored alongside its objective, so NOT
3374
+ // cross_product_eligible (the cross-team nature lives in the question text, not
3375
+ // in a cross-graph edge).
3376
+ objective_raises_strategic_question: { forward_verb: "raises", reverse_verb: "raised_by", classification: "hierarchy", source_type: "objective", target_type: "strategic_question" },
3377
+ initiative_raises_strategic_question: { forward_verb: "raises", reverse_verb: "raised_by", classification: "hierarchy", source_type: "initiative", target_type: "strategic_question" },
3378
+ // objective → feature / capability (the defer / out-of-scope edge). Every OKR
3379
+ // in the source doc carries an explicit "Out of scope" list, load-bearing for
3380
+ // keeping a quarter from silently expanding (localization deferred to Q4,
3381
+ // another team's feature work parked). Modelled as an edge to the real feature
3382
+ // or capability parked for later, not a scalar exclusion string, so the parked
3383
+ // work stays queryable and connected. The `deferred_to` edge property carries
3384
+ // the temporal target. feature is product_spec (cross-domain); capability is
3385
+ // intra-strategy (semantic). Both cross_product_eligible: deferring another
3386
+ // product's feature or capability, authored in a different graph within the
3387
+ // portfolio, fits the 0.17.3 locked predicate.
3388
+ objective_defers_feature: { forward_verb: "defers", reverse_verb: "deferred_by", classification: "cross-domain", source_type: "objective", target_type: "feature", carries_properties: true, property_schema: DEFER_EDGE_PROPERTY_SCHEMA, cross_product_eligible: true, deliberate_only: true },
3389
+ objective_defers_capability: { forward_verb: "defers", reverse_verb: "deferred_by", classification: "semantic", source_type: "objective", target_type: "capability", carries_properties: true, property_schema: DEFER_EDGE_PROPERTY_SCHEMA, cross_product_eligible: true, deliberate_only: true }
3335
3390
  };
3391
+ var UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES = Object.keys(UPG_EDGE_CATALOG).filter(
3392
+ (k) => UPG_EDGE_CATALOG[k].cross_product_eligible === true
3393
+ );
3394
+ function isCrossProductEligible(type) {
3395
+ const def = UPG_EDGE_CATALOG[type];
3396
+ return def?.cross_product_eligible === true;
3397
+ }
3398
+ var UPG_DELIBERATE_ONLY_EDGE_TYPES = Object.keys(UPG_EDGE_CATALOG).filter(
3399
+ (k) => UPG_EDGE_CATALOG[k].deliberate_only === true
3400
+ );
3401
+ function isDeliberateOnlyEdge(type) {
3402
+ const def = UPG_EDGE_CATALOG[type];
3403
+ return def?.deliberate_only === true;
3404
+ }
3336
3405
  var UPG_POLYMORPHIC_EDGE_KEYS = [
3337
3406
  // Universal semantic verbs
3338
3407
  "node_informs_node",
@@ -3392,52 +3461,47 @@ function isLegacyProductStage(stage) {
3392
3461
  }
3393
3462
 
3394
3463
  // src/shapes/document.ts
3395
- var UPG_CROSS_EDGE_TYPES = [
3464
+ var UPG_CROSS_ONLY_EDGE_TYPES = [
3465
+ // Peer overlap: "these two products share / overlap on this thing." Symmetric,
3466
+ // no canonical instance_of identity. shares_job / shares_need are the job/need
3467
+ // siblings of the persona/competitor/metric peers (connective layer, 0.13.1).
3396
3468
  "shares_persona",
3397
3469
  "shares_competitor",
3398
3470
  "shares_metric",
3471
+ "shares_job",
3472
+ "shares_need",
3473
+ // Product-to-product relationships.
3399
3474
  "depends_on_product",
3475
+ // runtime dependency (built-on / dogfood), not containment
3400
3476
  "cannibalises",
3401
3477
  "succeeds",
3402
3478
  "hosts",
3479
+ // host runs the hosted product inside itself (container -> contained)
3480
+ // OKR / measurement rollup primitives: the cascade ACROSS products (subordinate
3481
+ // -> superior). `contributes_to` rolls a product strategy entity up to a higher-
3482
+ // level one; `rolls_up_to` feeds a product metric into a higher-level north-star.
3403
3483
  "contributes_to",
3484
+ "rolls_up_to",
3485
+ // Canonical instance + area-to-audience: the target lives in the portfolio
3486
+ // `registry` section (`registry/{node_id}`). `instance_of` is same-type
3487
+ // canonical-to-instance; the area edges are minted via `link_area_to_audience`.
3404
3488
  "instance_of",
3405
3489
  "area_serves_persona",
3406
3490
  "area_targets_market_segment",
3407
- "rolls_up_to",
3491
+ // Foundations (0.9.12): a product-graph entity links to a canonical specification
3492
+ // or primitive in the registry (`registry/{node_id}` target, same shape as
3493
+ // instance_of). Registry-internal spec-to-spec links are catalog edges, not these.
3408
3494
  "product_implements_specification",
3409
3495
  "product_exposes_specification",
3410
3496
  "feature_conforms_to_specification",
3411
3497
  "api_contract_speaks_specification",
3412
3498
  "product_exposes_primitive",
3413
3499
  "feature_manipulates_primitive",
3414
- "primitive_stored_as_data_type",
3415
- "feature_rivals_competitor_feature",
3416
- "competitor_signal_maps_to_feature",
3417
- "competitor_signal_surfaces_opportunity",
3418
- "competitor_classified_as_classification_value",
3419
- "node_classified_as_classification_value",
3420
- "journey_phase_realises_operating_stage",
3421
- "screen_markets_product",
3422
- "screen_renders_design_component",
3423
- "product_expresses_brand_identity",
3424
- // Connective cross-product layer (0.13.1) — see UPGCrossEdgeType above.
3425
- "shares_job",
3426
- "shares_need",
3427
- "persona_delegates_to_persona",
3428
- "screen_targets_competitor",
3429
- "feature_surfaces_product",
3430
- "feature_uses_design_component",
3431
- "product_implements_design_system",
3432
- // Org-link (0.17.0): dual-registered ownership edges (see UPGCrossEdgeType above).
3433
- "node_owned_by_team",
3434
- "node_owned_by_department",
3435
- // Cross-graph strategy & measurement (0.17.2): dual-registered OKR/measurement
3436
- // hierarchy edges so the strategy spine can span files (see UPGCrossEdgeType above).
3437
- "strategic_theme_contains_objective",
3438
- "objective_achieved_through_key_result",
3439
- "key_result_quantified_by_metric",
3440
- "objective_measured_by_metric"
3500
+ "primitive_stored_as_data_type"
3501
+ ];
3502
+ var UPG_CROSS_EDGE_TYPES = [
3503
+ ...UPG_CROSS_ONLY_EDGE_TYPES,
3504
+ ...UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES
3441
3505
  ];
3442
3506
  var REGISTRY_PRODUCT_ID = "registry";
3443
3507
  var UPG_PORTFOLIO_KINDS = ["owned", "watched", "strategic", "internal", "gtm"];
@@ -3705,7 +3769,9 @@ var UPG_VALID_CHILDREN = {
3705
3769
  // where self-nesting genuinely lives, not on `experiment`).
3706
3770
  experiment_run: ["learning", "evidence", "metric", "experiment_run"],
3707
3771
  // ── OKR hierarchy ──────────────────────────────────────────────────────────
3708
- objective: ["key_result", "metric"],
3772
+ // strategic_question (0.17.4): an open coordination question raised under an
3773
+ // objective (objective_raises_strategic_question, hierarchy).
3774
+ objective: ["key_result", "metric", "strategic_question"],
3709
3775
  key_result: ["metric"],
3710
3776
  // ── Strategic cascade: vision → mission → strategic_pillar → strategic_theme →
3711
3777
  // { initiative, objective } ───────────────────────────────────────────────
@@ -3730,7 +3796,7 @@ var UPG_VALID_CHILDREN = {
3730
3796
  // catalog (hierarchy, strategic_theme → objective, reverse_verb: rolls_up_to;
3731
3797
  // renamed from objective_rolls_up_to_strategic_theme in UPG-676).
3732
3798
  strategic_theme: ["initiative", "objective"],
3733
- initiative: ["assumption"],
3799
+ initiative: ["assumption", "strategic_question"],
3734
3800
  // v0.5.2 (UPG-528): capability decomposes into sub-capabilities (Wardley
3735
3801
  // value-chain spine) and is realised by user-facing features. Pairs with
3736
3802
  // `capability_depends_on_capability` and `capability_implemented_by_feature`
@@ -4803,6 +4869,15 @@ var ASSUMPTION_LIFECYCLE = {
4803
4869
  }
4804
4870
  ]
4805
4871
  };
4872
+ var STRATEGIC_QUESTION_LIFECYCLE = {
4873
+ entity_type: "strategic_question",
4874
+ initial_phase: "open",
4875
+ terminal_phases: ["resolved"],
4876
+ phases: [
4877
+ { id: "open", label: "Open", description: "The question has been raised but not yet answered. The plan is exposed to it.", transitions_to: ["resolved"] },
4878
+ { id: "resolved", label: "Resolved", description: "The question has been answered; the resolution is captured. The plan is no longer exposed to it. May reopen if the answer unravels.", transitions_to: ["open"] }
4879
+ ]
4880
+ };
4806
4881
  var OUTCOME_LIFECYCLE = {
4807
4882
  entity_type: "outcome",
4808
4883
  initial_phase: "identified",
@@ -6480,6 +6555,7 @@ var UPG_LIFECYCLES = [
6480
6555
  INITIATIVE_LIFECYCLE,
6481
6556
  STRATEGIC_PILLAR_LIFECYCLE,
6482
6557
  ASSUMPTION_LIFECYCLE,
6558
+ STRATEGIC_QUESTION_LIFECYCLE,
6483
6559
  FEATURE_AREA_LIFECYCLE,
6484
6560
  FEATURE_LIFECYCLE,
6485
6561
  EPIC_LIFECYCLE,
@@ -12956,6 +13032,15 @@ var UPG_PROPERTY_SCHEMA = {
12956
13032
  time_horizon: { type: "string", description: 'Standing / multi-year horizon, often open-ended (a pillar is durable). @example "3 years", "2026-2028", "ongoing"' },
12957
13033
  success_indicator: { type: "string", description: "How the business knows this durable pillar is on track. Narrative, not a metric edge. A strategic_theme deliberately has no success_indicator: it is measured through its child objectives, not on its own." }
12958
13034
  },
13035
+ // StrategicQuestionProperties: StrategicQuestion entity. An open coordination or
13036
+ // ownership question a plan is exposed to (strategy sibling of research_question /
13037
+ // design_question). `status` is the node lifecycle (open -> resolved).
13038
+ strategic_question: {
13039
+ question: { type: "string", description: "The question itself. Primary content." },
13040
+ context: { type: "string", description: "Context that surfaced the question: the reorg, the boundary, the unowned area." },
13041
+ resolution: { type: "string", description: "The answer, captured when the question moves to `resolved`." },
13042
+ priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Importance to resolve relative to other open questions." }
13043
+ },
12959
13044
  // StrategicThemeProperties: StrategicTheme entity. A time-bound thrust WITHIN a
12960
13045
  // strategic_pillar (distinct cascade level, UPG-692 T3.3) — measured through its
12961
13046
  // child objectives, so it carries no success_indicator of its own.
@@ -19984,6 +20069,7 @@ var ENTITY_EMOJI = {
19984
20069
  stakeholder: "\u{1F9D1}\u200D\u{1F4BC}",
19985
20070
  status_report: "\u{1F4C4}",
19986
20071
  strategic_pillar: "\u{1F3DB}\uFE0F",
20072
+ strategic_question: "\u2754",
19987
20073
  strategic_theme: "\u{1F9F5}",
19988
20074
  subscription: "\u{1F502}",
19989
20075
  success_milestone: "\u{1F389}",
@@ -20541,6 +20627,7 @@ var STANDARD_LABELS = {
20541
20627
  value_stream: { alt_labels: ["value chain", "stream"] },
20542
20628
  strategic_pillar: { alt_labels: ["pillar", "foundation"] },
20543
20629
  assumption: { alt_labels: ["belief", "working assumption", "premise"] },
20630
+ strategic_question: { alt_labels: ["open question", "coordination question", "ownership question"] },
20544
20631
  // User layer
20545
20632
  job_step: { alt_labels: ["job stage", "job phase", "job map step"] },
20546
20633
  switching_cost: { alt_labels: ["lock-in", "migration cost", "switching barrier"] },
@@ -21279,6 +21366,30 @@ var UPG_TREE_PATTERNS = [
21279
21366
  metric: [opt("metric"), opt("outcome")]
21280
21367
  },
21281
21368
  natural_depth: 3
21369
+ },
21370
+ {
21371
+ id: "org",
21372
+ label: "Org chart",
21373
+ description: "Departments and the teams they contain, plus the sub-teams nested within those teams. The people-structure org chart, walked by containment (department_contains_team, then team_contains_team). Distinct from product_area, which is the product classification axis, not the org.",
21374
+ region: "operations_quality",
21375
+ gap_policy: "all-optional",
21376
+ anchor_type: "department",
21377
+ // A graph with no department roots at the team (team -> sub-team), reported
21378
+ // anchor_resolved_from: department. A sub-team also renders as a bare team
21379
+ // root when its parent department is not modelled.
21380
+ fallback_anchors: ["team"],
21381
+ child_map: {
21382
+ // department -> team (department_contains_team) is the first level; team ->
21383
+ // team (team_contains_team, 0.17.2) is the second, so a sub-team nested one
21384
+ // level deeper than department_contains_team renders under its parent team.
21385
+ // Self-nesting: the assembler's `seen` set terminates a team -> team cycle
21386
+ // for free (a team met again becomes a shared reference).
21387
+ department: [opt("team")],
21388
+ team: [opt("team")]
21389
+ },
21390
+ // Default to 3 tiers (department -> team -> sub-team); `depth` extends into
21391
+ // deeper team_contains_team nesting.
21392
+ natural_depth: 3
21282
21393
  }
21283
21394
  ];
21284
21395
  var UPG_TREE_PATTERNS_BY_ID = Object.fromEntries(
@@ -23061,25 +23172,34 @@ var STRATEGY_GUIDE = {
23061
23172
  // entries are later additions appended in chronological-introduction
23062
23173
  // order. Placement reflects the order in which they would naturally be
23063
23174
  // authored after the canonical strategy spine.
23064
- creation_sequence: ["product", "vision", "mission", "outcome", "objective", "key_result", "metric", "metric_quality_assessment", "strategic_theme", "strategic_pillar", "initiative", "capability", "value_stream", "assumption", "decision", "constraint"],
23175
+ creation_sequence: ["product", "vision", "mission", "outcome", "objective", "key_result", "metric", "metric_quality_assessment", "strategic_theme", "strategic_pillar", "initiative", "capability", "value_stream", "assumption", "strategic_question", "decision", "constraint"],
23065
23176
  patterns: [
23066
23177
  {
23067
23178
  name: "Strategic Cascade",
23068
23179
  description: "Vision grounds mission, product pursues outcomes and targets objectives, objectives achieved through key results measured by metrics",
23069
23180
  entity_types: ["vision", "mission", "outcome", "objective", "key_result", "metric"],
23070
23181
  edge_chain: ["product_guided_by_vision", "product_fulfils_mission", "vision_realised_through_mission", "product_pursues_outcome", "product_targets_objective", "objective_achieved_through_key_result", "outcome_measured_by_metric"]
23182
+ },
23183
+ {
23184
+ name: "Rendering the company spine",
23185
+ description: "The company OKR / strategy / north-star spine already renders with get_tree, no new pattern needed: switch to the org_rollup member (the company rollup graph) and run the okr, strategy, or north_star tree pattern there. In a portfolio the spine can span files, a rollup theme laddering into product-graph objectives through the cross-product strategic_theme_contains_objective edge; get_tree walks the active member, so render the rollup for the whole-company view and a product for its slice.",
23186
+ entity_types: ["strategic_theme", "objective", "key_result", "metric"],
23187
+ edge_chain: ["strategic_theme_contains_objective", "objective_achieved_through_key_result", "key_result_quantified_by_metric"]
23071
23188
  }
23072
23189
  ],
23073
23190
  required_bridges: [
23074
23191
  { edge_type: "outcome_reveals_opportunity", target_domain: "discovery", when: "Outcomes should connect to the opportunities that deliver them" },
23075
23192
  { edge_type: "outcome_delivered_by_feature", target_domain: "product_spec", when: "Strategic outcomes should decompose into shipped features" },
23076
- { edge_type: "assumption_becomes_hypothesis", target_domain: "validation", when: "Risky assumptions should become testable hypotheses" }
23193
+ { edge_type: "assumption_becomes_hypothesis", target_domain: "validation", when: "Risky assumptions should become testable hypotheses" },
23194
+ { edge_type: "objective_depends_on_dependency", target_domain: "team_org", when: "An objective that hinges on cross-team work should name the dependency it is exposed to" },
23195
+ { edge_type: "objective_defers_feature", target_domain: "product_spec", when: "Work an objective explicitly puts out of scope for now should point at the deferred feature with a deferred_to period, not silently vanish from the quarter" }
23077
23196
  ],
23078
23197
  anti_patterns: [
23079
23198
  { description: "Outcomes without metrics. Measurement is the signal an outcome happened." },
23080
23199
  { description: "Objectives without key results: an objective without measurement is a wish" },
23081
23200
  { description: "Too many strategic themes: focus beats breadth, aim for 2-4 active themes" },
23082
- { description: "Constraints without an origin: a qualitative guardrail lives on a constraint, so set constraint_origin to say where it comes from. internal marks a self-imposed principle or operating tenet the team commits to; external marks a limit, requirement, or ceiling imposed from outside (a regulation, a budget cap, a platform bound)." }
23201
+ { description: "Constraints without an origin: a qualitative guardrail lives on a constraint, so set constraint_origin to say where it comes from. internal marks a self-imposed principle or operating tenet the team commits to; external marks a limit, requirement, or ceiling imposed from outside (a regulation, a budget cap, a platform bound)." },
23202
+ { description: "Overloading assumption for open questions: an assumption is a premise the plan is built on and resolves by being tested (assumption_becomes_hypothesis). An unresolved coordination or ownership question the plan is exposed to (who owns a capability across teams, where a boundary falls after a reorg) is a strategic_question, raised under the objective or initiative it hangs off. Do not force one into the other." }
23083
23203
  ]
23084
23204
  };
23085
23205
  var PRODUCT_SPEC_GUIDE = {
@@ -27132,6 +27252,10 @@ var UPG_REGIONS = [
27132
27252
  type: "assumption",
27133
27253
  role: "leaf"
27134
27254
  },
27255
+ {
27256
+ type: "strategic_question",
27257
+ role: "leaf"
27258
+ },
27135
27259
  {
27136
27260
  type: "constraint",
27137
27261
  role: "leaf"
@@ -27157,6 +27281,8 @@ var UPG_REGIONS = [
27157
27281
  "strategic_pillar_decided_via_decision",
27158
27282
  "strategic_theme_pursues_initiative",
27159
27283
  "initiative_assumes_assumption",
27284
+ "objective_raises_strategic_question",
27285
+ "initiative_raises_strategic_question",
27160
27286
  "initiative_drives_outcome",
27161
27287
  "objective_achieved_through_key_result",
27162
27288
  "objective_measured_by_metric",
@@ -29841,7 +29967,7 @@ function isCanonical(text) {
29841
29967
  }
29842
29968
 
29843
29969
  // src/index.ts
29844
- var UPG_VERSION = "0.17.2";
29970
+ var UPG_VERSION = "0.17.4";
29845
29971
  var UPG_FORMAT_VERSION = "0.4.0";
29846
29972
  var MARKDOWN_FORMAT_VERSION = "0.1";
29847
29973
  var UPG_TYPES = getTypes();
@@ -29915,6 +30041,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
29915
30041
  COVERAGE_ANTI_PATTERNS,
29916
30042
  DEFAULT_ENTITY_EMOJI,
29917
30043
  DEFERRED_PROPOSED_BY_CONTRACT,
30044
+ DEFER_EDGE_PROPERTY_SCHEMA,
29918
30045
  DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK,
29919
30046
  ENGINEERING_PLATFORM_PLAYBOOK,
29920
30047
  ENTITY_EMOJI,
@@ -29944,6 +30071,9 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
29944
30071
  UPG_CONTAINMENT_FREE_TYPES,
29945
30072
  UPG_COUNT_BENCHMARKS,
29946
30073
  UPG_CROSS_EDGE_TYPES,
30074
+ UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES,
30075
+ UPG_CROSS_ONLY_EDGE_TYPES,
30076
+ UPG_DELIBERATE_ONLY_EDGE_TYPES,
29947
30077
  UPG_DEPRECATED_TYPES,
29948
30078
  UPG_DOMAINS,
29949
30079
  UPG_DOMAIN_ACTIVATION,
@@ -30074,6 +30204,8 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
30074
30204
  isCanonical,
30075
30205
  isCanonicalProductStage,
30076
30206
  isContainmentFreeType,
30207
+ isCrossProductEligible,
30208
+ isDeliberateOnlyEdge,
30077
30209
  isDeprecatedType,
30078
30210
  isDomainGuideStep,
30079
30211
  isEntitySequenceStep,