@unified-product-graph/mcp-server 0.8.6 → 0.8.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7923,7 +7923,6 @@ function migrateStatusValue(entityType, currentStatus) {
7923
7923
  if (!typeMap) return null;
7924
7924
  return typeMap[currentStatus] ?? null;
7925
7925
  }
7926
- var crossProductEdgeTypeSet = new Set(UPG_CROSS_EDGE_TYPES);
7927
7926
  var UPG_PROPERTY_SCHEMA = {
7928
7927
  // A11yAnnotationProperties: Accessibility annotation.
7929
7928
  a11y_annotation: {
@@ -11297,31 +11296,37 @@ var UPG_FRAMEWORKS = [
11297
11296
  "slots": [
11298
11297
  {
11299
11298
  "label": "Customer Jobs",
11299
+ "role": "customer_job",
11300
11300
  "entityTypeId": "job",
11301
11301
  "description": "Place job entities in the Customer Jobs position of the matrix"
11302
11302
  },
11303
11303
  {
11304
11304
  "label": "Pains",
11305
+ "role": "pain",
11305
11306
  "entityTypeId": "need",
11306
11307
  "description": "Place need entities in the Pains position of the matrix"
11307
11308
  },
11308
11309
  {
11309
11310
  "label": "Gains",
11311
+ "role": "gain",
11310
11312
  "entityTypeId": "desired_outcome",
11311
11313
  "description": "Place desired outcome entities in the Gains position of the matrix"
11312
11314
  },
11313
11315
  {
11314
11316
  "label": "Products & Services",
11317
+ "role": "product_or_service",
11315
11318
  "entityTypeId": "feature",
11316
11319
  "description": "Place feature entities in the Products & Services position of the matrix"
11317
11320
  },
11318
11321
  {
11319
11322
  "label": "Pain Relievers",
11323
+ "role": "pain_reliever",
11320
11324
  "entityTypeId": "feature",
11321
11325
  "description": "Place feature entities in the Pain Relievers position of the matrix"
11322
11326
  },
11323
11327
  {
11324
11328
  "label": "Gain Creators",
11329
+ "role": "gain_creator",
11325
11330
  "entityTypeId": "feature",
11326
11331
  "description": "Place feature entities in the Gain Creators position of the matrix"
11327
11332
  }
@@ -11950,26 +11955,31 @@ var UPG_FRAMEWORKS = [
11950
11955
  "slots": [
11951
11956
  {
11952
11957
  "label": "Competitive Rivalry",
11958
+ "role": "competitive_rivalry",
11953
11959
  "entityTypeId": "competitor",
11954
11960
  "description": "Intensity of competition among existing players"
11955
11961
  },
11956
11962
  {
11957
11963
  "label": "Threat of New Entrants",
11964
+ "role": "new_entrants",
11958
11965
  "entityTypeId": "competitor",
11959
11966
  "description": "How easy is it for new competitors to enter?"
11960
11967
  },
11961
11968
  {
11962
11969
  "label": "Threat of Substitutes",
11970
+ "role": "substitutes",
11963
11971
  "entityTypeId": "competitor",
11964
11972
  "description": "Can customers switch to alternatives?"
11965
11973
  },
11966
11974
  {
11967
11975
  "label": "Buyer Power",
11976
+ "role": "buyer_power",
11968
11977
  "entityTypeId": "persona",
11969
11978
  "description": "How much leverage do buyers have?"
11970
11979
  },
11971
11980
  {
11972
11981
  "label": "Supplier Power",
11982
+ "role": "supplier_power",
11973
11983
  "entityTypeId": "persona",
11974
11984
  "description": "How much leverage do suppliers have?"
11975
11985
  }
@@ -12137,31 +12147,37 @@ var UPG_FRAMEWORKS = [
12137
12147
  "slots": [
12138
12148
  {
12139
12149
  "label": "Inbound Logistics",
12150
+ "role": "inbound_logistics",
12140
12151
  "entityTypeId": "key_activity",
12141
12152
  "description": "Inbound Logistics phase: key activity entities move through this stage"
12142
12153
  },
12143
12154
  {
12144
12155
  "label": "Operations",
12156
+ "role": "operations",
12145
12157
  "entityTypeId": "key_activity",
12146
12158
  "description": "Operations phase: key activity entities move through this stage"
12147
12159
  },
12148
12160
  {
12149
12161
  "label": "Outbound Logistics",
12162
+ "role": "outbound_logistics",
12150
12163
  "entityTypeId": "key_activity",
12151
12164
  "description": "Outbound Logistics phase: key activity entities move through this stage"
12152
12165
  },
12153
12166
  {
12154
12167
  "label": "Marketing & Sales",
12168
+ "role": "marketing_and_sales",
12155
12169
  "entityTypeId": "key_activity",
12156
12170
  "description": "Marketing & Sales phase: key activity entities move through this stage"
12157
12171
  },
12158
12172
  {
12159
12173
  "label": "Service",
12174
+ "role": "service",
12160
12175
  "entityTypeId": "key_activity",
12161
12176
  "description": "Service phase: key activity entities move through this stage"
12162
12177
  },
12163
12178
  {
12164
12179
  "label": "Support Activities",
12180
+ "role": "support_activity",
12165
12181
  "entityTypeId": "capability",
12166
12182
  "description": "Support Activities phase: capability entities move through this stage"
12167
12183
  }
@@ -12232,26 +12248,31 @@ var UPG_FRAMEWORKS = [
12232
12248
  "slots": [
12233
12249
  {
12234
12250
  "label": "Portfolio",
12251
+ "role": "portfolio",
12235
12252
  "entityTypeId": "portfolio",
12236
12253
  "description": "Innovation portfolio balanced across three horizons: core performance, emerging growth, and future creation"
12237
12254
  },
12238
12255
  {
12239
12256
  "label": "Product",
12257
+ "role": "product",
12240
12258
  "entityTypeId": "product",
12241
12259
  "description": "Product or business unit assigned to a horizon: H1 (defend and extend), H2 (build), or H3 (seed and explore)"
12242
12260
  },
12243
12261
  {
12244
12262
  "label": "Initiative",
12263
+ "role": "initiative",
12245
12264
  "entityTypeId": "portfolio",
12246
12265
  "description": "Growth initiative positioned in a horizon, with appropriate funding model, governance, and success metrics"
12247
12266
  },
12248
12267
  {
12249
12268
  "label": "Product Area",
12269
+ "role": "product_area",
12250
12270
  "entityTypeId": "product_area",
12251
12271
  "description": "Product area representing a horizon: core products (H1), adjacent expansions (H2), or experimental ventures (H3)"
12252
12272
  },
12253
12273
  {
12254
12274
  "label": "Capability",
12275
+ "role": "capability",
12255
12276
  "entityTypeId": "capability",
12256
12277
  "description": "Capability needed to execute across horizons: H1 needs efficiency, H2 needs scaling, H3 needs discovery"
12257
12278
  }
@@ -12315,7 +12336,7 @@ var UPG_FRAMEWORKS = [
12315
12336
  ],
12316
12337
  "name": "RICE Scoring",
12317
12338
  "version": "1.0.0",
12318
- "description": "Score features and opportunities by Reach, Impact, Confidence, and Effort to produce a ranked priority list.",
12339
+ "description": "Score features, opportunities, and needs by Reach, Impact, Confidence, and Effort to produce a ranked priority list.",
12319
12340
  "category": "prioritization",
12320
12341
  "origin": {
12321
12342
  "type": "practitioner",
@@ -12333,7 +12354,7 @@ var UPG_FRAMEWORKS = [
12333
12354
  {
12334
12355
  "label": "Items to score",
12335
12356
  "entityTypeId": "feature",
12336
- "description": "Features, opportunities, or solutions being evaluated"
12357
+ "description": "Features, opportunities, or needs being evaluated"
12337
12358
  },
12338
12359
  {
12339
12360
  "label": "Opportunities to score",
@@ -12499,7 +12520,60 @@ var UPG_FRAMEWORKS = [
12499
12520
  "label": "RICE Score",
12500
12521
  "format": "number"
12501
12522
  }
12502
- ]
12523
+ ],
12524
+ "scoring_lens": {
12525
+ "applies_to": [
12526
+ "feature",
12527
+ "opportunity",
12528
+ "need"
12529
+ ],
12530
+ "inputs": [
12531
+ {
12532
+ "property": "reach",
12533
+ "type": "assessment",
12534
+ "scale_id": "reach_5",
12535
+ "required": true,
12536
+ "scope": "framework",
12537
+ "label": "Reach",
12538
+ "description": "How many users will this impact per quarter?"
12539
+ },
12540
+ {
12541
+ "property": "impact",
12542
+ "type": "assessment",
12543
+ "scale_id": "impact_5",
12544
+ "required": true,
12545
+ "scope": "framework",
12546
+ "label": "Impact",
12547
+ "description": "How much will this impact each user, on the impact scale?"
12548
+ },
12549
+ {
12550
+ "property": "confidence",
12551
+ "type": "assessment",
12552
+ "scale_id": "confidence_5",
12553
+ "required": true,
12554
+ "scope": "framework",
12555
+ "label": "Confidence",
12556
+ "description": "How confident are you in the reach, impact, and effort estimates?"
12557
+ },
12558
+ {
12559
+ "property": "effort",
12560
+ "type": "assessment",
12561
+ "scale_id": "effort_5",
12562
+ "required": true,
12563
+ "scope": "framework",
12564
+ "label": "Effort",
12565
+ "description": "How much work is required to build and ship this, on the effort scale?"
12566
+ }
12567
+ ],
12568
+ "computed": [
12569
+ {
12570
+ "property": "rice_score",
12571
+ "expression": "(reach * impact * confidence) / effort",
12572
+ "label": "RICE Score",
12573
+ "format": "number"
12574
+ }
12575
+ ]
12576
+ }
12503
12577
  },
12504
12578
  "structure": {
12505
12579
  "pattern": "table"
@@ -12678,21 +12752,25 @@ var UPG_FRAMEWORKS = [
12678
12752
  "slots": [
12679
12753
  {
12680
12754
  "label": "Must-haves",
12755
+ "role": "must_have",
12681
12756
  "entityTypeId": "feature",
12682
12757
  "description": "Expected features: absence causes dissatisfaction"
12683
12758
  },
12684
12759
  {
12685
12760
  "label": "Performance",
12761
+ "role": "performance",
12686
12762
  "entityTypeId": "feature",
12687
12763
  "description": "More is better: linear satisfaction increase"
12688
12764
  },
12689
12765
  {
12690
12766
  "label": "Delighters",
12767
+ "role": "delighter",
12691
12768
  "entityTypeId": "feature",
12692
12769
  "description": "Unexpected features: presence creates delight"
12693
12770
  },
12694
12771
  {
12695
12772
  "label": "Indifferent",
12773
+ "role": "indifferent",
12696
12774
  "entityTypeId": "feature",
12697
12775
  "description": "Features users don't care about either way"
12698
12776
  }
@@ -12701,7 +12779,7 @@ var UPG_FRAMEWORKS = [
12701
12779
  "entity_types": [
12702
12780
  {
12703
12781
  "type": "feature",
12704
- "role": "item"
12782
+ "role": "scored_item"
12705
12783
  }
12706
12784
  ],
12707
12785
  "required_properties": {
@@ -12785,7 +12863,90 @@ var UPG_FRAMEWORKS = [
12785
12863
  "label": "Dissatisfaction Coefficient",
12786
12864
  "format": "number"
12787
12865
  }
12788
- ]
12866
+ ],
12867
+ "scoring_lens": {
12868
+ "applies_to": [
12869
+ "feature"
12870
+ ],
12871
+ "inputs": [
12872
+ {
12873
+ "property": "functional_response",
12874
+ "type": "enum",
12875
+ "required": true,
12876
+ "scope": "framework",
12877
+ "label": "Functional Response",
12878
+ "description": "How users feel when the feature IS present",
12879
+ "enum_values": [
12880
+ "i_like_it",
12881
+ "i_expect_it",
12882
+ "i_am_neutral",
12883
+ "i_can_tolerate_it",
12884
+ "i_dislike_it"
12885
+ ]
12886
+ },
12887
+ {
12888
+ "property": "dysfunctional_response",
12889
+ "type": "enum",
12890
+ "required": true,
12891
+ "scope": "framework",
12892
+ "label": "Dysfunctional Response",
12893
+ "description": "How users feel when the feature IS NOT present",
12894
+ "enum_values": [
12895
+ "i_like_it",
12896
+ "i_expect_it",
12897
+ "i_am_neutral",
12898
+ "i_can_tolerate_it",
12899
+ "i_dislike_it"
12900
+ ]
12901
+ },
12902
+ {
12903
+ "property": "delighter_count",
12904
+ "type": "number",
12905
+ "required": false,
12906
+ "scope": "framework",
12907
+ "label": "Delighter classifications",
12908
+ "description": "Count of survey responses classifying this feature as a delighter (attractive)"
12909
+ },
12910
+ {
12911
+ "property": "performance_count",
12912
+ "type": "number",
12913
+ "required": false,
12914
+ "scope": "framework",
12915
+ "label": "Performance classifications",
12916
+ "description": "Count of survey responses classifying this feature as performance (one-dimensional)"
12917
+ },
12918
+ {
12919
+ "property": "must_be_count",
12920
+ "type": "number",
12921
+ "required": false,
12922
+ "scope": "framework",
12923
+ "label": "Must-be classifications",
12924
+ "description": "Count of survey responses classifying this feature as must-be (basic)"
12925
+ },
12926
+ {
12927
+ "property": "indifferent_count",
12928
+ "type": "number",
12929
+ "required": false,
12930
+ "scope": "framework",
12931
+ "label": "Indifferent classifications",
12932
+ "description": "Count of survey responses classifying this feature as indifferent"
12933
+ }
12934
+ ],
12935
+ "computed": [
12936
+ {
12937
+ "property": "satisfaction_coefficient",
12938
+ "expression": "(delighter_count + performance_count) / (delighter_count + performance_count + must_be_count + indifferent_count)",
12939
+ "label": "Satisfaction Coefficient",
12940
+ "format": "number"
12941
+ },
12942
+ {
12943
+ "property": "dissatisfaction_coefficient",
12944
+ "expression": "(must_be_count + performance_count) / (delighter_count + performance_count + must_be_count + indifferent_count) * -1",
12945
+ "label": "Dissatisfaction Coefficient",
12946
+ "format": "number"
12947
+ }
12948
+ ]
12949
+ }
12789
12950
  },
12790
12951
  "structure": {
12791
12952
  "pattern": "matrix"
@@ -12840,16 +13001,19 @@ var UPG_FRAMEWORKS = [
12840
13001
  "slots": [
12841
13002
  {
12842
13003
  "label": "Now",
13004
+ "role": "now",
12843
13005
  "entityTypeId": "feature",
12844
13006
  "description": "Committed work in progress"
12845
13007
  },
12846
13008
  {
12847
13009
  "label": "Next",
13010
+ "role": "next",
12848
13011
  "entityTypeId": "feature",
12849
13012
  "description": "High-confidence upcoming work"
12850
13013
  },
12851
13014
  {
12852
13015
  "label": "Later",
13016
+ "role": "later",
12853
13017
  "entityTypeId": "initiative",
12854
13018
  "description": "Exploratory, needs more discovery"
12855
13019
  }
@@ -13365,26 +13529,31 @@ var UPG_FRAMEWORKS = [
13365
13529
  "slots": [
13366
13530
  {
13367
13531
  "label": "Atoms",
13532
+ "role": "atom",
13368
13533
  "entityTypeId": "design_component",
13369
13534
  "description": "Atoms: design component entities for this dimension of the framework"
13370
13535
  },
13371
13536
  {
13372
13537
  "label": "Molecules",
13538
+ "role": "molecule",
13373
13539
  "entityTypeId": "design_component",
13374
13540
  "description": "Molecules: design token entities for this dimension of the framework"
13375
13541
  },
13376
13542
  {
13377
13543
  "label": "Organisms",
13544
+ "role": "organism",
13378
13545
  "entityTypeId": "design_pattern",
13379
13546
  "description": "Organisms: design pattern entities for this dimension of the framework"
13380
13547
  },
13381
13548
  {
13382
13549
  "label": "Templates",
13550
+ "role": "template",
13383
13551
  "entityTypeId": "wireframe",
13384
13552
  "description": "Templates: design system entities for this dimension of the framework"
13385
13553
  },
13386
13554
  {
13387
13555
  "label": "Pages",
13556
+ "role": "page",
13388
13557
  "entityTypeId": "screen",
13389
13558
  "description": "Pages: screen entities for this dimension of the framework"
13390
13559
  }
@@ -14049,26 +14218,31 @@ var UPG_FRAMEWORKS = [
14049
14218
  "slots": [
14050
14219
  {
14051
14220
  "label": "Outer Ring",
14221
+ "role": "outer_ring",
14052
14222
  "entityTypeId": "acquisition_channel",
14053
14223
  "description": "All 19 traction channels brainstormed"
14054
14224
  },
14055
14225
  {
14056
14226
  "label": "Middle Ring",
14227
+ "role": "middle_ring",
14057
14228
  "entityTypeId": "acquisition_channel",
14058
14229
  "description": "Top 6 channels worth testing"
14059
14230
  },
14060
14231
  {
14061
14232
  "label": "Inner Ring",
14233
+ "role": "inner_ring",
14062
14234
  "entityTypeId": "acquisition_channel",
14063
14235
  "description": "Top 3 channels to focus on"
14064
14236
  },
14065
14237
  {
14066
14238
  "label": "Traction Test",
14239
+ "role": "traction_test",
14067
14240
  "entityTypeId": "growth_campaign",
14068
14241
  "description": "Cheap test for each channel"
14069
14242
  },
14070
14243
  {
14071
14244
  "label": "Bullseye Channel",
14245
+ "role": "bullseye_channel",
14072
14246
  "entityTypeId": "acquisition_channel",
14073
14247
  "description": "The single best-performing channel"
14074
14248
  }
@@ -14138,26 +14312,31 @@ var UPG_FRAMEWORKS = [
14138
14312
  "slots": [
14139
14313
  {
14140
14314
  "label": "Free Entry",
14315
+ "role": "free_entry",
14141
14316
  "entityTypeId": "gtm_strategy",
14142
14317
  "description": "How users access the product for free"
14143
14318
  },
14144
14319
  {
14145
14320
  "label": "Aha Moment",
14321
+ "role": "aha_moment",
14146
14322
  "entityTypeId": "gtm_strategy",
14147
14323
  "description": "First experience of core value"
14148
14324
  },
14149
14325
  {
14150
14326
  "label": "Expansion Motion",
14327
+ "role": "expansion_motion",
14151
14328
  "entityTypeId": "sales_motion",
14152
14329
  "description": "How usage spreads within accounts"
14153
14330
  },
14154
14331
  {
14155
14332
  "label": "Monetisation Trigger",
14333
+ "role": "monetisation_trigger",
14156
14334
  "entityTypeId": "gtm_strategy",
14157
14335
  "description": "When and how to convert to paid"
14158
14336
  },
14159
14337
  {
14160
14338
  "label": "Metric",
14339
+ "role": "metric",
14161
14340
  "entityTypeId": "metric",
14162
14341
  "description": "Key metric driving the PLG motion"
14163
14342
  }
@@ -14232,21 +14411,25 @@ var UPG_FRAMEWORKS = [
14232
14411
  "slots": [
14233
14412
  {
14234
14413
  "label": "Objective",
14414
+ "role": "objective",
14235
14415
  "entityTypeId": "objective",
14236
14416
  "description": "Qualitative, inspiring goal"
14237
14417
  },
14238
14418
  {
14239
14419
  "label": "Key Result 1",
14420
+ "role": "key_result",
14240
14421
  "entityTypeId": "key_result",
14241
14422
  "description": "Measurable outcome proving progress"
14242
14423
  },
14243
14424
  {
14244
14425
  "label": "Key Result 2",
14426
+ "role": "key_result",
14245
14427
  "entityTypeId": "key_result",
14246
14428
  "description": "Measurable outcome proving progress"
14247
14429
  },
14248
14430
  {
14249
14431
  "label": "Initiatives",
14432
+ "role": "initiative",
14250
14433
  "entityTypeId": "initiative",
14251
14434
  "description": "Work streams that drive key results"
14252
14435
  }
@@ -14320,26 +14503,31 @@ var UPG_FRAMEWORKS = [
14320
14503
  "slots": [
14321
14504
  {
14322
14505
  "label": "Activity",
14506
+ "role": "activity",
14323
14507
  "entityTypeId": "key_activity",
14324
14508
  "description": "Place persona entities in the Activity position of the matrix"
14325
14509
  },
14326
14510
  {
14327
14511
  "label": "Responsible",
14512
+ "role": "responsible",
14328
14513
  "entityTypeId": "role",
14329
14514
  "description": "Does the work"
14330
14515
  },
14331
14516
  {
14332
14517
  "label": "Accountable",
14518
+ "role": "accountable",
14333
14519
  "entityTypeId": "role",
14334
14520
  "description": "Makes the final call"
14335
14521
  },
14336
14522
  {
14337
14523
  "label": "Consulted",
14524
+ "role": "consulted",
14338
14525
  "entityTypeId": "role",
14339
14526
  "description": "Gives input"
14340
14527
  },
14341
14528
  {
14342
14529
  "label": "Informed",
14530
+ "role": "informed",
14343
14531
  "entityTypeId": "role",
14344
14532
  "description": "Kept in the loop"
14345
14533
  }
@@ -14413,21 +14601,25 @@ var UPG_FRAMEWORKS = [
14413
14601
  "slots": [
14414
14602
  {
14415
14603
  "label": "What Went Well",
14604
+ "role": "went_well",
14416
14605
  "entityTypeId": "outcome",
14417
14606
  "description": "Practices to continue"
14418
14607
  },
14419
14608
  {
14420
14609
  "label": "What Didn't Go Well",
14610
+ "role": "went_poorly",
14421
14611
  "entityTypeId": "need",
14422
14612
  "description": "Issues to address"
14423
14613
  },
14424
14614
  {
14425
14615
  "label": "Action Items",
14616
+ "role": "action_item",
14426
14617
  "entityTypeId": "learning",
14427
14618
  "description": "Changes for next iteration"
14428
14619
  },
14429
14620
  {
14430
14621
  "label": "Learnings",
14622
+ "role": "learning",
14431
14623
  "entityTypeId": "learning",
14432
14624
  "description": "Insights to carry forward"
14433
14625
  }
@@ -14624,7 +14816,7 @@ var UPG_FRAMEWORKS = [
14624
14816
  "entity_types": [
14625
14817
  {
14626
14818
  "type": "team",
14627
- "role": "scored_item"
14819
+ "role": "item"
14628
14820
  },
14629
14821
  {
14630
14822
  "type": "retrospective",
@@ -14788,7 +14980,36 @@ var UPG_FRAMEWORKS = [
14788
14980
  "label": "Severity",
14789
14981
  "format": "number"
14790
14982
  }
14791
- ]
14983
+ ],
14984
+ "scoring_lens": {
14985
+ "applies_to": [
14986
+ "risk"
14987
+ ],
14988
+ "inputs": [
14989
+ {
14990
+ "property": "probability",
14991
+ "type": "number",
14992
+ "required": true,
14993
+ "label": "Probability",
14994
+ "description": "Likelihood the risk materialises (risk.probability assessment)"
14995
+ },
14996
+ {
14997
+ "property": "impact",
14998
+ "type": "number",
14999
+ "required": true,
15000
+ "label": "Impact",
15001
+ "description": "Consequence severity if the risk materialises (risk.impact assessment)"
15002
+ }
15003
+ ],
15004
+ "computed": [
15005
+ {
15006
+ "property": "severity",
15007
+ "expression": "probability * impact",
15008
+ "label": "Severity",
15009
+ "format": "number"
15010
+ }
15011
+ ]
15012
+ }
14792
15013
  },
14793
15014
  "structure": {
14794
15015
  "pattern": "table"
@@ -14864,31 +15085,37 @@ var UPG_FRAMEWORKS = [
14864
15085
  "slots": [
14865
15086
  {
14866
15087
  "label": "Items to score",
15088
+ "role": "candidate",
14867
15089
  "entityTypeId": "feature",
14868
15090
  "description": "Features or experiments being evaluated"
14869
15091
  },
14870
15092
  {
14871
15093
  "label": "Impact",
15094
+ "role": "impact",
14872
15095
  "entityTypeId": "outcome",
14873
15096
  "description": "How much will this move the needle?"
14874
15097
  },
14875
15098
  {
14876
15099
  "label": "Confidence",
15100
+ "role": "confidence",
14877
15101
  "entityTypeId": "assumption",
14878
15102
  "description": "How sure are we about the impact?"
14879
15103
  },
14880
15104
  {
14881
15105
  "label": "Ease",
15106
+ "role": "ease",
14882
15107
  "entityTypeId": "feature",
14883
15108
  "description": "How easy is this to implement?"
14884
15109
  },
14885
15110
  {
14886
15111
  "label": "Opportunities to score",
15112
+ "role": "candidate",
14887
15113
  "entityTypeId": "opportunity",
14888
15114
  "description": "Opportunities scored on the same ICE Scoring inputs as features."
14889
15115
  },
14890
15116
  {
14891
15117
  "label": "Needs to score",
15118
+ "role": "candidate",
14892
15119
  "entityTypeId": "need",
14893
15120
  "description": "Needs scored on the same ICE Scoring inputs as features."
14894
15121
  }
@@ -15018,7 +15245,48 @@ var UPG_FRAMEWORKS = [
15018
15245
  "label": "ICE Score",
15019
15246
  "format": "number"
15020
15247
  }
15021
- ]
15248
+ ],
15249
+ "scoring_lens": {
15250
+ "applies_to": [
15251
+ "feature",
15252
+ "opportunity",
15253
+ "need"
15254
+ ],
15255
+ "inputs": [
15256
+ {
15257
+ "property": "impact",
15258
+ "type": "number",
15259
+ "required": true,
15260
+ "scope": "framework",
15261
+ "label": "Impact",
15262
+ "description": "Expected impact on the target metric (1-10)"
15263
+ },
15264
+ {
15265
+ "property": "confidence",
15266
+ "type": "number",
15267
+ "required": true,
15268
+ "scope": "framework",
15269
+ "label": "Confidence",
15270
+ "description": "Confidence in the impact estimate (1-10)"
15271
+ },
15272
+ {
15273
+ "property": "ease",
15274
+ "type": "number",
15275
+ "required": true,
15276
+ "scope": "framework",
15277
+ "label": "Ease",
15278
+ "description": "Ease of implementation (1-10)"
15279
+ }
15280
+ ],
15281
+ "computed": [
15282
+ {
15283
+ "property": "ice_score",
15284
+ "expression": "impact * confidence * ease",
15285
+ "label": "ICE Score",
15286
+ "format": "number"
15287
+ }
15288
+ ]
15289
+ }
15022
15290
  },
15023
15291
  "structure": {
15024
15292
  "pattern": "table"
@@ -15098,31 +15366,37 @@ var UPG_FRAMEWORKS = [
15098
15366
  "slots": [
15099
15367
  {
15100
15368
  "label": "Backlog Items",
15369
+ "role": "candidate",
15101
15370
  "entityTypeId": "feature",
15102
15371
  "description": "Backlog Items: feature entries to evaluate"
15103
15372
  },
15104
15373
  {
15105
15374
  "label": "User/Business Value",
15375
+ "role": "user_business_value",
15106
15376
  "entityTypeId": "metric",
15107
15377
  "description": "User/Business Value: metric entries to evaluate"
15108
15378
  },
15109
15379
  {
15110
15380
  "label": "Time Criticality",
15381
+ "role": "time_criticality",
15111
15382
  "entityTypeId": "metric",
15112
15383
  "description": "How much value decays if delivery is delayed (deadlines, competition, seasonal windows)"
15113
15384
  },
15114
15385
  {
15115
15386
  "label": "Risk Reduction / Opportunity Enablement",
15387
+ "role": "risk_reduction",
15116
15388
  "entityTypeId": "metric",
15117
15389
  "description": "Risk Reduction / Opportunity Enablement: metric entries to evaluate"
15118
15390
  },
15119
15391
  {
15120
15392
  "label": "Job Size",
15393
+ "role": "job_size",
15121
15394
  "entityTypeId": "metric",
15122
15395
  "description": "Estimated effort (story points, t-shirt size, or person-weeks)"
15123
15396
  },
15124
15397
  {
15125
15398
  "label": "Opportunities to score",
15399
+ "role": "candidate",
15126
15400
  "entityTypeId": "opportunity",
15127
15401
  "description": "Opportunities scored on the same WSJF (Weighted Shortest Job First) inputs as features."
15128
15402
  }
@@ -15227,7 +15501,55 @@ var UPG_FRAMEWORKS = [
15227
15501
  "label": "WSJF Score",
15228
15502
  "format": "number"
15229
15503
  }
15230
- ]
15504
+ ],
15505
+ "scoring_lens": {
15506
+ "applies_to": [
15507
+ "feature",
15508
+ "opportunity"
15509
+ ],
15510
+ "inputs": [
15511
+ {
15512
+ "property": "user_value",
15513
+ "type": "number",
15514
+ "required": true,
15515
+ "scope": "framework",
15516
+ "label": "User/Business Value",
15517
+ "description": "Relative value to users and the business if delivered"
15518
+ },
15519
+ {
15520
+ "property": "time_criticality",
15521
+ "type": "number",
15522
+ "required": true,
15523
+ "scope": "framework",
15524
+ "label": "Time Criticality",
15525
+ "description": "How much value decays if delivery is delayed (deadlines, competition, seasonal windows)"
15526
+ },
15527
+ {
15528
+ "property": "risk_reduction",
15529
+ "type": "number",
15530
+ "required": true,
15531
+ "scope": "framework",
15532
+ "label": "Risk Reduction / Opportunity Enablement",
15533
+ "description": "Value from reducing risk or enabling future opportunities"
15534
+ },
15535
+ {
15536
+ "property": "job_size",
15537
+ "type": "number",
15538
+ "required": true,
15539
+ "scope": "framework",
15540
+ "label": "Job Size",
15541
+ "description": "Estimated effort (story points, t-shirt size, or person-weeks)"
15542
+ }
15543
+ ],
15544
+ "computed": [
15545
+ {
15546
+ "property": "wsjf_score",
15547
+ "expression": "(user_value + time_criticality + risk_reduction) / job_size",
15548
+ "label": "WSJF Score",
15549
+ "format": "number"
15550
+ }
15551
+ ]
15552
+ }
15231
15553
  },
15232
15554
  "structure": {
15233
15555
  "pattern": "table"
@@ -15300,7 +15622,7 @@ var UPG_FRAMEWORKS = [
15300
15622
  ],
15301
15623
  "name": "Cost of Delay",
15302
15624
  "version": "1.0.0",
15303
- "description": "Quantify the economic cost of not shipping a feature to drive priority decisions. Combines urgency with value.",
15625
+ "description": "Quantify the economic cost of not shipping a feature or opportunity to drive priority decisions. Combines urgency with value.",
15304
15626
  "category": "prioritization",
15305
15627
  "origin": {
15306
15628
  "type": "practitioner",
@@ -15416,7 +15738,39 @@ var UPG_FRAMEWORKS = [
15416
15738
  "label": "WSJF Score",
15417
15739
  "format": "number"
15418
15740
  }
15419
- ]
15741
+ ],
15742
+ "scoring_lens": {
15743
+ "applies_to": [
15744
+ "feature",
15745
+ "opportunity"
15746
+ ],
15747
+ "inputs": [
15748
+ {
15749
+ "property": "cost_of_delay",
15750
+ "type": "number",
15751
+ "required": true,
15752
+ "scope": "framework",
15753
+ "label": "Cost of Delay",
15754
+ "description": "Weekly revenue impact of not shipping"
15755
+ },
15756
+ {
15757
+ "property": "job_size",
15758
+ "type": "number",
15759
+ "required": true,
15760
+ "scope": "framework",
15761
+ "label": "Job Size",
15762
+ "description": "Weeks of development effort"
15763
+ }
15764
+ ],
15765
+ "computed": [
15766
+ {
15767
+ "property": "wsjf_score",
15768
+ "expression": "cost_of_delay / job_size",
15769
+ "label": "WSJF Score",
15770
+ "format": "number"
15771
+ }
15772
+ ]
15773
+ }
15420
15774
  },
15421
15775
  "structure": {
15422
15776
  "pattern": "table"
@@ -15498,16 +15852,19 @@ var UPG_FRAMEWORKS = [
15498
15852
  "slots": [
15499
15853
  {
15500
15854
  "label": "Symptom",
15855
+ "role": "symptom",
15501
15856
  "entityTypeId": "need",
15502
15857
  "description": "The observed problem the analysis starts from."
15503
15858
  },
15504
15859
  {
15505
15860
  "label": "Why chain",
15861
+ "role": "why",
15506
15862
  "entityTypeId": "insight",
15507
15863
  "description": 'Each "why?" answer along the chain, typically five iterations deep.'
15508
15864
  },
15509
15865
  {
15510
15866
  "label": "Root cause",
15867
+ "role": "root_cause",
15511
15868
  "entityTypeId": "insight",
15512
15869
  "description": "The terminal answer at the bottom of the chain: the underlying cause to address."
15513
15870
  }
@@ -15852,16 +16209,19 @@ var UPG_FRAMEWORKS = [
15852
16209
  "slots": [
15853
16210
  {
15854
16211
  "label": "First-order move",
16212
+ "role": "first_order",
15855
16213
  "entityTypeId": "decision",
15856
16214
  "description": "The decision or move under consideration."
15857
16215
  },
15858
16216
  {
15859
16217
  "label": "Second-order consequences",
16218
+ "role": "second_order",
15860
16219
  "entityTypeId": "insight",
15861
16220
  "description": "Downstream effects that follow from the first-order move."
15862
16221
  },
15863
16222
  {
15864
16223
  "label": "Higher-order consequences",
16224
+ "role": "higher_order",
15865
16225
  "entityTypeId": "insight",
15866
16226
  "description": "Third-, fourth-, fifth-order ripples: second-order consequences of the second-order consequences."
15867
16227
  }
@@ -15920,6 +16280,7 @@ for (const fw of UPG_FRAMEWORKS) {
15920
16280
  if (!UPG_FRAMEWORKS_BY_CATEGORY[fw.category]) UPG_FRAMEWORKS_BY_CATEGORY[fw.category] = [];
15921
16281
  UPG_FRAMEWORKS_BY_CATEGORY[fw.category].push(fw);
15922
16282
  }
16283
+ var crossProductEdgeTypeSet = new Set(UPG_CROSS_EDGE_TYPES);
15923
16284
  var PRIORITY_LABELS = [
15924
16285
  // ── need (CONSOLIDATED: replaces pain_point + user_need) ─────────────────────
15925
16286
  {
@@ -24004,7 +24365,7 @@ function serializePortfolioWithHeader(doc, opts) {
24004
24365
  header.integrity = { algorithm: INTEGRITY_ALGORITHM, body: computeBodyChecksum(doc) };
24005
24366
  return JSON.stringify({ $upg: header, ...body }, null, 2) + "\n";
24006
24367
  }
24007
- var UPG_VERSION = "0.8.6";
24368
+ var UPG_VERSION = "0.8.7";
24008
24369
  var MARKDOWN_FORMAT_VERSION = "0.1";
24009
24370
  var UPG_TYPES = getTypes();
24010
24371
  var UPG_TYPES_SET = new Set(UPG_TYPES);
@@ -24714,12 +25075,13 @@ var listNodes = (args, ctx) => {
24714
25075
  };
24715
25076
  var getNode = (args, ctx) => {
24716
25077
  const { store } = ctx;
24717
- if (!args.node_id) return textError(`Missing required parameter: node_id`);
25078
+ const nodeId2 = args.node_id ?? args.id;
25079
+ if (!nodeId2) return textError(`Missing required parameter: node_id (alias: id)`);
24718
25080
  const result = getNodeLib(store, {
24719
- node_id: args.node_id,
25081
+ node_id: nodeId2,
24720
25082
  compact_edges: args.compact_edges ?? false
24721
25083
  });
24722
- if (!result) return textError(`Node not found: ${args.node_id}`);
25084
+ if (!result) return textError(`Node not found: ${nodeId2}`);
24723
25085
  const typed = result;
24724
25086
  if (typed.node.properties) {
24725
25087
  const { unknown_properties, warning } = checkUnknownProperties(typed.node.type, typed.node.properties);
@@ -26158,7 +26520,10 @@ var listLocalProducts = (_args, _ctx) => {
26158
26520
  };
26159
26521
  var switchProduct = async (args, ctx) => {
26160
26522
  const { store } = ctx;
26161
- const fileArg = args.file;
26523
+ const fileArg = args.file ?? args.product;
26524
+ if (typeof fileArg !== "string" || fileArg.length === 0) {
26525
+ return textError("Missing required parameter: file (alias: product). Pass a .upg path or a bare product name.");
26526
+ }
26162
26527
  let resolved = path3.resolve(fileArg);
26163
26528
  if (!fs.existsSync(resolved)) {
26164
26529
  const cwd = process.cwd();
@@ -26513,6 +26878,7 @@ var getEntitySchema = (args, _ctx) => {
26513
26878
  // src/tools/frameworks.ts
26514
26879
  import {
26515
26880
  applyFramework as applyFrameworkLib,
26881
+ applyFrameworkEnvelope,
26516
26882
  scoreEntity as scoreEntityLib
26517
26883
  } from "@unified-product-graph/sdk";
26518
26884
  var applyFramework = (args, ctx) => {
@@ -26528,18 +26894,7 @@ var applyFramework = (args, ctx) => {
26528
26894
  entity_ids: args.entity_ids ?? [],
26529
26895
  status: args.status
26530
26896
  });
26531
- return text(
26532
- JSON.stringify(
26533
- {
26534
- exercise_id: result.exercise.id,
26535
- exercise: result.exercise,
26536
- included: result.edges.map((e) => ({ edge_id: e.id, entity_id: e.target })),
26537
- warnings: result.warnings
26538
- },
26539
- null,
26540
- 2
26541
- )
26542
- );
26897
+ return text(JSON.stringify(applyFrameworkEnvelope(result), null, 2));
26543
26898
  } catch (err) {
26544
26899
  return textError(err.message);
26545
26900
  }
@@ -26966,9 +27321,11 @@ var validateGraph = (args, ctx) => {
26966
27321
  argsHint: `scope=${scope}, limit=${limit}`
26967
27322
  });
26968
27323
  if (guardOutcome.kind === "refuse") return guardOutcome.result;
26969
- const driftClean = skipDrift || summary.entity_drift === 0 && summary.edge_drift === 0 && summary.top_level_drift === 0 && summary.lifecycle_drift === 0 && summary.self_referential === 0 && summary.property_drift === 0 && edgeTypePairDrift.length === 0 && graphTopologySelfLoops.length === 0 && propertyTypeDrift.length === 0;
27324
+ const structurallyClean = summary.entity_drift === 0 && summary.edge_drift === 0 && summary.top_level_drift === 0 && summary.lifecycle_drift === 0 && summary.self_referential === 0 && summary.property_drift === 0 && edgeTypePairDrift.length === 0 && graphTopologySelfLoops.length === 0 && propertyTypeDrift.length === 0;
27325
+ const driftClean = skipDrift || structurallyClean;
26970
27326
  const antiPatternClean = skipAntiPatterns || (antiPatternViolations?.length ?? 0) === 0;
26971
27327
  const valid = driftClean && antiPatternClean;
27328
+ const structurallyValid = skipDrift ? void 0 : structurallyClean;
26972
27329
  let highCount = 0;
26973
27330
  let mediumCount = 0;
26974
27331
  let lowCount = 0;
@@ -26981,6 +27338,11 @@ var validateGraph = (args, ctx) => {
26981
27338
  }
26982
27339
  const response = {
26983
27340
  valid,
27341
+ // N4 (UPG QA 0.8.7): additive structural-conformance signal. true ⟺ every
27342
+ // drift class is 0, independent of anti-pattern health. Omitted when
27343
+ // `skip_drift` is true (structure was not assessed). A CI gate that wants
27344
+ // "is this graph spec-shaped?" should read this, not `valid`.
27345
+ ...structurallyValid !== void 0 ? { structurally_valid: structurallyValid } : {},
26984
27346
  summary: {
26985
27347
  ...summary,
26986
27348
  spec_version: UPG_VERSION,
@@ -27286,19 +27648,31 @@ var listFrameworks = (args) => {
27286
27648
  const slice = pool.slice(cursorOffset, cursorOffset + limit);
27287
27649
  const nextOffset = cursorOffset + slice.length;
27288
27650
  const nextCursor = nextOffset < total ? encodeCursor(nextOffset) : void 0;
27651
+ const frameworks = slice.map((f) => ({
27652
+ id: f.id,
27653
+ name: f.name,
27654
+ category: f.category,
27655
+ description: f.description,
27656
+ tags: f.tags,
27657
+ approach_ids: f.approach_ids,
27658
+ structure_pattern: f.structure?.pattern
27659
+ }));
27289
27660
  const body = {
27290
27661
  total,
27291
27662
  count: slice.length,
27292
- frameworks: slice
27663
+ frameworks
27293
27664
  };
27294
27665
  if (nextCursor) body.next_cursor = nextCursor;
27295
27666
  return text(JSON.stringify(body, null, 2));
27296
27667
  };
27297
27668
  var getFramework = (args) => {
27298
- const id = args.id;
27299
- if (!id) return textError("Missing required parameter: id");
27669
+ const id = args.id ?? args.framework_id;
27670
+ if (!id) return textError("Missing required parameter: id (alias: framework_id)");
27300
27671
  const framework = UPG_FRAMEWORKS_BY_ID[id];
27301
- if (!framework) return textError(`Unknown framework id: ${id}`);
27672
+ if (!framework)
27673
+ return textError(
27674
+ `Unknown framework id: "${id}". Pass a framework id from the catalog (e.g. 'moscow', 'rice-scoring', 'kano-model'). See list_frameworks for the full list.`
27675
+ );
27302
27676
  return text(JSON.stringify(framework, null, 2));
27303
27677
  };
27304
27678
  function buildEdgeEntries(filterSource, filterTarget) {
@@ -28264,7 +28638,8 @@ var TOOL_DEFINITIONS = [
28264
28638
  inputSchema: {
28265
28639
  type: "object",
28266
28640
  properties: {
28267
- node_id: { type: "string", description: "The node ID" },
28641
+ node_id: { type: "string", description: "The node ID. Alias: `id`." },
28642
+ id: { type: "string", description: "Alias for `node_id`." },
28268
28643
  compact_edges: { type: "boolean", description: "Omit source_title/target_title from edges (saves ~30% on edge-heavy nodes)" }
28269
28644
  },
28270
28645
  required: ["node_id"]
@@ -28706,7 +29081,11 @@ var TOOL_DEFINITIONS = [
28706
29081
  properties: {
28707
29082
  file: {
28708
29083
  type: "string",
28709
- description: "Path to the .upg file (relative, absolute, or a bare product name in workspace mode)."
29084
+ description: "Path to the .upg file (relative, absolute, or a bare product name in workspace mode). Alias: `product`."
29085
+ },
29086
+ product: {
29087
+ type: "string",
29088
+ description: "Alias for `file`."
28710
29089
  }
28711
29090
  },
28712
29091
  required: ["file"]
@@ -28989,7 +29368,7 @@ var TOOL_DEFINITIONS = [
28989
29368
  },
28990
29369
  {
28991
29370
  name: "list_frameworks",
28992
- description: "List the canonical `UPGFramework` definitions; the 34 curated, famous product frameworks that anchor the public catalog (spanning strategy, discovery, prioritisation, design, growth, engineering, and reflection classics). Paginated (default 50, max 200). Cursor is opaque: pass `next_cursor` from a previous response. Optional `category` is exact-match against `UPGFramework.category` and applies before pagination.",
29371
+ description: "List the canonical `UPGFramework` definitions: the curated, famous product frameworks that anchor the public catalog (spanning strategy, discovery, prioritisation, design, growth, engineering, and reflection classics). Returns a lightweight summary per framework (id, name, category, description, tags, approach_ids, structure_pattern); call `get_framework(id)` for the full record. Paginated (default 50, max 200). Cursor is opaque: pass `next_cursor` from a previous response. Optional `category` is exact-match against `UPGFramework.category` and applies before pagination.",
28993
29372
  inputSchema: {
28994
29373
  type: "object",
28995
29374
  properties: {
@@ -29005,7 +29384,8 @@ var TOOL_DEFINITIONS = [
29005
29384
  inputSchema: {
29006
29385
  type: "object",
29007
29386
  properties: {
29008
- id: { type: "string", description: "Framework id (kebab-case)." }
29387
+ id: { type: "string", description: "Framework id (kebab-case). Alias: `framework_id`." },
29388
+ framework_id: { type: "string", description: "Alias for `id` (matches the key used by apply_framework / prioritise)." }
29009
29389
  },
29010
29390
  required: ["id"]
29011
29391
  }
@@ -29918,6 +30298,7 @@ async function runMcpServer() {
29918
30298
  }
29919
30299
  }
29920
30300
  const store = new UPGFileStore();
30301
+ store.setWriter("upg-mcp-local", SERVER_VERSION);
29921
30302
  await store.load(resolvedPath);
29922
30303
  const deprecated = getDeprecatedTypes();
29923
30304
  const nodes = store.getAllNodes();