@unified-product-graph/core 0.8.15 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -283,7 +283,7 @@ var UPG_DOMAINS = [
283
283
  {
284
284
  id: "product_spec",
285
285
  label: "Product Specification",
286
- description: "What you are building and shipping. Feature areas group related capabilities. Features, epics, and user stories break work down. Acceptance criteria define done. Tasks and bugs track execution. Releases and changelogs mark what shipped. Roadmaps and roadmap items plan what comes next. Themes group strategic bets. Translates Strategy into Engineering and tracks delivery through Program Management.",
286
+ description: "What you are building and shipping. Feature areas group related capabilities. Features, epics, and user stories break work down. Acceptance criteria define done. Tasks and bugs track execution. Releases and changelogs mark what shipped. Roadmaps and roadmap items plan what comes next. Roadmap themes group roadmap work around the customer problem it solves, one level down from the strategic themes in Strategy. Translates Strategy into Engineering and tracks delivery through Program Management.",
287
287
  types: [
288
288
  "feature",
289
289
  "feature_area",
@@ -295,7 +295,7 @@ var UPG_DOMAINS = [
295
295
  "bug",
296
296
  "roadmap",
297
297
  "roadmap_item",
298
- "theme",
298
+ "roadmap_theme",
299
299
  "changelog"
300
300
  ]
301
301
  },
@@ -728,8 +728,8 @@ var UPG_ENTITY_META = [
728
728
  { name: "need", type_id: "ent_313", maturity: "stable", since: "0.1.0" },
729
729
  { name: "switching_cost", type_id: "ent_022", maturity: "stable", since: "0.1.0" },
730
730
  // ── Discovery ──
731
- { name: "opportunity", type_id: "ent_023", maturity: "stable", since: "0.1.0" },
732
- { name: "solution", type_id: "ent_024", maturity: "stable", since: "0.1.0" },
731
+ { name: "opportunity", type_id: "ent_023", maturity: "stable", since: "0.1.0", default_frameworks: ["opportunity-sizing", "rice-scoring"] },
732
+ { name: "solution", type_id: "ent_024", maturity: "stable", since: "0.1.0", default_frameworks: ["rice-scoring"] },
733
733
  { name: "feasibility_study", type_id: "ent_025", maturity: "stable", since: "0.1.0" },
734
734
  { name: "design_sprint", type_id: "ent_026", maturity: "stable", since: "0.1.0" },
735
735
  // ── Validation ──
@@ -830,7 +830,8 @@ var UPG_ENTITY_META = [
830
830
  { name: "bug", type_id: "ent_077", maturity: "stable", since: "0.1.0" },
831
831
  { name: "roadmap", type_id: "ent_078", maturity: "stable", since: "0.1.0" },
832
832
  { name: "roadmap_item", type_id: "ent_079", maturity: "stable", since: "0.1.0" },
833
- { name: "theme", type_id: "ent_080", maturity: "stable", since: "0.1.0" },
833
+ { name: "theme", type_id: "ent_080", maturity: "deprecated", since: "0.1.0", deprecated_in: "0.9.0", replacement: "roadmap_theme" },
834
+ { name: "roadmap_theme", type_id: "ent_351", maturity: "stable", since: "0.1.0" },
834
835
  { name: "changelog", type_id: "ent_081", maturity: "stable", since: "0.1.0" },
835
836
  // ── Engineering ──
836
837
  { name: "bounded_context", type_id: "ent_082", maturity: "stable", since: "0.1.0" },
@@ -1346,6 +1347,12 @@ var UPG_EDGE_CATALOG = {
1346
1347
  strategic_pillar_delivers_value_stream: { forward_verb: "delivers", reverse_verb: "delivered_by", classification: "hierarchy", source_type: "strategic_pillar", target_type: "value_stream" },
1347
1348
  strategic_pillar_decided_via_decision: { forward_verb: "decided_via", reverse_verb: "decided_for", classification: "hierarchy", source_type: "strategic_pillar", target_type: "decision" },
1348
1349
  strategic_theme_pursues_initiative: { forward_verb: "pursues", reverse_verb: "pursued_under", classification: "hierarchy", source_type: "strategic_theme", target_type: "initiative" },
1350
+ // v0.9.0 (UPG-660): the soft bridge from the annual strategy focus area to the
1351
+ // roadmap grouping that realises it. Semantic, NOT hierarchy: strategic_theme and
1352
+ // roadmap_theme sit on different spines (strategy cascade vs roadmap cascade), so
1353
+ // this is a cross-reference, not containment. Pairs with the theme → roadmap_theme
1354
+ // rename that removed the bare-'theme' collision (N6/UPG-652 lineage).
1355
+ strategic_theme_realised_by_roadmap_theme: { forward_verb: "realised_by", reverse_verb: "realises", classification: "semantic", source_type: "strategic_theme", target_type: "roadmap_theme" },
1349
1356
  // v0.5.4 (UPG-511): three edges that lift strategic_theme from structural
1350
1357
  // isolation to a conceptually central strategy node.
1351
1358
  //
@@ -1403,7 +1410,7 @@ var UPG_EDGE_CATALOG = {
1403
1410
  product_builds_feature: { forward_verb: "builds", reverse_verb: "built_by", classification: "hierarchy", source_type: "product", target_type: "feature" },
1404
1411
  product_ships_via_release: { forward_verb: "ships_via", reverse_verb: "ships", classification: "hierarchy", source_type: "product", target_type: "release" },
1405
1412
  product_plans_via_roadmap: { forward_verb: "plans_via", reverse_verb: "plans_for", classification: "hierarchy", source_type: "product", target_type: "roadmap" },
1406
- product_categorises_by_theme: { forward_verb: "categorises_by", reverse_verb: "categorises", classification: "hierarchy", source_type: "product", target_type: "theme" },
1413
+ product_categorises_by_roadmap_theme: { forward_verb: "categorises_by", reverse_verb: "categorises", classification: "hierarchy", source_type: "product", target_type: "roadmap_theme" },
1407
1414
  feature_area_contains_feature: { forward_verb: "contains", reverse_verb: "belongs_to", classification: "hierarchy", source_type: "feature_area", target_type: "feature" },
1408
1415
  feature_area_contains_feature_area: { forward_verb: "contains", reverse_verb: "belongs_to", classification: "hierarchy", source_type: "feature_area", target_type: "feature_area" },
1409
1416
  outcome_delivered_by_feature: { forward_verb: "delivered_by", reverse_verb: "delivers", classification: "cross-domain", source_type: "outcome", target_type: "feature" },
@@ -1427,12 +1434,12 @@ var UPG_EDGE_CATALOG = {
1427
1434
  release_contains_bug: { forward_verb: "contains", reverse_verb: "belongs_to", classification: "hierarchy", source_type: "release", target_type: "bug" },
1428
1435
  release_documented_in_changelog: { forward_verb: "documented_in", reverse_verb: "documents", classification: "hierarchy", source_type: "release", target_type: "changelog" },
1429
1436
  roadmap_contains_roadmap_item: { forward_verb: "contains", reverse_verb: "belongs_to", classification: "hierarchy", source_type: "roadmap", target_type: "roadmap_item" },
1430
- roadmap_categorised_by_theme: { forward_verb: "categorised_by", reverse_verb: "categorises", classification: "hierarchy", source_type: "roadmap", target_type: "theme" },
1437
+ roadmap_categorised_by_roadmap_theme: { forward_verb: "categorised_by", reverse_verb: "categorises", classification: "hierarchy", source_type: "roadmap", target_type: "roadmap_theme" },
1431
1438
  roadmap_schedules_release: { forward_verb: "schedules", reverse_verb: "scheduled_in", classification: "hierarchy", source_type: "roadmap", target_type: "release" },
1432
- theme_groups_feature: { forward_verb: "groups", reverse_verb: "grouped_in", classification: "hierarchy", source_type: "theme", target_type: "feature" },
1433
- // feature_area is not contained by theme; themes span multiple
1439
+ roadmap_theme_groups_feature: { forward_verb: "groups", reverse_verb: "grouped_in", classification: "hierarchy", source_type: "roadmap_theme", target_type: "feature" },
1440
+ // feature_area is not contained by roadmap_theme; roadmap themes span multiple
1434
1441
  // areas cross-cuttingly. Containment path: product → feature_area.
1435
- theme_spans_feature_area: { forward_verb: "spans", reverse_verb: "spanned_by", classification: "semantic", source_type: "theme", target_type: "feature_area" },
1442
+ roadmap_theme_spans_feature_area: { forward_verb: "spans", reverse_verb: "spanned_by", classification: "semantic", source_type: "roadmap_theme", target_type: "feature_area" },
1436
1443
  // The legacy `story_task` collapsed into `task` (v0.4.0), so the implements
1437
1444
  // relationship is the canonical `task_implements_user_story` above; there is
1438
1445
  // no separate story_task edge. (v0.2.7 introduced the Statement/Implementation
@@ -2943,7 +2950,8 @@ var UPG_CROSS_EDGE_TYPES = [
2943
2950
  "shares_metric",
2944
2951
  "depends_on_product",
2945
2952
  "cannibalises",
2946
- "succeeds"
2953
+ "succeeds",
2954
+ "hosts"
2947
2955
  ];
2948
2956
 
2949
2957
  // src/registry/entity-type-resolution.ts
@@ -3041,7 +3049,7 @@ var UPG_VALID_CHILDREN = {
3041
3049
  "feature_area",
3042
3050
  "release",
3043
3051
  "roadmap",
3044
- "theme",
3052
+ "roadmap_theme",
3045
3053
  // Engineering
3046
3054
  "bounded_context",
3047
3055
  "code_repository",
@@ -3437,8 +3445,8 @@ var UPG_VALID_CHILDREN = {
3437
3445
  a11y_standard: ["a11y_guideline", "a11y_audit", "a11y_annotation"],
3438
3446
  a11y_audit: ["a11y_issue"],
3439
3447
  // ── Product Specification expansion ─────────────────────────────────────────
3440
- roadmap: ["roadmap_item", "theme", "release"],
3441
- theme: ["feature"],
3448
+ roadmap: ["roadmap_item", "roadmap_theme", "release"],
3449
+ roadmap_theme: ["feature"],
3442
3450
  // ── Unified Context Layer hierarchy ─────────────────────────────────────────
3443
3451
  design_system: [
3444
3452
  "design_component",
@@ -6051,7 +6059,7 @@ var UPG_LIFECYCLE_FREE_TYPES = /* @__PURE__ */ new Set([
6051
6059
  // v0.7.0/UPG-571. ─
6052
6060
  "acceptance_criterion",
6053
6061
  "changelog",
6054
- "theme",
6062
+ "roadmap_theme",
6055
6063
  "user_story",
6056
6064
  // ── Strategy: metric is a measurement definition; metric_quality_assessment
6057
6065
  // is a point-in-time snapshot; value_stream is a mapped flow;
@@ -6731,6 +6739,21 @@ function getEnumValueMeta(scaleName, value) {
6731
6739
 
6732
6740
  // src/grammar/migrations.ts
6733
6741
  var UPG_MIGRATIONS = {
6742
+ "0.9.0": [
6743
+ // (since v0.9.0, UPG-660) theme → roadmap_theme. `theme` was the only bare,
6744
+ // unqualified theme among four domain-prefixed siblings (strategic_theme,
6745
+ // content_theme, feedback_theme); it claimed the unqualified word and read as
6746
+ // interchangeable with strategic_theme (the N6/UPG-652 confusion). Renamed to
6747
+ // roadmap_theme so all four read consistently and the customer-problem roadmap
6748
+ // grouping is explicit. Lifecycle-free, identical property surface (theme_scope
6749
+ // / priority); no property migration required. Paired edge renames live in
6750
+ // UPG_EDGE_MIGRATIONS['0.9.0'].
6751
+ {
6752
+ from: "theme",
6753
+ to: "roadmap_theme",
6754
+ reason: 'theme renamed to roadmap_theme (UPG-660). The bare "theme" was the only domain-unprefixed theme among strategic_theme / content_theme / feedback_theme; it grabbed the unqualified word and read as interchangeable with strategic_theme. roadmap_theme makes the customer-problem roadmap grouping explicit and consistent across the four. Same property surface (theme_scope / priority); no property migration needed.'
6755
+ }
6756
+ ],
6734
6757
  "0.7.0": [
6735
6758
  // (since v0.7.0, UPG-571) story_statement → user_story. The v0.2.7 split
6736
6759
  // correctly separated the templated promise from the engineering work
@@ -7773,6 +7796,17 @@ function getSplitMigrations(fromVersion, toVersion) {
7773
7796
  return result;
7774
7797
  }
7775
7798
  var UPG_EDGE_MIGRATIONS = {
7799
+ "0.9.0": [
7800
+ // (since v0.9.0, UPG-660) theme → roadmap_theme. The four canonical edges that
7801
+ // touch the roadmap theme are renamed to the roadmap_theme form. Endpoint guards
7802
+ // reference the POST-migration (roadmap_theme) types; edge migration runs after
7803
+ // node migration, so by the time these rules apply the node has already been
7804
+ // renamed theme → roadmap_theme (UPG_MIGRATIONS['0.9.0']).
7805
+ { kind: "rename", from: "product_categorises_by_theme", to: "product_categorises_by_roadmap_theme", requires_source_type: "product", requires_target_type: "roadmap_theme", reason: "theme \u2192 roadmap_theme (UPG-660). Product categorises by the roadmap theme; edge key updated to the renamed target type." },
7806
+ { kind: "rename", from: "roadmap_categorised_by_theme", to: "roadmap_categorised_by_roadmap_theme", requires_source_type: "roadmap", requires_target_type: "roadmap_theme", reason: "theme \u2192 roadmap_theme (UPG-660). Roadmap is categorised by the roadmap theme; edge key updated to the renamed target type." },
7807
+ { kind: "rename", from: "theme_groups_feature", to: "roadmap_theme_groups_feature", requires_source_type: "roadmap_theme", requires_target_type: "feature", reason: "theme \u2192 roadmap_theme (UPG-660). The roadmap theme groups features; edge key updated to the renamed source type." },
7808
+ { kind: "rename", from: "theme_spans_feature_area", to: "roadmap_theme_spans_feature_area", requires_source_type: "roadmap_theme", requires_target_type: "feature_area", reason: "theme \u2192 roadmap_theme (UPG-660). The roadmap theme spans feature areas; edge key updated to the renamed source type." }
7809
+ ],
7776
7810
  "0.7.0": [
7777
7811
  // (since v0.7.0, UPG-571) story_statement → user_story re-canon. The four
7778
7812
  // canonical edges that touch the statement are renamed to the user_story
@@ -10669,7 +10703,7 @@ var UPG_PROPERTY_SCHEMA = {
10669
10703
  reach: {
10670
10704
  type: "assessment",
10671
10705
  scale_id: "reach_5",
10672
- description: "How many users experience this problem",
10706
+ description: "How many users experience this problem. @deprecated 0.9.0:a framework-scoped scoring input, not an intrinsic property. Apply the `opportunity-sizing` framework; the value lives on the framework_exercise includes-edge. Removed in 0.9.1.",
10673
10707
  properties: {
10674
10708
  value: { type: "number", description: "The numeric value, used for computation." },
10675
10709
  label: { type: "string", description: "The qualitative label (what the assessor meant)." },
@@ -10681,7 +10715,7 @@ var UPG_PROPERTY_SCHEMA = {
10681
10715
  frequency: {
10682
10716
  type: "assessment",
10683
10717
  scale_id: "frequency_5",
10684
- description: "How often users experience this problem",
10718
+ description: "How often users experience this problem. @deprecated 0.9.0:framework-scoped (opportunity-sizing). Removed in 0.9.1.",
10685
10719
  properties: {
10686
10720
  value: { type: "number", description: "The numeric value, used for computation." },
10687
10721
  label: { type: "string", description: "The qualitative label (what the assessor meant)." },
@@ -10693,7 +10727,7 @@ var UPG_PROPERTY_SCHEMA = {
10693
10727
  pain: {
10694
10728
  type: "assessment",
10695
10729
  scale_id: "pain_5",
10696
- description: "How painful it is when unaddressed",
10730
+ description: "How painful it is when unaddressed. @deprecated 0.9.0:framework-scoped (opportunity-sizing). Removed in 0.9.1.",
10697
10731
  properties: {
10698
10732
  value: { type: "number", description: "The numeric value, used for computation." },
10699
10733
  label: { type: "string", description: "The qualitative label (what the assessor meant)." },
@@ -10702,7 +10736,7 @@ var UPG_PROPERTY_SCHEMA = {
10702
10736
  },
10703
10737
  required: ["value", "label"]
10704
10738
  },
10705
- opportunity_score: { type: "number", description: "Computed: normalized_reach x normalized_frequency x normalized_pain (0-1)" }
10739
+ opportunity_score: { type: "number", description: "Computed: normalized_reach x normalized_frequency x normalized_pain (0-1). @deprecated 0.9.0:computed by the `opportunity-sizing` framework on its application edge, not stored on the entity. Removed in 0.9.1." }
10706
10740
  },
10707
10741
  // OrganizationProperties: Organization entity.
10708
10742
  organization: {
@@ -11116,6 +11150,11 @@ var UPG_PROPERTY_SCHEMA = {
11116
11150
  start_date: { type: "string", description: "ISO date work begins. More precise than `quarter` for continuous planning." },
11117
11151
  target_date: { type: "string", description: "ISO date completion is expected. For shipped items, the actual completion date." }
11118
11152
  },
11153
+ // RoadmapThemeProperties: Thematic grouping of roadmap work, around the customer problem it solves.
11154
+ roadmap_theme: {
11155
+ theme_scope: { type: "string", description: "Scope description" },
11156
+ priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Priority" }
11157
+ },
11119
11158
  // RoleProperties: Role entity.
11120
11159
  role: {
11121
11160
  responsibilities: { type: "string[]", description: "Key responsibilities of the role" },
@@ -11301,7 +11340,7 @@ var UPG_PROPERTY_SCHEMA = {
11301
11340
  reach: {
11302
11341
  type: "assessment",
11303
11342
  scale_id: "reach_5",
11304
- description: "How many users this solution reaches (1 = few, 5 = most)",
11343
+ description: "How many users this solution reaches (1 = few, 5 = most). @deprecated 0.9.0:a framework-scoped scoring input, not an intrinsic property. Apply the `rice-scoring` framework; the value lives on the framework_exercise includes-edge. Removed in 0.9.1.",
11305
11344
  properties: {
11306
11345
  value: { type: "number", description: "The numeric value, used for computation." },
11307
11346
  label: { type: "string", description: "The qualitative label (what the assessor meant)." },
@@ -11313,7 +11352,7 @@ var UPG_PROPERTY_SCHEMA = {
11313
11352
  impact: {
11314
11353
  type: "assessment",
11315
11354
  scale_id: "impact_5",
11316
- description: "Expected impact on the target outcome (1 = minimal, 5 = transformative)",
11355
+ description: "Expected impact on the target outcome (1 = minimal, 5 = transformative). @deprecated 0.9.0:framework-scoped (rice-scoring). Removed in 0.9.1.",
11317
11356
  properties: {
11318
11357
  value: { type: "number", description: "The numeric value, used for computation." },
11319
11358
  label: { type: "string", description: "The qualitative label (what the assessor meant)." },
@@ -11325,7 +11364,7 @@ var UPG_PROPERTY_SCHEMA = {
11325
11364
  confidence: {
11326
11365
  type: "assessment",
11327
11366
  scale_id: "confidence_5",
11328
- description: "How confident the team is in this solution (1 = speculative, 5 = proven)",
11367
+ description: "How confident the team is in this solution (1 = speculative, 5 = proven). @deprecated 0.9.0:framework-scoped (rice-scoring). Removed in 0.9.1.",
11329
11368
  properties: {
11330
11369
  value: { type: "number", description: "The numeric value, used for computation." },
11331
11370
  label: { type: "string", description: "The qualitative label (what the assessor meant)." },
@@ -11337,7 +11376,7 @@ var UPG_PROPERTY_SCHEMA = {
11337
11376
  effort: {
11338
11377
  type: "assessment",
11339
11378
  scale_id: "effort_5",
11340
- description: "Level of effort required to implement (1 = trivial, 5 = very large)",
11379
+ description: "Level of effort required to implement (1 = trivial, 5 = very large). @deprecated 0.9.0:effort is a framework-scoped scoring input (it varies by assessor and method), not an intrinsic property. Removed in 0.9.1.",
11341
11380
  properties: {
11342
11381
  value: { type: "number", description: "The numeric value, used for computation." },
11343
11382
  label: { type: "string", description: "The qualitative label (what the assessor meant)." },
@@ -11346,7 +11385,7 @@ var UPG_PROPERTY_SCHEMA = {
11346
11385
  },
11347
11386
  required: ["value", "label"]
11348
11387
  },
11349
- rice_score: { type: "number", description: "Computed: (reach \xD7 impact \xD7 confidence) / effort" }
11388
+ rice_score: { type: "number", description: "Computed: (reach \xD7 impact \xD7 confidence) / effort. @deprecated 0.9.0:computed by the `rice-scoring` framework on its application edge, not stored on the entity. Removed in 0.9.1." }
11350
11389
  },
11351
11390
  // StakeholderProperties: Stakeholder entity.
11352
11391
  stakeholder: {
@@ -11593,11 +11632,6 @@ var UPG_PROPERTY_SCHEMA = {
11593
11632
  skipped_count: { type: "number", description: "Number of tests that were skipped in the last run" },
11594
11633
  flaky_count: { type: "number", description: "Number of tests that passed only on retry (flaky) in the last run" }
11595
11634
  },
11596
- // ThemeProperties: Thematic grouping of work.
11597
- theme: {
11598
- theme_scope: { type: "string", description: "Scope description" },
11599
- priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Priority" }
11600
- },
11601
11635
  // ThreatProperties: Threat.
11602
11636
  threat: {
11603
11637
  category: { type: "string", description: 'Attack or threat scenario. @example "injection", "misconfiguration", "social engineering", "supply chain"' },
@@ -11828,6 +11862,188 @@ function getPropertySchema(entityType) {
11828
11862
 
11829
11863
  // src/frameworks/canonical.ts
11830
11864
  var UPG_FRAMEWORKS = [
11865
+ {
11866
+ "id": "opportunity-sizing",
11867
+ "approach_ids": [
11868
+ "prioritise"
11869
+ ],
11870
+ "name": "Opportunity Sizing",
11871
+ "version": "1.0.0",
11872
+ "description": "Size opportunities by Reach, Frequency, and Pain to rank which problems are most worth solving before committing to solutions.",
11873
+ "category": "prioritization",
11874
+ "origin": {
11875
+ "type": "practitioner",
11876
+ "attribution": "Continuous discovery practice",
11877
+ "description": "A lightweight discovery-prioritisation method: weigh how many users hit a problem, how often, and how much it hurts, to rank opportunities before investing in solutions.",
11878
+ "url": "https://www.producttalk.org/2016/08/opportunity-solution-tree/",
11879
+ "year": 2016,
11880
+ "license": "open_attribution"
11881
+ },
11882
+ "tags": [
11883
+ "prioritization",
11884
+ "discovery",
11885
+ "table"
11886
+ ],
11887
+ "slots": [
11888
+ {
11889
+ "label": "Opportunities to size",
11890
+ "entityTypeId": "opportunity",
11891
+ "description": "Opportunities scored on Reach, Frequency, and Pain."
11892
+ }
11893
+ ],
11894
+ "data": {
11895
+ "entity_types": [
11896
+ {
11897
+ "type": "opportunity",
11898
+ "role": "scored_item"
11899
+ }
11900
+ ],
11901
+ "required_properties": {
11902
+ "opportunity": [
11903
+ {
11904
+ "property": "reach",
11905
+ "type": "assessment",
11906
+ "scale_id": "reach_5",
11907
+ "required": true,
11908
+ "scope": "framework",
11909
+ "label": "Reach",
11910
+ "description": "How many users experience this problem?"
11911
+ },
11912
+ {
11913
+ "property": "frequency",
11914
+ "type": "assessment",
11915
+ "scale_id": "frequency_5",
11916
+ "required": true,
11917
+ "scope": "framework",
11918
+ "label": "Frequency",
11919
+ "description": "How often do they run into it?"
11920
+ },
11921
+ {
11922
+ "property": "pain",
11923
+ "type": "assessment",
11924
+ "scale_id": "pain_5",
11925
+ "required": true,
11926
+ "scope": "framework",
11927
+ "label": "Pain",
11928
+ "description": "How painful is it when left unaddressed?"
11929
+ }
11930
+ ]
11931
+ },
11932
+ "computed_properties": [
11933
+ {
11934
+ "property": "opportunity_score",
11935
+ "expression": "reach * frequency * pain",
11936
+ "entity_type": "opportunity",
11937
+ "label": "Opportunity Score",
11938
+ "format": "number"
11939
+ }
11940
+ ],
11941
+ "scoring_method": {
11942
+ "applies_to": [
11943
+ "opportunity"
11944
+ ],
11945
+ "inputs": [
11946
+ {
11947
+ "property": "reach",
11948
+ "type": "assessment",
11949
+ "scale_id": "reach_5",
11950
+ "required": true,
11951
+ "scope": "framework",
11952
+ "label": "Reach",
11953
+ "description": "How many users experience this problem?"
11954
+ },
11955
+ {
11956
+ "property": "frequency",
11957
+ "type": "assessment",
11958
+ "scale_id": "frequency_5",
11959
+ "required": true,
11960
+ "scope": "framework",
11961
+ "label": "Frequency",
11962
+ "description": "How often do they run into it?"
11963
+ },
11964
+ {
11965
+ "property": "pain",
11966
+ "type": "assessment",
11967
+ "scale_id": "pain_5",
11968
+ "required": true,
11969
+ "scope": "framework",
11970
+ "label": "Pain",
11971
+ "description": "How painful is it when left unaddressed?"
11972
+ }
11973
+ ],
11974
+ "computed": [
11975
+ {
11976
+ "property": "opportunity_score",
11977
+ "expression": "reach * frequency * pain",
11978
+ "label": "Opportunity Score",
11979
+ "format": "number"
11980
+ }
11981
+ ]
11982
+ }
11983
+ },
11984
+ "structure": {
11985
+ "pattern": "table"
11986
+ },
11987
+ "presentation": {
11988
+ "layout": {
11989
+ "type": "table",
11990
+ "columns": [
11991
+ {
11992
+ "property": "title",
11993
+ "label": "Opportunities to size",
11994
+ "sortable": true
11995
+ },
11996
+ {
11997
+ "property": "reach",
11998
+ "label": "Reach",
11999
+ "sortable": true,
12000
+ "format": "number"
12001
+ },
12002
+ {
12003
+ "property": "frequency",
12004
+ "label": "Frequency",
12005
+ "sortable": true,
12006
+ "format": "number"
12007
+ },
12008
+ {
12009
+ "property": "pain",
12010
+ "label": "Pain",
12011
+ "sortable": true,
12012
+ "format": "number"
12013
+ },
12014
+ {
12015
+ "property": "opportunity_score",
12016
+ "label": "Opportunity Score",
12017
+ "sortable": true,
12018
+ "format": "score_pill"
12019
+ }
12020
+ ]
12021
+ },
12022
+ "sort_by": {
12023
+ "property": "opportunity_score",
12024
+ "direction": "desc"
12025
+ },
12026
+ "colour_by": "score",
12027
+ "card_fields": [
12028
+ "title",
12029
+ "description",
12030
+ "status"
12031
+ ]
12032
+ },
12033
+ "education": {
12034
+ "purpose": "Rank opportunities by how widely, how often, and how painfully a problem is felt, so discovery effort flows to the problems most worth solving.",
12035
+ "core_question": "Of the problems we could pursue, which affect the most users, most often, with the most pain?",
12036
+ "when_to_use": [
12037
+ "You have more opportunities than you can pursue",
12038
+ "You need to compare problems before committing to solutions",
12039
+ "You want a defensible, transparent way to choose what to explore"
12040
+ ],
12041
+ "when_not_to_use": [
12042
+ "A single opportunity is already validated and obvious",
12043
+ "You have no signal yet on reach, frequency, or pain"
12044
+ ]
12045
+ }
12046
+ },
11831
12047
  {
11832
12048
  "id": "opportunity-solution-tree",
11833
12049
  "approach_ids": [
@@ -13084,7 +13300,7 @@ var UPG_FRAMEWORKS = [
13084
13300
  ],
13085
13301
  "name": "RICE Scoring",
13086
13302
  "version": "1.0.0",
13087
- "description": "Score features, opportunities, and needs by Reach, Impact, Confidence, and Effort to produce a ranked priority list.",
13303
+ "description": "Score features, solutions, opportunities, and needs by Reach, Impact, Confidence, and Effort to produce a ranked priority list.",
13088
13304
  "category": "prioritization",
13089
13305
  "origin": {
13090
13306
  "type": "practitioner",
@@ -13109,6 +13325,11 @@ var UPG_FRAMEWORKS = [
13109
13325
  "entityTypeId": "opportunity",
13110
13326
  "description": "Opportunities scored on the same RICE Scoring inputs as features."
13111
13327
  },
13328
+ {
13329
+ "label": "Solutions to score",
13330
+ "entityTypeId": "solution",
13331
+ "description": "Solutions scored on the same RICE Scoring inputs as features."
13332
+ },
13112
13333
  {
13113
13334
  "label": "Needs to score",
13114
13335
  "entityTypeId": "need",
@@ -13125,6 +13346,10 @@ var UPG_FRAMEWORKS = [
13125
13346
  "type": "opportunity",
13126
13347
  "role": "scored_item"
13127
13348
  },
13349
+ {
13350
+ "type": "solution",
13351
+ "role": "scored_item"
13352
+ },
13128
13353
  {
13129
13354
  "type": "need",
13130
13355
  "role": "scored_item"
@@ -13207,6 +13432,44 @@ var UPG_FRAMEWORKS = [
13207
13432
  "description": "How much work is required to build and ship this, on the effort scale?"
13208
13433
  }
13209
13434
  ],
13435
+ "solution": [
13436
+ {
13437
+ "property": "reach",
13438
+ "type": "assessment",
13439
+ "scale_id": "reach_5",
13440
+ "required": true,
13441
+ "scope": "framework",
13442
+ "label": "Reach",
13443
+ "description": "How many users will this impact per quarter?"
13444
+ },
13445
+ {
13446
+ "property": "impact",
13447
+ "type": "assessment",
13448
+ "scale_id": "impact_5",
13449
+ "required": true,
13450
+ "scope": "framework",
13451
+ "label": "Impact",
13452
+ "description": "How much will this impact each user, on the impact scale?"
13453
+ },
13454
+ {
13455
+ "property": "confidence",
13456
+ "type": "assessment",
13457
+ "scale_id": "confidence_5",
13458
+ "required": true,
13459
+ "scope": "framework",
13460
+ "label": "Confidence",
13461
+ "description": "How confident are you in the reach, impact, and effort estimates?"
13462
+ },
13463
+ {
13464
+ "property": "effort",
13465
+ "type": "assessment",
13466
+ "scale_id": "effort_5",
13467
+ "required": true,
13468
+ "scope": "framework",
13469
+ "label": "Effort",
13470
+ "description": "How much work is required to build and ship this, on the effort scale?"
13471
+ }
13472
+ ],
13210
13473
  "need": [
13211
13474
  {
13212
13475
  "property": "reach",
@@ -13261,6 +13524,13 @@ var UPG_FRAMEWORKS = [
13261
13524
  "label": "RICE Score",
13262
13525
  "format": "number"
13263
13526
  },
13527
+ {
13528
+ "property": "rice_score",
13529
+ "expression": "(reach * impact * confidence) / effort",
13530
+ "entity_type": "solution",
13531
+ "label": "RICE Score",
13532
+ "format": "number"
13533
+ },
13264
13534
  {
13265
13535
  "property": "rice_score",
13266
13536
  "expression": "(reach * impact * confidence) / effort",
@@ -13273,6 +13543,7 @@ var UPG_FRAMEWORKS = [
13273
13543
  "applies_to": [
13274
13544
  "feature",
13275
13545
  "opportunity",
13546
+ "solution",
13276
13547
  "need"
13277
13548
  ],
13278
13549
  "inputs": [
@@ -17955,7 +18226,8 @@ var STANDARD_LABELS = {
17955
18226
  product: { alt_labels: ["offering", "app", "service", "platform"] },
17956
18227
  vision: { alt_labels: ["product vision", "north star vision", "long-term vision"] },
17957
18228
  mission: { alt_labels: ["mission statement", "purpose"] },
17958
- strategic_theme: { alt_labels: ["theme", "strategic pillar", "focus area"] },
18229
+ strategic_theme: { alt_labels: ["focus area", "strategic focus area"] },
18230
+ // N6: not 'theme'/'strategic pillar' (own types)
17959
18231
  initiative: { alt_labels: ["strategic initiative", "program initiative", "workstream"] },
17960
18232
  capability: { alt_labels: ["business capability", "organizational capability"] },
17961
18233
  value_stream: { alt_labels: ["value chain", "stream"] },
@@ -18017,7 +18289,8 @@ var STANDARD_LABELS = {
18017
18289
  fix: { alt_labels: ["bugfix", "patch", "remediation"] },
18018
18290
  roadmap: { alt_labels: ["product roadmap", "release plan", "timeline"] },
18019
18291
  roadmap_item: { alt_labels: ["roadmap entry", "planned item"] },
18020
- theme: { alt_labels: ["product theme", "bucket", "category"] },
18292
+ roadmap_theme: { alt_labels: ["product theme", "roadmap theme"] },
18293
+ // UPG-660: renamed from bare 'theme' (N6 lineage)
18021
18294
  // Engineering layer
18022
18295
  bounded_context: { alt_labels: ["context", "domain boundary", "module boundary"] },
18023
18296
  service: { alt_labels: ["microservice", "backend service", "api service"] },
@@ -18216,7 +18489,8 @@ var STANDARD_LABELS = {
18216
18489
  feedback_vote: { alt_labels: ["upvote", "vote", "user vote"] },
18217
18490
  user_advisory_board: { alt_labels: ["cab", "customer advisory board", "advisory council"] },
18218
18491
  beta_program: { alt_labels: ["beta", "early access", "preview program"] },
18219
- feedback_theme: { alt_labels: ["feedback cluster", "theme", "feedback category"] },
18492
+ feedback_theme: { alt_labels: ["feedback cluster", "feedback category"] },
18493
+ // N6: not bare 'theme'
18220
18494
  // Pricing & Packaging layer
18221
18495
  pricing_strategy: { alt_labels: ["pricing model", "monetization strategy"] },
18222
18496
  package: { alt_labels: ["product package", "bundle", "sku"] },
@@ -18722,9 +18996,9 @@ var PRODUCT_DELIVERY_PLAYBOOK = {
18722
18996
  ),
18723
18997
  seqStep(
18724
18998
  6,
18725
- "Themes & Changelog",
18726
- ["theme", "changelog"],
18727
- "Group releases into strategic themes. Maintain a changelog the team and customers can read together."
18999
+ "Roadmap Themes & Changelog",
19000
+ ["roadmap_theme", "changelog"],
19001
+ "Group roadmap work into roadmap themes around the customer problem. Maintain a changelog the team and customers can read together."
18728
19002
  )
18729
19003
  ]
18730
19004
  };
@@ -20029,7 +20303,7 @@ var PRODUCT_SPEC_GUIDE = {
20029
20303
  // registered to product_spec but missing from the navigation order).
20030
20304
  // `changelog` lives here because it is a structural product-shipping
20031
20305
  // artefact; content domain references it only via cross-domain bridges.
20032
- creation_sequence: ["feature_area", "feature", "epic", "user_story", "acceptance_criterion", "task", "bug", "release", "roadmap", "roadmap_item", "theme", "changelog"],
20306
+ creation_sequence: ["feature_area", "feature", "epic", "user_story", "acceptance_criterion", "task", "bug", "release", "roadmap", "roadmap_item", "roadmap_theme", "changelog"],
20033
20307
  patterns: [
20034
20308
  {
20035
20309
  name: "Feature Decomposition",
@@ -24511,7 +24785,7 @@ var UPG_REGIONS = [
24511
24785
  role: "leaf"
24512
24786
  },
24513
24787
  {
24514
- type: "theme",
24788
+ type: "roadmap_theme",
24515
24789
  role: "container",
24516
24790
  notes: "semantic spanner, not containment"
24517
24791
  },
@@ -24547,10 +24821,10 @@ var UPG_REGIONS = [
24547
24821
  "user_story_verified_by_acceptance_criterion",
24548
24822
  "task_implements_user_story",
24549
24823
  "roadmap_contains_roadmap_item",
24550
- "roadmap_categorised_by_theme",
24824
+ "roadmap_categorised_by_roadmap_theme",
24551
24825
  "roadmap_schedules_release",
24552
24826
  "release_documented_in_changelog",
24553
- "theme_spans_feature_area",
24827
+ "roadmap_theme_spans_feature_area",
24554
24828
  "milestone_gates_release",
24555
24829
  "roadmap_item_references_feature",
24556
24830
  "feature_request_voted_on_by_feedback_vote"
@@ -25871,7 +26145,7 @@ function isCanonical(text) {
25871
26145
  }
25872
26146
 
25873
26147
  // src/index.ts
25874
- var UPG_VERSION = "0.8.15";
26148
+ var UPG_VERSION = "0.9.0";
25875
26149
  var UPG_FORMAT_VERSION = "0.4.0";
25876
26150
  var MARKDOWN_FORMAT_VERSION = "0.1";
25877
26151
  var UPG_TYPES = getTypes();