@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 +1 -1
- package/dist/index.cjs +203 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +268 -17
- package/dist/index.d.ts +268 -17
- package/dist/index.js +197 -71
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20,7 +20,8 @@ var UPG_DOMAINS = [
|
|
|
20
20
|
"strategic_pillar",
|
|
21
21
|
"assumption",
|
|
22
22
|
"decision",
|
|
23
|
-
"constraint"
|
|
23
|
+
"constraint",
|
|
24
|
+
"strategic_question"
|
|
24
25
|
]
|
|
25
26
|
},
|
|
26
27
|
{
|
|
@@ -539,6 +540,10 @@ var UPG_ENTITY_META = [
|
|
|
539
540
|
{ name: "assumption", type_id: "ent_014", maturity: "stable", since: "0.1.0" },
|
|
540
541
|
{ name: "decision", type_id: "ent_015", maturity: "stable", since: "0.1.0" },
|
|
541
542
|
{ name: "constraint", type_id: "ent_348", maturity: "stable", since: "0.4.3" },
|
|
543
|
+
// (0.17.4) Strategy-domain sibling of research_question / design_question,
|
|
544
|
+
// completing the domain-question triad. An open coordination/ownership question
|
|
545
|
+
// a plan is exposed to (distinct from `assumption`, which the plan is built on).
|
|
546
|
+
{ name: "strategic_question", type_id: "ent_357", maturity: "proposed", since: "0.17.4" },
|
|
542
547
|
// ── User ──
|
|
543
548
|
{ name: "persona", type_id: "ent_016", maturity: "stable", since: "0.1.0" },
|
|
544
549
|
{ name: "job", type_id: "ent_017", maturity: "stable", since: "0.1.0" },
|
|
@@ -1013,6 +1018,12 @@ var CLASSIFICATION_EDGE_PROPERTY_SCHEMA = {
|
|
|
1013
1018
|
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)."
|
|
1014
1019
|
}
|
|
1015
1020
|
};
|
|
1021
|
+
var DEFER_EDGE_PROPERTY_SCHEMA = {
|
|
1022
|
+
deferred_to: {
|
|
1023
|
+
type: "string",
|
|
1024
|
+
description: 'Target period the parked work is deferred to. Freeform, mirroring strategic_theme.time_horizon. @example "Q4 2026", "FY27", "next release".'
|
|
1025
|
+
}
|
|
1026
|
+
};
|
|
1016
1027
|
var UPG_EDGE_CATALOG = {
|
|
1017
1028
|
// ── Part 1: Core Narrative Spine (Ring 1) ──────────────────────────────────
|
|
1018
1029
|
// 1.1 User Domain
|
|
@@ -1029,7 +1040,7 @@ var UPG_EDGE_CATALOG = {
|
|
|
1029
1040
|
persona_aspires_to_desired_outcome: { forward_verb: "aspires_to", reverse_verb: "aspirational_for", classification: "hierarchy", source_type: "persona", target_type: "desired_outcome" },
|
|
1030
1041
|
// Delegation (0.11.6): a persona delegates work to another. The common case is human -> agent
|
|
1031
1042
|
// (Content Ops Lead -> Content Agent), but it also expresses human -> human (editor -> reviewer).
|
|
1032
|
-
persona_delegates_to_persona: { forward_verb: "delegates_to", reverse_verb: "delegated_by", classification: "semantic", source_type: "persona", target_type: "persona" },
|
|
1043
|
+
persona_delegates_to_persona: { forward_verb: "delegates_to", reverse_verb: "delegated_by", classification: "semantic", source_type: "persona", target_type: "persona", cross_product_eligible: true },
|
|
1033
1044
|
persona_incurs_switching_cost: { forward_verb: "incurs", reverse_verb: "incurred_by", classification: "hierarchy", source_type: "persona", target_type: "switching_cost" },
|
|
1034
1045
|
job_surfaces_need: { forward_verb: "surfaces", reverse_verb: "surfaces_from", classification: "causal", source_type: "job", target_type: "need" },
|
|
1035
1046
|
job_motivates_desired_outcome: { forward_verb: "motivates", reverse_verb: "motivated_by", classification: "causal", source_type: "job", target_type: "desired_outcome" },
|
|
@@ -1147,15 +1158,15 @@ var UPG_EDGE_CATALOG = {
|
|
|
1147
1158
|
// Dual-registered as a cross-edge (UPG_CROSS_EDGE_TYPES) so it also spans our
|
|
1148
1159
|
// product graph and a watched competitor-intelligence graph. Distinct from
|
|
1149
1160
|
// `competitor_feature_inspires_feature` (ideation lineage, not parity).
|
|
1150
|
-
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 },
|
|
1161
|
+
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 },
|
|
1151
1162
|
// 0.10.0 (spec issue #41): competitor_signal is a dated competitor move (feature
|
|
1152
1163
|
// launch / pricing change / acquisition / partnership / market entry) emitted by a
|
|
1153
1164
|
// competitor and mapped onto our portfolio. `emits` is within the watched graph;
|
|
1154
1165
|
// `maps_to_feature` / `surfaces_opportunity` cross from the watched signal into our
|
|
1155
1166
|
// product graph (dual-registered as cross-edges in UPG_CROSS_EDGE_TYPES).
|
|
1156
1167
|
competitor_emits_competitor_signal: { forward_verb: "emits", reverse_verb: "emitted_by", classification: "hierarchy", source_type: "competitor", target_type: "competitor_signal" },
|
|
1157
|
-
competitor_signal_maps_to_feature: { forward_verb: "maps_to", reverse_verb: "targeted_by_signal", classification: "cross-domain", source_type: "competitor_signal", target_type: "feature" },
|
|
1158
|
-
competitor_signal_surfaces_opportunity: { forward_verb: "surfaces", reverse_verb: "prompted_by_signal", classification: "cross-domain", source_type: "competitor_signal", target_type: "opportunity" },
|
|
1168
|
+
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 },
|
|
1169
|
+
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 },
|
|
1159
1170
|
competitive_analysis_analyses_competitor: { forward_verb: "analyses", reverse_verb: "analysed_in", classification: "hierarchy", source_type: "competitive_analysis", target_type: "competitor" },
|
|
1160
1171
|
competitive_analysis_identifies_market_trend: { forward_verb: "identifies", reverse_verb: "identified_in", classification: "hierarchy", source_type: "competitive_analysis", target_type: "market_trend" },
|
|
1161
1172
|
competitive_analysis_scopes_market_segment: { forward_verb: "scopes", reverse_verb: "scoped_in", classification: "hierarchy", source_type: "competitive_analysis", target_type: "market_segment" },
|
|
@@ -1188,13 +1199,13 @@ var UPG_EDGE_CATALOG = {
|
|
|
1188
1199
|
// competitor can be classified directly against a `registry/{classification_value}`
|
|
1189
1200
|
// canonical, eliminating the per-graph taxonomy node. Within-graph (the catalogue
|
|
1190
1201
|
// case) here; cross-product against the registry canonical via create_cross_product_edge.
|
|
1191
|
-
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 },
|
|
1202
|
+
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 },
|
|
1192
1203
|
// 0.10.3: the polymorphic, type-agnostic sibling. ANY node (a feature, a
|
|
1193
1204
|
// product, a market_segment) classified against a classification_value, so
|
|
1194
1205
|
// classification is not welded to the competitor type. Also dual-registered as
|
|
1195
1206
|
// a cross-edge for the registry-canonical case. source_type:'node' (wildcard);
|
|
1196
1207
|
// listed in UPG_POLYMORPHIC_EDGE_KEYS.
|
|
1197
|
-
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 },
|
|
1208
|
+
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 },
|
|
1198
1209
|
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" },
|
|
1199
1210
|
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" },
|
|
1200
1211
|
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" },
|
|
@@ -1247,28 +1258,28 @@ var UPG_EDGE_CATALOG = {
|
|
|
1247
1258
|
feedback_program_has_beta_program: { forward_verb: "has", reverse_verb: "part_of", classification: "hierarchy", source_type: "feedback_program", target_type: "beta_program" },
|
|
1248
1259
|
// ── Part 2: Strategic & Execution Spine (Ring 2) ───────────────────────────
|
|
1249
1260
|
// 2.1 Strategic Domain
|
|
1250
|
-
product_pursues_outcome: { forward_verb: "pursues", reverse_verb: "pursued_by", classification: "hierarchy", source_type: "product", target_type: "outcome" },
|
|
1251
|
-
product_targets_objective: { forward_verb: "targets", reverse_verb: "targeted_by", classification: "hierarchy", source_type: "product", target_type: "objective" },
|
|
1252
|
-
product_guided_by_vision: { forward_verb: "guided_by", reverse_verb: "guides", classification: "hierarchy", source_type: "product", target_type: "vision" },
|
|
1261
|
+
product_pursues_outcome: { forward_verb: "pursues", reverse_verb: "pursued_by", classification: "hierarchy", source_type: "product", target_type: "outcome", cross_product_eligible: true },
|
|
1262
|
+
product_targets_objective: { forward_verb: "targets", reverse_verb: "targeted_by", classification: "hierarchy", source_type: "product", target_type: "objective", cross_product_eligible: true },
|
|
1263
|
+
product_guided_by_vision: { forward_verb: "guided_by", reverse_verb: "guides", classification: "hierarchy", source_type: "product", target_type: "vision", cross_product_eligible: true },
|
|
1253
1264
|
// product→{mission,strategic_theme,strategic_pillar,initiative,capability,value_stream,assumption}
|
|
1254
1265
|
// are semantic "how the product relates to the strategic cascade", not containment.
|
|
1255
1266
|
// The containment chain is product → vision → mission → strategic_pillar → … so these
|
|
1256
1267
|
// targets are reachable via the vision/mission hierarchy already.
|
|
1257
|
-
product_fulfils_mission: { forward_verb: "fulfils", reverse_verb: "fulfilled_by", classification: "semantic", source_type: "product", target_type: "mission" },
|
|
1258
|
-
product_organises_around_strategic_theme: { forward_verb: "organises_around", reverse_verb: "organises", classification: "semantic", source_type: "product", target_type: "strategic_theme" },
|
|
1259
|
-
product_stands_on_strategic_pillar: { forward_verb: "stands_on", reverse_verb: "supports", classification: "semantic", source_type: "product", target_type: "strategic_pillar" },
|
|
1260
|
-
product_invests_in_initiative: { forward_verb: "invests_in", reverse_verb: "investment_of", classification: "semantic", source_type: "product", target_type: "initiative" },
|
|
1268
|
+
product_fulfils_mission: { forward_verb: "fulfils", reverse_verb: "fulfilled_by", classification: "semantic", source_type: "product", target_type: "mission", cross_product_eligible: true },
|
|
1269
|
+
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 },
|
|
1270
|
+
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 },
|
|
1271
|
+
product_invests_in_initiative: { forward_verb: "invests_in", reverse_verb: "investment_of", classification: "semantic", source_type: "product", target_type: "initiative", cross_product_eligible: true },
|
|
1261
1272
|
product_develops_capability: { forward_verb: "develops", reverse_verb: "developed_by", classification: "semantic", source_type: "product", target_type: "capability" },
|
|
1262
1273
|
product_delivers_through_value_stream: { forward_verb: "delivers_through", reverse_verb: "delivers_for", classification: "semantic", source_type: "product", target_type: "value_stream" },
|
|
1263
1274
|
product_holds_assumption: { forward_verb: "holds", reverse_verb: "held_by", classification: "semantic", source_type: "product", target_type: "assumption" },
|
|
1264
|
-
product_measures_with_metric: { forward_verb: "measures_with", reverse_verb: "measures", classification: "hierarchy", source_type: "product", target_type: "metric" },
|
|
1265
|
-
outcome_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "hierarchy", source_type: "outcome", target_type: "metric" },
|
|
1275
|
+
product_measures_with_metric: { forward_verb: "measures_with", reverse_verb: "measures", classification: "hierarchy", source_type: "product", target_type: "metric", cross_product_eligible: true },
|
|
1276
|
+
outcome_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "hierarchy", source_type: "outcome", target_type: "metric", cross_product_eligible: true },
|
|
1266
1277
|
// (UPG-677) outcome_tracked_by_metric retired — near-synonym of
|
|
1267
1278
|
// outcome_measured_by_metric (the kept canonical key). Captain's lean =
|
|
1268
1279
|
// collapse. See UPG_EDGE_MIGRATIONS['0.9.9'].
|
|
1269
|
-
objective_achieved_through_key_result: { forward_verb: "achieved_through", reverse_verb: "achieves", classification: "hierarchy", source_type: "objective", target_type: "key_result" },
|
|
1270
|
-
objective_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "hierarchy", source_type: "objective", target_type: "metric" },
|
|
1271
|
-
key_result_quantified_by_metric: { forward_verb: "quantified_by", reverse_verb: "quantifies", classification: "hierarchy", source_type: "key_result", target_type: "metric" },
|
|
1280
|
+
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 },
|
|
1281
|
+
objective_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "hierarchy", source_type: "objective", target_type: "metric", cross_product_eligible: true },
|
|
1282
|
+
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 },
|
|
1272
1283
|
// (UPG-677) key_result_tracked_by_metric retired — near-synonym of
|
|
1273
1284
|
// key_result_quantified_by_metric (the kept canonical key). Captain's lean =
|
|
1274
1285
|
// collapse. See UPG_EDGE_MIGRATIONS['0.9.9'].
|
|
@@ -1278,7 +1289,7 @@ var UPG_EDGE_CATALOG = {
|
|
|
1278
1289
|
strategic_pillar_enables_capability: { forward_verb: "enables", reverse_verb: "enabled_by", classification: "hierarchy", source_type: "strategic_pillar", target_type: "capability" },
|
|
1279
1290
|
strategic_pillar_delivers_value_stream: { forward_verb: "delivers", reverse_verb: "delivered_by", classification: "hierarchy", source_type: "strategic_pillar", target_type: "value_stream" },
|
|
1280
1291
|
strategic_pillar_decided_via_decision: { forward_verb: "decided_via", reverse_verb: "decided_for", classification: "hierarchy", source_type: "strategic_pillar", target_type: "decision" },
|
|
1281
|
-
strategic_theme_pursues_initiative: { forward_verb: "pursues", reverse_verb: "pursued_under", classification: "hierarchy", source_type: "strategic_theme", target_type: "initiative" },
|
|
1292
|
+
strategic_theme_pursues_initiative: { forward_verb: "pursues", reverse_verb: "pursued_under", classification: "hierarchy", source_type: "strategic_theme", target_type: "initiative", cross_product_eligible: true },
|
|
1282
1293
|
// v0.9.0 (UPG-660): the soft bridge from the annual strategy focus area to the
|
|
1283
1294
|
// roadmap grouping that realises it. Semantic, NOT hierarchy: strategic_theme and
|
|
1284
1295
|
// roadmap_theme sit on different spines (strategy cascade vs roadmap cascade), so
|
|
@@ -1306,11 +1317,11 @@ var UPG_EDGE_CATALOG = {
|
|
|
1306
1317
|
// surfaces the upward-rollup read. Mirrors `strategic_pillar_organises_
|
|
1307
1318
|
// strategic_theme` (pillar → theme), completing the strategic cascade:
|
|
1308
1319
|
// strategic_pillar → strategic_theme → objective → key_result.
|
|
1309
|
-
strategic_theme_delivers_outcome: { forward_verb: "delivers", reverse_verb: "delivered_by", classification: "causal", source_type: "strategic_theme", target_type: "outcome" },
|
|
1310
|
-
strategic_theme_measured_by_key_result: { forward_verb: "measured_by", reverse_verb: "measures", classification: "causal", source_type: "strategic_theme", target_type: "key_result" },
|
|
1311
|
-
strategic_theme_contains_objective: { forward_verb: "contains", reverse_verb: "rolls_up_to", classification: "hierarchy", source_type: "strategic_theme", target_type: "objective" },
|
|
1320
|
+
strategic_theme_delivers_outcome: { forward_verb: "delivers", reverse_verb: "delivered_by", classification: "causal", source_type: "strategic_theme", target_type: "outcome", cross_product_eligible: true },
|
|
1321
|
+
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 },
|
|
1322
|
+
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 },
|
|
1312
1323
|
initiative_assumes_assumption: { forward_verb: "assumes", reverse_verb: "assumed_by", classification: "hierarchy", source_type: "initiative", target_type: "assumption" },
|
|
1313
|
-
initiative_drives_outcome: { forward_verb: "drives", reverse_verb: "driven_by", classification: "cross-domain", source_type: "initiative", target_type: "outcome" },
|
|
1324
|
+
initiative_drives_outcome: { forward_verb: "drives", reverse_verb: "driven_by", classification: "cross-domain", source_type: "initiative", target_type: "outcome", cross_product_eligible: true },
|
|
1314
1325
|
capability_enables_value_stream: { forward_verb: "enables", reverse_verb: "enabled_by", classification: "cross-domain", source_type: "capability", target_type: "value_stream" },
|
|
1315
1326
|
// v0.5.2 (UPG-528): three capability-anchored edges that complete the
|
|
1316
1327
|
// Wardley-style value chain: need → capability → capability → feature.
|
|
@@ -1448,7 +1459,7 @@ var UPG_EDGE_CATALOG = {
|
|
|
1448
1459
|
// brand_identity. Dual-registered: also a cross-edge for the common case where the
|
|
1449
1460
|
// brand is a registry singleton in another graph (the ratified pattern: brand is a
|
|
1450
1461
|
// singleton expressed, not instance_of-d); this catalog entry is the within-graph case.
|
|
1451
|
-
product_expresses_brand_identity: { forward_verb: "expresses", reverse_verb: "expressed_by", classification: "semantic", source_type: "product", target_type: "brand_identity" },
|
|
1462
|
+
product_expresses_brand_identity: { forward_verb: "expresses", reverse_verb: "expressed_by", classification: "semantic", source_type: "product", target_type: "brand_identity", cross_product_eligible: true },
|
|
1452
1463
|
design_system_encompasses_user_journey: { forward_verb: "encompasses", reverse_verb: "encompassed_in", classification: "hierarchy", source_type: "design_system", target_type: "user_journey" },
|
|
1453
1464
|
design_system_encompasses_user_flow: { forward_verb: "encompasses", reverse_verb: "encompassed_in", classification: "hierarchy", source_type: "design_system", target_type: "user_flow" },
|
|
1454
1465
|
design_system_informed_by_insight: { forward_verb: "informed_by", reverse_verb: "informs", classification: "hierarchy", source_type: "design_system", target_type: "insight" },
|
|
@@ -1460,12 +1471,12 @@ var UPG_EDGE_CATALOG = {
|
|
|
1460
1471
|
design_component_specified_by_interaction_spec: { forward_verb: "specified_by", reverse_verb: "specifies", classification: "hierarchy", source_type: "design_component", target_type: "interaction_spec" },
|
|
1461
1472
|
design_component_composes_design_component: { forward_verb: "composes", reverse_verb: "composed_in", classification: "hierarchy", source_type: "design_component", target_type: "design_component" },
|
|
1462
1473
|
prototype_annotated_with_annotation: { forward_verb: "annotated_with", reverse_verb: "annotates", classification: "hierarchy", source_type: "prototype", target_type: "annotation" },
|
|
1463
|
-
screen_renders_design_component: { forward_verb: "renders", reverse_verb: "rendered_on", classification: "hierarchy", source_type: "screen", target_type: "design_component" },
|
|
1474
|
+
screen_renders_design_component: { forward_verb: "renders", reverse_verb: "rendered_on", classification: "hierarchy", source_type: "screen", target_type: "design_component", cross_product_eligible: true },
|
|
1464
1475
|
// Marketing surface to product (0.12.7, UPG-696/698). A marketing/landing screen
|
|
1465
1476
|
// markets a product. Dual-registered: also a cross-edge (UPG_CROSS_EDGE_TYPES) for
|
|
1466
1477
|
// the common case where the product lives in another graph; this catalog entry is
|
|
1467
1478
|
// the within-graph degenerate case (a product's own landing page).
|
|
1468
|
-
screen_markets_product: { forward_verb: "markets", reverse_verb: "marketed_by", classification: "semantic", source_type: "screen", target_type: "product" },
|
|
1479
|
+
screen_markets_product: { forward_verb: "markets", reverse_verb: "marketed_by", classification: "semantic", source_type: "screen", target_type: "product", cross_product_eligible: true },
|
|
1469
1480
|
// Connective cross-product references (0.13.1, Data's connective-layer brief).
|
|
1470
1481
|
// Dual-registered (also in UPG_CROSS_EDGE_TYPES) for the common cross-graph case;
|
|
1471
1482
|
// these catalog entries are the within-graph degenerate case.
|
|
@@ -1481,10 +1492,10 @@ var UPG_EDGE_CATALOG = {
|
|
|
1481
1492
|
// system (the adoption semantic, mirroring product_implements_specification). Distinct
|
|
1482
1493
|
// from the hierarchy `product_systematised_in_design_system` (structural containment):
|
|
1483
1494
|
// same pattern as brand (branded_as = hierarchy, expresses = semantic).
|
|
1484
|
-
screen_targets_competitor: { forward_verb: "targets", reverse_verb: "targeted_by", classification: "semantic", source_type: "screen", target_type: "competitor" },
|
|
1485
|
-
feature_surfaces_product: { forward_verb: "surfaces", reverse_verb: "surfaced_by", classification: "semantic", source_type: "feature", target_type: "product" },
|
|
1486
|
-
feature_uses_design_component: { forward_verb: "uses", reverse_verb: "used_by", classification: "semantic", source_type: "feature", target_type: "design_component" },
|
|
1487
|
-
product_implements_design_system: { forward_verb: "implements", reverse_verb: "implemented_by", classification: "semantic", source_type: "product", target_type: "design_system" },
|
|
1495
|
+
screen_targets_competitor: { forward_verb: "targets", reverse_verb: "targeted_by", classification: "semantic", source_type: "screen", target_type: "competitor", cross_product_eligible: true },
|
|
1496
|
+
feature_surfaces_product: { forward_verb: "surfaces", reverse_verb: "surfaced_by", classification: "semantic", source_type: "feature", target_type: "product", cross_product_eligible: true },
|
|
1497
|
+
feature_uses_design_component: { forward_verb: "uses", reverse_verb: "used_by", classification: "semantic", source_type: "feature", target_type: "design_component", cross_product_eligible: true },
|
|
1498
|
+
product_implements_design_system: { forward_verb: "implements", reverse_verb: "implemented_by", classification: "semantic", source_type: "product", target_type: "design_system", cross_product_eligible: true },
|
|
1488
1499
|
screen_navigates_to_screen: { forward_verb: "navigates_to", reverse_verb: "navigated_from", classification: "hierarchy", source_type: "screen", target_type: "screen" },
|
|
1489
1500
|
screen_surfaces_feature: { forward_verb: "surfaces", reverse_verb: "surfaced_on", classification: "cross-domain", source_type: "screen", target_type: "feature" },
|
|
1490
1501
|
screen_wireframed_as_wireframe: { forward_verb: "wireframed_as", reverse_verb: "wireframes", classification: "hierarchy", source_type: "screen", target_type: "wireframe" },
|
|
@@ -2336,10 +2347,10 @@ var UPG_EDGE_CATALOG = {
|
|
|
2336
2347
|
experiment_run_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "hierarchy", source_type: "experiment_run", target_type: "metric" },
|
|
2337
2348
|
solution_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "hierarchy", source_type: "solution", target_type: "metric" },
|
|
2338
2349
|
// ── Cross-domain: Ownership ──────────────────────────────────────────────────
|
|
2339
|
-
node_owned_by_team: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "team" },
|
|
2350
|
+
node_owned_by_team: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "team", cross_product_eligible: true },
|
|
2340
2351
|
node_owned_by_role: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "role" },
|
|
2341
2352
|
node_owned_by_stakeholder: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "stakeholder" },
|
|
2342
|
-
node_owned_by_department: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "department" },
|
|
2353
|
+
node_owned_by_department: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "department", cross_product_eligible: true },
|
|
2343
2354
|
node_owned_by_person: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "node", target_type: "person" },
|
|
2344
2355
|
// ── Cross-domain: Architecture (DDD) ─────────────────────────────────────────
|
|
2345
2356
|
// Service, domain_event, domain_entity, aggregate, read_model, api_contract,
|
|
@@ -3003,7 +3014,7 @@ var UPG_EDGE_CATALOG = {
|
|
|
3003
3014
|
// not the outcome it exists to move; the strategic spine was severed at its
|
|
3004
3015
|
// anchor (0 outbound to outcome). An objective ADVANCES an outcome. Intra-
|
|
3005
3016
|
// domain (both in strategy) and directional → causal.
|
|
3006
|
-
objective_advances_outcome: { forward_verb: "advances", reverse_verb: "advanced_by", classification: "causal", source_type: "objective", target_type: "outcome" },
|
|
3017
|
+
objective_advances_outcome: { forward_verb: "advances", reverse_verb: "advanced_by", classification: "causal", source_type: "objective", target_type: "outcome", cross_product_eligible: true },
|
|
3007
3018
|
// ── F6: Priority 2 — scored / synthesis / verdict dead-end leaves (P-A) ─────
|
|
3008
3019
|
// desired_outcome (Ulwick-scored: importance × satisfaction) had 0 outbound —
|
|
3009
3020
|
// the scores could not flow anywhere. An under-served desired_outcome REVEALS
|
|
@@ -3086,9 +3097,61 @@ var UPG_EDGE_CATALOG = {
|
|
|
3086
3097
|
specification_governed_by_organization: { forward_verb: "governed_by", reverse_verb: "governs", classification: "semantic", source_type: "specification", target_type: "organization" },
|
|
3087
3098
|
// Operating-lifecycle cross-edges (0.11.6): a product's journey phase realises a canonical
|
|
3088
3099
|
// operating stage (the cross-surface join key); a stage is measured by a rollup metric (loop close).
|
|
3089
|
-
journey_phase_realises_operating_stage: { forward_verb: "realises", reverse_verb: "realised_by", classification: "cross-domain", source_type: "journey_phase", target_type: "operating_stage" },
|
|
3090
|
-
operating_stage_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "cross-domain", source_type: "operating_stage", target_type: "metric" }
|
|
3100
|
+
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 },
|
|
3101
|
+
operating_stage_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "cross-domain", source_type: "operating_stage", target_type: "metric" },
|
|
3102
|
+
// ── OKR planning coverage (0.17.4) ──────────────────────────────────────────
|
|
3103
|
+
// Reconciling the strategy graph against a live planning doc surfaced texture
|
|
3104
|
+
// the objective — the node every OKR doc organises itself around — could not
|
|
3105
|
+
// reach: cross-team dependencies and deferred (out-of-scope) work.
|
|
3106
|
+
// objective ↔ dependency. Every OKR in the source doc carries a dependency
|
|
3107
|
+
// table ("which other team's work this depends on"). `dependency` (team_org)
|
|
3108
|
+
// already carries dependency_type / criticality / target_date; it was
|
|
3109
|
+
// reachable only from `team`. An objective DEPENDS ON a dependency; the
|
|
3110
|
+
// dependency BLOCKS the objective (explicit mirror, not left implicit).
|
|
3111
|
+
// Cross-domain, not hierarchy: a dependency is parented under its owning team,
|
|
3112
|
+
// so an objective references it laterally rather than containing it. Both are
|
|
3113
|
+
// cross_product_eligible — a Studio objective can depend on a dependency owned
|
|
3114
|
+
// by another team's graph within the portfolio (0.17.3 locked predicate).
|
|
3115
|
+
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 },
|
|
3116
|
+
dependency_blocks_objective: { forward_verb: "blocks", reverse_verb: "blocked_by", classification: "cross-domain", source_type: "dependency", target_type: "objective", cross_product_eligible: true },
|
|
3117
|
+
// objective / initiative → strategic_question. A planning doc's "Risks & Open
|
|
3118
|
+
// Questions" section names unresolved coordination questions the plan is
|
|
3119
|
+
// exposed to (who owns a capability across teams after a reorg). The
|
|
3120
|
+
// strategy-domain sibling of research_question / design_question. The question
|
|
3121
|
+
// is raised under (contained by) the objective or initiative that surfaces it,
|
|
3122
|
+
// so hierarchy — mirroring initiative_assumes_assumption. Within-graph: the
|
|
3123
|
+
// question node is authored alongside its objective, so NOT
|
|
3124
|
+
// cross_product_eligible (the cross-team nature lives in the question text, not
|
|
3125
|
+
// in a cross-graph edge).
|
|
3126
|
+
objective_raises_strategic_question: { forward_verb: "raises", reverse_verb: "raised_by", classification: "hierarchy", source_type: "objective", target_type: "strategic_question" },
|
|
3127
|
+
initiative_raises_strategic_question: { forward_verb: "raises", reverse_verb: "raised_by", classification: "hierarchy", source_type: "initiative", target_type: "strategic_question" },
|
|
3128
|
+
// objective → feature / capability (the defer / out-of-scope edge). Every OKR
|
|
3129
|
+
// in the source doc carries an explicit "Out of scope" list, load-bearing for
|
|
3130
|
+
// keeping a quarter from silently expanding (localization deferred to Q4,
|
|
3131
|
+
// another team's feature work parked). Modelled as an edge to the real feature
|
|
3132
|
+
// or capability parked for later, not a scalar exclusion string, so the parked
|
|
3133
|
+
// work stays queryable and connected. The `deferred_to` edge property carries
|
|
3134
|
+
// the temporal target. feature is product_spec (cross-domain); capability is
|
|
3135
|
+
// intra-strategy (semantic). Both cross_product_eligible: deferring another
|
|
3136
|
+
// product's feature or capability, authored in a different graph within the
|
|
3137
|
+
// portfolio, fits the 0.17.3 locked predicate.
|
|
3138
|
+
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 },
|
|
3139
|
+
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 }
|
|
3091
3140
|
};
|
|
3141
|
+
var UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES = Object.keys(UPG_EDGE_CATALOG).filter(
|
|
3142
|
+
(k) => UPG_EDGE_CATALOG[k].cross_product_eligible === true
|
|
3143
|
+
);
|
|
3144
|
+
function isCrossProductEligible(type) {
|
|
3145
|
+
const def = UPG_EDGE_CATALOG[type];
|
|
3146
|
+
return def?.cross_product_eligible === true;
|
|
3147
|
+
}
|
|
3148
|
+
var UPG_DELIBERATE_ONLY_EDGE_TYPES = Object.keys(UPG_EDGE_CATALOG).filter(
|
|
3149
|
+
(k) => UPG_EDGE_CATALOG[k].deliberate_only === true
|
|
3150
|
+
);
|
|
3151
|
+
function isDeliberateOnlyEdge(type) {
|
|
3152
|
+
const def = UPG_EDGE_CATALOG[type];
|
|
3153
|
+
return def?.deliberate_only === true;
|
|
3154
|
+
}
|
|
3092
3155
|
var UPG_POLYMORPHIC_EDGE_KEYS = [
|
|
3093
3156
|
// Universal semantic verbs
|
|
3094
3157
|
"node_informs_node",
|
|
@@ -3148,52 +3211,47 @@ function isLegacyProductStage(stage) {
|
|
|
3148
3211
|
}
|
|
3149
3212
|
|
|
3150
3213
|
// src/shapes/document.ts
|
|
3151
|
-
var
|
|
3214
|
+
var UPG_CROSS_ONLY_EDGE_TYPES = [
|
|
3215
|
+
// Peer overlap: "these two products share / overlap on this thing." Symmetric,
|
|
3216
|
+
// no canonical instance_of identity. shares_job / shares_need are the job/need
|
|
3217
|
+
// siblings of the persona/competitor/metric peers (connective layer, 0.13.1).
|
|
3152
3218
|
"shares_persona",
|
|
3153
3219
|
"shares_competitor",
|
|
3154
3220
|
"shares_metric",
|
|
3221
|
+
"shares_job",
|
|
3222
|
+
"shares_need",
|
|
3223
|
+
// Product-to-product relationships.
|
|
3155
3224
|
"depends_on_product",
|
|
3225
|
+
// runtime dependency (built-on / dogfood), not containment
|
|
3156
3226
|
"cannibalises",
|
|
3157
3227
|
"succeeds",
|
|
3158
3228
|
"hosts",
|
|
3229
|
+
// host runs the hosted product inside itself (container -> contained)
|
|
3230
|
+
// OKR / measurement rollup primitives: the cascade ACROSS products (subordinate
|
|
3231
|
+
// -> superior). `contributes_to` rolls a product strategy entity up to a higher-
|
|
3232
|
+
// level one; `rolls_up_to` feeds a product metric into a higher-level north-star.
|
|
3159
3233
|
"contributes_to",
|
|
3234
|
+
"rolls_up_to",
|
|
3235
|
+
// Canonical instance + area-to-audience: the target lives in the portfolio
|
|
3236
|
+
// `registry` section (`registry/{node_id}`). `instance_of` is same-type
|
|
3237
|
+
// canonical-to-instance; the area edges are minted via `link_area_to_audience`.
|
|
3160
3238
|
"instance_of",
|
|
3161
3239
|
"area_serves_persona",
|
|
3162
3240
|
"area_targets_market_segment",
|
|
3163
|
-
|
|
3241
|
+
// Foundations (0.9.12): a product-graph entity links to a canonical specification
|
|
3242
|
+
// or primitive in the registry (`registry/{node_id}` target, same shape as
|
|
3243
|
+
// instance_of). Registry-internal spec-to-spec links are catalog edges, not these.
|
|
3164
3244
|
"product_implements_specification",
|
|
3165
3245
|
"product_exposes_specification",
|
|
3166
3246
|
"feature_conforms_to_specification",
|
|
3167
3247
|
"api_contract_speaks_specification",
|
|
3168
3248
|
"product_exposes_primitive",
|
|
3169
3249
|
"feature_manipulates_primitive",
|
|
3170
|
-
"primitive_stored_as_data_type"
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
"node_classified_as_classification_value",
|
|
3176
|
-
"journey_phase_realises_operating_stage",
|
|
3177
|
-
"screen_markets_product",
|
|
3178
|
-
"screen_renders_design_component",
|
|
3179
|
-
"product_expresses_brand_identity",
|
|
3180
|
-
// Connective cross-product layer (0.13.1) — see UPGCrossEdgeType above.
|
|
3181
|
-
"shares_job",
|
|
3182
|
-
"shares_need",
|
|
3183
|
-
"persona_delegates_to_persona",
|
|
3184
|
-
"screen_targets_competitor",
|
|
3185
|
-
"feature_surfaces_product",
|
|
3186
|
-
"feature_uses_design_component",
|
|
3187
|
-
"product_implements_design_system",
|
|
3188
|
-
// Org-link (0.17.0): dual-registered ownership edges (see UPGCrossEdgeType above).
|
|
3189
|
-
"node_owned_by_team",
|
|
3190
|
-
"node_owned_by_department",
|
|
3191
|
-
// Cross-graph strategy & measurement (0.17.2): dual-registered OKR/measurement
|
|
3192
|
-
// hierarchy edges so the strategy spine can span files (see UPGCrossEdgeType above).
|
|
3193
|
-
"strategic_theme_contains_objective",
|
|
3194
|
-
"objective_achieved_through_key_result",
|
|
3195
|
-
"key_result_quantified_by_metric",
|
|
3196
|
-
"objective_measured_by_metric"
|
|
3250
|
+
"primitive_stored_as_data_type"
|
|
3251
|
+
];
|
|
3252
|
+
var UPG_CROSS_EDGE_TYPES = [
|
|
3253
|
+
...UPG_CROSS_ONLY_EDGE_TYPES,
|
|
3254
|
+
...UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES
|
|
3197
3255
|
];
|
|
3198
3256
|
var REGISTRY_PRODUCT_ID = "registry";
|
|
3199
3257
|
var UPG_PORTFOLIO_KINDS = ["owned", "watched", "strategic", "internal", "gtm"];
|
|
@@ -3461,7 +3519,9 @@ var UPG_VALID_CHILDREN = {
|
|
|
3461
3519
|
// where self-nesting genuinely lives, not on `experiment`).
|
|
3462
3520
|
experiment_run: ["learning", "evidence", "metric", "experiment_run"],
|
|
3463
3521
|
// ── OKR hierarchy ──────────────────────────────────────────────────────────
|
|
3464
|
-
|
|
3522
|
+
// strategic_question (0.17.4): an open coordination question raised under an
|
|
3523
|
+
// objective (objective_raises_strategic_question, hierarchy).
|
|
3524
|
+
objective: ["key_result", "metric", "strategic_question"],
|
|
3465
3525
|
key_result: ["metric"],
|
|
3466
3526
|
// ── Strategic cascade: vision → mission → strategic_pillar → strategic_theme →
|
|
3467
3527
|
// { initiative, objective } ───────────────────────────────────────────────
|
|
@@ -3486,7 +3546,7 @@ var UPG_VALID_CHILDREN = {
|
|
|
3486
3546
|
// catalog (hierarchy, strategic_theme → objective, reverse_verb: rolls_up_to;
|
|
3487
3547
|
// renamed from objective_rolls_up_to_strategic_theme in UPG-676).
|
|
3488
3548
|
strategic_theme: ["initiative", "objective"],
|
|
3489
|
-
initiative: ["assumption"],
|
|
3549
|
+
initiative: ["assumption", "strategic_question"],
|
|
3490
3550
|
// v0.5.2 (UPG-528): capability decomposes into sub-capabilities (Wardley
|
|
3491
3551
|
// value-chain spine) and is realised by user-facing features. Pairs with
|
|
3492
3552
|
// `capability_depends_on_capability` and `capability_implemented_by_feature`
|
|
@@ -4559,6 +4619,15 @@ var ASSUMPTION_LIFECYCLE = {
|
|
|
4559
4619
|
}
|
|
4560
4620
|
]
|
|
4561
4621
|
};
|
|
4622
|
+
var STRATEGIC_QUESTION_LIFECYCLE = {
|
|
4623
|
+
entity_type: "strategic_question",
|
|
4624
|
+
initial_phase: "open",
|
|
4625
|
+
terminal_phases: ["resolved"],
|
|
4626
|
+
phases: [
|
|
4627
|
+
{ id: "open", label: "Open", description: "The question has been raised but not yet answered. The plan is exposed to it.", transitions_to: ["resolved"] },
|
|
4628
|
+
{ 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"] }
|
|
4629
|
+
]
|
|
4630
|
+
};
|
|
4562
4631
|
var OUTCOME_LIFECYCLE = {
|
|
4563
4632
|
entity_type: "outcome",
|
|
4564
4633
|
initial_phase: "identified",
|
|
@@ -6236,6 +6305,7 @@ var UPG_LIFECYCLES = [
|
|
|
6236
6305
|
INITIATIVE_LIFECYCLE,
|
|
6237
6306
|
STRATEGIC_PILLAR_LIFECYCLE,
|
|
6238
6307
|
ASSUMPTION_LIFECYCLE,
|
|
6308
|
+
STRATEGIC_QUESTION_LIFECYCLE,
|
|
6239
6309
|
FEATURE_AREA_LIFECYCLE,
|
|
6240
6310
|
FEATURE_LIFECYCLE,
|
|
6241
6311
|
EPIC_LIFECYCLE,
|
|
@@ -12712,6 +12782,15 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
12712
12782
|
time_horizon: { type: "string", description: 'Standing / multi-year horizon, often open-ended (a pillar is durable). @example "3 years", "2026-2028", "ongoing"' },
|
|
12713
12783
|
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." }
|
|
12714
12784
|
},
|
|
12785
|
+
// StrategicQuestionProperties: StrategicQuestion entity. An open coordination or
|
|
12786
|
+
// ownership question a plan is exposed to (strategy sibling of research_question /
|
|
12787
|
+
// design_question). `status` is the node lifecycle (open -> resolved).
|
|
12788
|
+
strategic_question: {
|
|
12789
|
+
question: { type: "string", description: "The question itself. Primary content." },
|
|
12790
|
+
context: { type: "string", description: "Context that surfaced the question: the reorg, the boundary, the unowned area." },
|
|
12791
|
+
resolution: { type: "string", description: "The answer, captured when the question moves to `resolved`." },
|
|
12792
|
+
priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Importance to resolve relative to other open questions." }
|
|
12793
|
+
},
|
|
12715
12794
|
// StrategicThemeProperties: StrategicTheme entity. A time-bound thrust WITHIN a
|
|
12716
12795
|
// strategic_pillar (distinct cascade level, UPG-692 T3.3) — measured through its
|
|
12717
12796
|
// child objectives, so it carries no success_indicator of its own.
|
|
@@ -19740,6 +19819,7 @@ var ENTITY_EMOJI = {
|
|
|
19740
19819
|
stakeholder: "\u{1F9D1}\u200D\u{1F4BC}",
|
|
19741
19820
|
status_report: "\u{1F4C4}",
|
|
19742
19821
|
strategic_pillar: "\u{1F3DB}\uFE0F",
|
|
19822
|
+
strategic_question: "\u2754",
|
|
19743
19823
|
strategic_theme: "\u{1F9F5}",
|
|
19744
19824
|
subscription: "\u{1F502}",
|
|
19745
19825
|
success_milestone: "\u{1F389}",
|
|
@@ -20297,6 +20377,7 @@ var STANDARD_LABELS = {
|
|
|
20297
20377
|
value_stream: { alt_labels: ["value chain", "stream"] },
|
|
20298
20378
|
strategic_pillar: { alt_labels: ["pillar", "foundation"] },
|
|
20299
20379
|
assumption: { alt_labels: ["belief", "working assumption", "premise"] },
|
|
20380
|
+
strategic_question: { alt_labels: ["open question", "coordination question", "ownership question"] },
|
|
20300
20381
|
// User layer
|
|
20301
20382
|
job_step: { alt_labels: ["job stage", "job phase", "job map step"] },
|
|
20302
20383
|
switching_cost: { alt_labels: ["lock-in", "migration cost", "switching barrier"] },
|
|
@@ -21035,6 +21116,30 @@ var UPG_TREE_PATTERNS = [
|
|
|
21035
21116
|
metric: [opt("metric"), opt("outcome")]
|
|
21036
21117
|
},
|
|
21037
21118
|
natural_depth: 3
|
|
21119
|
+
},
|
|
21120
|
+
{
|
|
21121
|
+
id: "org",
|
|
21122
|
+
label: "Org chart",
|
|
21123
|
+
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.",
|
|
21124
|
+
region: "operations_quality",
|
|
21125
|
+
gap_policy: "all-optional",
|
|
21126
|
+
anchor_type: "department",
|
|
21127
|
+
// A graph with no department roots at the team (team -> sub-team), reported
|
|
21128
|
+
// anchor_resolved_from: department. A sub-team also renders as a bare team
|
|
21129
|
+
// root when its parent department is not modelled.
|
|
21130
|
+
fallback_anchors: ["team"],
|
|
21131
|
+
child_map: {
|
|
21132
|
+
// department -> team (department_contains_team) is the first level; team ->
|
|
21133
|
+
// team (team_contains_team, 0.17.2) is the second, so a sub-team nested one
|
|
21134
|
+
// level deeper than department_contains_team renders under its parent team.
|
|
21135
|
+
// Self-nesting: the assembler's `seen` set terminates a team -> team cycle
|
|
21136
|
+
// for free (a team met again becomes a shared reference).
|
|
21137
|
+
department: [opt("team")],
|
|
21138
|
+
team: [opt("team")]
|
|
21139
|
+
},
|
|
21140
|
+
// Default to 3 tiers (department -> team -> sub-team); `depth` extends into
|
|
21141
|
+
// deeper team_contains_team nesting.
|
|
21142
|
+
natural_depth: 3
|
|
21038
21143
|
}
|
|
21039
21144
|
];
|
|
21040
21145
|
var UPG_TREE_PATTERNS_BY_ID = Object.fromEntries(
|
|
@@ -22817,25 +22922,34 @@ var STRATEGY_GUIDE = {
|
|
|
22817
22922
|
// entries are later additions appended in chronological-introduction
|
|
22818
22923
|
// order. Placement reflects the order in which they would naturally be
|
|
22819
22924
|
// authored after the canonical strategy spine.
|
|
22820
|
-
creation_sequence: ["product", "vision", "mission", "outcome", "objective", "key_result", "metric", "metric_quality_assessment", "strategic_theme", "strategic_pillar", "initiative", "capability", "value_stream", "assumption", "decision", "constraint"],
|
|
22925
|
+
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"],
|
|
22821
22926
|
patterns: [
|
|
22822
22927
|
{
|
|
22823
22928
|
name: "Strategic Cascade",
|
|
22824
22929
|
description: "Vision grounds mission, product pursues outcomes and targets objectives, objectives achieved through key results measured by metrics",
|
|
22825
22930
|
entity_types: ["vision", "mission", "outcome", "objective", "key_result", "metric"],
|
|
22826
22931
|
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"]
|
|
22932
|
+
},
|
|
22933
|
+
{
|
|
22934
|
+
name: "Rendering the company spine",
|
|
22935
|
+
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.",
|
|
22936
|
+
entity_types: ["strategic_theme", "objective", "key_result", "metric"],
|
|
22937
|
+
edge_chain: ["strategic_theme_contains_objective", "objective_achieved_through_key_result", "key_result_quantified_by_metric"]
|
|
22827
22938
|
}
|
|
22828
22939
|
],
|
|
22829
22940
|
required_bridges: [
|
|
22830
22941
|
{ edge_type: "outcome_reveals_opportunity", target_domain: "discovery", when: "Outcomes should connect to the opportunities that deliver them" },
|
|
22831
22942
|
{ edge_type: "outcome_delivered_by_feature", target_domain: "product_spec", when: "Strategic outcomes should decompose into shipped features" },
|
|
22832
|
-
{ edge_type: "assumption_becomes_hypothesis", target_domain: "validation", when: "Risky assumptions should become testable hypotheses" }
|
|
22943
|
+
{ edge_type: "assumption_becomes_hypothesis", target_domain: "validation", when: "Risky assumptions should become testable hypotheses" },
|
|
22944
|
+
{ 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" },
|
|
22945
|
+
{ 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" }
|
|
22833
22946
|
],
|
|
22834
22947
|
anti_patterns: [
|
|
22835
22948
|
{ description: "Outcomes without metrics. Measurement is the signal an outcome happened." },
|
|
22836
22949
|
{ description: "Objectives without key results: an objective without measurement is a wish" },
|
|
22837
22950
|
{ description: "Too many strategic themes: focus beats breadth, aim for 2-4 active themes" },
|
|
22838
|
-
{ 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)." }
|
|
22951
|
+
{ 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)." },
|
|
22952
|
+
{ 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." }
|
|
22839
22953
|
]
|
|
22840
22954
|
};
|
|
22841
22955
|
var PRODUCT_SPEC_GUIDE = {
|
|
@@ -26888,6 +27002,10 @@ var UPG_REGIONS = [
|
|
|
26888
27002
|
type: "assumption",
|
|
26889
27003
|
role: "leaf"
|
|
26890
27004
|
},
|
|
27005
|
+
{
|
|
27006
|
+
type: "strategic_question",
|
|
27007
|
+
role: "leaf"
|
|
27008
|
+
},
|
|
26891
27009
|
{
|
|
26892
27010
|
type: "constraint",
|
|
26893
27011
|
role: "leaf"
|
|
@@ -26913,6 +27031,8 @@ var UPG_REGIONS = [
|
|
|
26913
27031
|
"strategic_pillar_decided_via_decision",
|
|
26914
27032
|
"strategic_theme_pursues_initiative",
|
|
26915
27033
|
"initiative_assumes_assumption",
|
|
27034
|
+
"objective_raises_strategic_question",
|
|
27035
|
+
"initiative_raises_strategic_question",
|
|
26916
27036
|
"initiative_drives_outcome",
|
|
26917
27037
|
"objective_achieved_through_key_result",
|
|
26918
27038
|
"objective_measured_by_metric",
|
|
@@ -29597,7 +29717,7 @@ function isCanonical(text) {
|
|
|
29597
29717
|
}
|
|
29598
29718
|
|
|
29599
29719
|
// src/index.ts
|
|
29600
|
-
var UPG_VERSION = "0.17.
|
|
29720
|
+
var UPG_VERSION = "0.17.4";
|
|
29601
29721
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
29602
29722
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
29603
29723
|
var UPG_TYPES = getTypes();
|
|
@@ -29670,6 +29790,7 @@ export {
|
|
|
29670
29790
|
COVERAGE_ANTI_PATTERNS,
|
|
29671
29791
|
DEFAULT_ENTITY_EMOJI,
|
|
29672
29792
|
DEFERRED_PROPOSED_BY_CONTRACT,
|
|
29793
|
+
DEFER_EDGE_PROPERTY_SCHEMA,
|
|
29673
29794
|
DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK,
|
|
29674
29795
|
ENGINEERING_PLATFORM_PLAYBOOK,
|
|
29675
29796
|
ENTITY_EMOJI,
|
|
@@ -29699,6 +29820,9 @@ export {
|
|
|
29699
29820
|
UPG_CONTAINMENT_FREE_TYPES,
|
|
29700
29821
|
UPG_COUNT_BENCHMARKS,
|
|
29701
29822
|
UPG_CROSS_EDGE_TYPES,
|
|
29823
|
+
UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES,
|
|
29824
|
+
UPG_CROSS_ONLY_EDGE_TYPES,
|
|
29825
|
+
UPG_DELIBERATE_ONLY_EDGE_TYPES,
|
|
29702
29826
|
UPG_DEPRECATED_TYPES,
|
|
29703
29827
|
UPG_DOMAINS,
|
|
29704
29828
|
UPG_DOMAIN_ACTIVATION,
|
|
@@ -29829,6 +29953,8 @@ export {
|
|
|
29829
29953
|
isCanonical,
|
|
29830
29954
|
isCanonicalProductStage,
|
|
29831
29955
|
isContainmentFreeType,
|
|
29956
|
+
isCrossProductEligible,
|
|
29957
|
+
isDeliberateOnlyEdge,
|
|
29832
29958
|
isDeprecatedType,
|
|
29833
29959
|
isDomainGuideStep,
|
|
29834
29960
|
isEntitySequenceStep,
|