@unified-product-graph/core 0.9.12 → 0.9.14

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
@@ -2942,7 +2942,9 @@ var UPG_EDGE_CATALOG = {
2942
2942
  specification_extends_specification: { forward_verb: "extends", reverse_verb: "extended_by", classification: "hierarchy", source_type: "specification", target_type: "specification" },
2943
2943
  specification_competes_with_specification: { forward_verb: "competes_with", reverse_verb: "competes_with", classification: "semantic", source_type: "specification", target_type: "specification" },
2944
2944
  primitive_defined_by_specification: { forward_verb: "defined_by", reverse_verb: "defines", classification: "semantic", source_type: "primitive", target_type: "specification" },
2945
- primitive_composes_primitive: { forward_verb: "composes", reverse_verb: "composed_by", classification: "hierarchy", source_type: "primitive", target_type: "primitive" }
2945
+ primitive_composes_primitive: { forward_verb: "composes", reverse_verb: "composed_by", classification: "hierarchy", source_type: "primitive", target_type: "primitive" },
2946
+ // Stewardship: a registry specification is governed by a (registry-hostable) organization (0.9.13).
2947
+ specification_governed_by_organization: { forward_verb: "governed_by", reverse_verb: "governs", classification: "semantic", source_type: "specification", target_type: "organization" }
2946
2948
  };
2947
2949
  var UPG_POLYMORPHIC_EDGE_KEYS = [
2948
2950
  // Universal semantic verbs
@@ -7224,6 +7226,22 @@ function getDeprecatedTypes() {
7224
7226
  return deprecated;
7225
7227
  }
7226
7228
  var UPG_PROPERTY_MIGRATIONS = {
7229
+ // ── v0.9.14: drop the key_result kr_status / status twin (A2) ──────────────
7230
+ //
7231
+ // key_result carried BOTH a lifecycle `status` and a `kr_status` property with
7232
+ // the identical four-value enum (on_track | at_risk | behind | achieved) ==
7233
+ // the KEY_RESULT_LIFECYCLE phases. Two fields, same values: an authoring trap.
7234
+ // The redundant property is removed; the authored health value lifts to the
7235
+ // canonical `UPGBaseNode.status` so a graph that set `kr_status` stays correct.
7236
+ "0.9.14": [
7237
+ {
7238
+ kind: "lift_property_to_top_level",
7239
+ type: "key_result",
7240
+ from_property: "kr_status",
7241
+ to: "status",
7242
+ reason: "A2 (0.9.14). key_result.kr_status duplicated the lifecycle `status` with the identical enum (on_track | at_risk | behind | achieved). The twin is removed; the authored health value lifts to `UPGBaseNode.status` verbatim."
7243
+ }
7244
+ ],
7227
7245
  // ── v0.9.12: technical-domain enum widening + data_flow orientation split ──
7228
7246
  //
7229
7247
  // Real authoring outgrew four engineering-domain enums. 0.9.12 widens them
@@ -10677,8 +10695,7 @@ var UPG_PROPERTY_SCHEMA = {
10677
10695
  key_result: {
10678
10696
  current_value: { type: "number", description: "Most recent observed value" },
10679
10697
  target_value: { type: "number", description: "Value for full achievement" },
10680
- unit: { type: "string", description: 'Display unit (e.g. "%", "users", "\xA3")' },
10681
- kr_status: { type: "string", enum: ["on_track", "at_risk", "behind", "achieved"], description: "Delivery health" }
10698
+ unit: { type: "string", description: 'Display unit (e.g. "%", "users", "\xA3")' }
10682
10699
  },
10683
10700
  // KnowledgeBaseArticleProperties: Knowledge base article.
10684
10701
  knowledge_base_article: {
@@ -17590,6 +17607,324 @@ var UPG_FRAMEWORKS = [
17590
17607
  "Time pressure makes a deeper trace expensive and the first-order call is good enough"
17591
17608
  ]
17592
17609
  }
17610
+ },
17611
+ {
17612
+ "id": "value-vs-effort",
17613
+ "approach_ids": [
17614
+ "prioritise"
17615
+ ],
17616
+ "name": "Value vs Effort",
17617
+ "version": "1.0.0",
17618
+ "description": "Plot features on a 2x2 matrix of value against effort. Quick wins (high value, low effort) get prioritised first.",
17619
+ "category": "prioritization",
17620
+ "origin": {
17621
+ "type": "practitioner",
17622
+ "description": "Common product management prioritisation tool. A simplified form of cost-benefit analysis.",
17623
+ "license": "cc_by"
17624
+ },
17625
+ "tags": [
17626
+ "prioritization",
17627
+ "quadrant"
17628
+ ],
17629
+ "slots": [
17630
+ {
17631
+ "label": "Quick Wins",
17632
+ "entityTypeId": "feature",
17633
+ "role": "quick_win",
17634
+ "description": "High value, low effort: do first"
17635
+ },
17636
+ {
17637
+ "label": "Big Bets",
17638
+ "entityTypeId": "feature",
17639
+ "role": "big_bet",
17640
+ "description": "High value, high effort: plan carefully"
17641
+ },
17642
+ {
17643
+ "label": "Fill-ins",
17644
+ "entityTypeId": "feature",
17645
+ "role": "fill_in",
17646
+ "description": "Low value, low effort: do when idle"
17647
+ },
17648
+ {
17649
+ "label": "Avoid",
17650
+ "entityTypeId": "feature",
17651
+ "role": "money_pit",
17652
+ "description": "Low value, high effort: deprioritise"
17653
+ }
17654
+ ],
17655
+ "data": {
17656
+ "entity_types": [
17657
+ {
17658
+ "type": "feature",
17659
+ "role": "item"
17660
+ }
17661
+ ],
17662
+ "required_properties": {
17663
+ "feature": [
17664
+ {
17665
+ "property": "value",
17666
+ "type": "number",
17667
+ "required": true,
17668
+ "label": "Value",
17669
+ "description": "Expected business value (1-10)"
17670
+ },
17671
+ {
17672
+ "property": "effort",
17673
+ "type": "number",
17674
+ "required": true,
17675
+ "label": "Effort",
17676
+ "description": "Implementation effort (1-10)"
17677
+ }
17678
+ ]
17679
+ },
17680
+ "computed_properties": [
17681
+ {
17682
+ "property": "value_effort_ratio",
17683
+ "expression": "value / effort",
17684
+ "entity_type": "feature",
17685
+ "label": "Value/Effort Ratio",
17686
+ "format": "number"
17687
+ }
17688
+ ]
17689
+ },
17690
+ "structure": {
17691
+ "pattern": "quadrant"
17692
+ },
17693
+ "presentation": {
17694
+ "layout": {
17695
+ "type": "quadrant",
17696
+ "x_axis": "impact",
17697
+ "y_axis": "effort",
17698
+ "x_label": "Quick Wins",
17699
+ "y_label": "Big Bets"
17700
+ },
17701
+ "colour_by": "group",
17702
+ "card_fields": [
17703
+ "title",
17704
+ "description"
17705
+ ]
17706
+ },
17707
+ "education": {
17708
+ "purpose": "Plot features on a value/effort matrix to identify quick wins (high value, low effort) and avoid resource traps (low value, high effort).",
17709
+ "core_question": "Which features give us the best return on engineering investment, and which are traps disguised as good ideas?",
17710
+ "when_to_use": [
17711
+ "You have more ideas or features than capacity to build them",
17712
+ "Stakeholders disagree on what to build next",
17713
+ "You need a transparent, defensible prioritisation process"
17714
+ ],
17715
+ "when_not_to_use": [
17716
+ "You have a single obvious next step with no contention",
17717
+ "The backlog is small enough to sequence intuitively"
17718
+ ]
17719
+ }
17720
+ },
17721
+ {
17722
+ "id": "eisenhower-matrix",
17723
+ "approach_ids": [
17724
+ "prioritise"
17725
+ ],
17726
+ "name": "Eisenhower Matrix",
17727
+ "version": "1.0.0",
17728
+ "description": "Classify tasks by urgency and importance into four quadrants: do, schedule, delegate, or eliminate.",
17729
+ "category": "prioritization",
17730
+ "origin": {
17731
+ "type": "practitioner",
17732
+ "attribution": "Dwight D. Eisenhower",
17733
+ "description": "Based on a quote attributed to Eisenhower: 'What is important is seldom urgent and what is urgent is seldom important.' Popularised by Stephen Covey.",
17734
+ "license": "public_domain"
17735
+ },
17736
+ "tags": [
17737
+ "prioritization",
17738
+ "quadrant"
17739
+ ],
17740
+ "slots": [
17741
+ {
17742
+ "label": "Do First",
17743
+ "entityTypeId": "feature",
17744
+ "role": "do_first",
17745
+ "description": "Urgent and important: act immediately"
17746
+ },
17747
+ {
17748
+ "label": "Schedule",
17749
+ "entityTypeId": "feature",
17750
+ "role": "schedule",
17751
+ "description": "Important but not urgent: plan it"
17752
+ },
17753
+ {
17754
+ "label": "Delegate",
17755
+ "entityTypeId": "feature",
17756
+ "role": "delegate",
17757
+ "description": "Urgent but not important: hand off"
17758
+ },
17759
+ {
17760
+ "label": "Eliminate",
17761
+ "entityTypeId": "feature",
17762
+ "role": "eliminate",
17763
+ "description": "Neither urgent nor important: drop it"
17764
+ }
17765
+ ],
17766
+ "data": {
17767
+ "entity_types": [
17768
+ {
17769
+ "type": "feature",
17770
+ "role": "item"
17771
+ }
17772
+ ],
17773
+ "required_properties": {
17774
+ "feature": [
17775
+ {
17776
+ "property": "urgency",
17777
+ "type": "number",
17778
+ "required": true,
17779
+ "label": "Urgency",
17780
+ "description": "How time-sensitive is this? (1-5)"
17781
+ },
17782
+ {
17783
+ "property": "importance",
17784
+ "type": "number",
17785
+ "required": true,
17786
+ "label": "Importance",
17787
+ "description": "How important is this to goals? (1-5)"
17788
+ }
17789
+ ]
17790
+ },
17791
+ "computed_properties": [
17792
+ {
17793
+ "property": "priority_score",
17794
+ "expression": "(urgency * 2) + importance",
17795
+ "entity_type": "feature",
17796
+ "label": "Priority Score",
17797
+ "format": "number"
17798
+ }
17799
+ ]
17800
+ },
17801
+ "structure": {
17802
+ "pattern": "quadrant"
17803
+ },
17804
+ "presentation": {
17805
+ "layout": {
17806
+ "type": "quadrant",
17807
+ "x_axis": "impact",
17808
+ "y_axis": "effort",
17809
+ "x_label": "Do First",
17810
+ "y_label": "Schedule"
17811
+ },
17812
+ "colour_by": "group",
17813
+ "card_fields": [
17814
+ "title",
17815
+ "description"
17816
+ ]
17817
+ },
17818
+ "education": {
17819
+ "purpose": "Sort tasks by urgency and importance into four quadrants, making it clear what to do now, schedule, delegate, or eliminate.",
17820
+ "core_question": "Am I spending my time on what matters most, or am I trapped in the urgent-but-unimportant quadrant?",
17821
+ "when_to_use": [
17822
+ "You have more ideas or features than capacity to build them",
17823
+ "Stakeholders disagree on what to build next",
17824
+ "You need a transparent, defensible prioritisation process"
17825
+ ],
17826
+ "when_not_to_use": [
17827
+ "You have a single obvious next step with no contention",
17828
+ "The backlog is small enough to sequence intuitively"
17829
+ ]
17830
+ }
17831
+ },
17832
+ {
17833
+ "id": "four-forces-of-progress",
17834
+ "approach_ids": [
17835
+ "reflect"
17836
+ ],
17837
+ "name": "Four Forces of Progress",
17838
+ "version": "1.0.0",
17839
+ "description": "Analyse the four forces that drive or inhibit customers switching to a new solution: Push, Pull, Anxiety, and Habit.",
17840
+ "category": "discovery",
17841
+ "origin": {
17842
+ "type": "practitioner",
17843
+ "attribution": "Bob Moesta",
17844
+ "description": "Demand-Side Sales 101",
17845
+ "url": "https://jobstobedone.org/",
17846
+ "year": 2014,
17847
+ "license": "published_methodology"
17848
+ },
17849
+ "tags": [
17850
+ "discovery",
17851
+ "matrix"
17852
+ ],
17853
+ "slots": [
17854
+ {
17855
+ "label": "Push of Current Situation",
17856
+ "entityTypeId": "need",
17857
+ "role": "push",
17858
+ "description": "Place need entities in the Push of Current Situation position of the matrix"
17859
+ },
17860
+ {
17861
+ "label": "Pull of New Solution",
17862
+ "entityTypeId": "desired_outcome",
17863
+ "role": "pull",
17864
+ "description": "Place desired outcome entities in the Pull of New Solution position of the matrix"
17865
+ },
17866
+ {
17867
+ "label": "Anxiety of New Solution",
17868
+ "entityTypeId": "switching_cost",
17869
+ "role": "anxiety",
17870
+ "description": "Place switching cost entities in the Anxiety of New Solution position of the matrix"
17871
+ },
17872
+ {
17873
+ "label": "Habit of Current Situation",
17874
+ "entityTypeId": "switching_cost",
17875
+ "role": "habit",
17876
+ "description": "Place switching cost entities in the Habit of Current Situation position of the matrix"
17877
+ }
17878
+ ],
17879
+ "data": {
17880
+ "entity_types": [
17881
+ {
17882
+ "type": "need",
17883
+ "role": "bucket"
17884
+ },
17885
+ {
17886
+ "type": "switching_cost",
17887
+ "role": "bucket"
17888
+ },
17889
+ {
17890
+ "type": "desired_outcome",
17891
+ "role": "bucket"
17892
+ }
17893
+ ],
17894
+ "required_properties": {}
17895
+ },
17896
+ "structure": {
17897
+ "pattern": "matrix"
17898
+ },
17899
+ "presentation": {
17900
+ "layout": {
17901
+ "type": "matrix",
17902
+ "rows": 2,
17903
+ "cols": 2
17904
+ },
17905
+ "sort_by": {
17906
+ "property": "title",
17907
+ "direction": "asc"
17908
+ },
17909
+ "colour_by": "group",
17910
+ "card_fields": [
17911
+ "title",
17912
+ "description"
17913
+ ]
17914
+ },
17915
+ "education": {
17916
+ "purpose": "Map the four forces that drive or resist a customer's switch to a new solution (Push, Pull, Anxiety, Habit) to understand why people change (or don't).",
17917
+ "core_question": "Are the push and pull forces strong enough to overcome the anxiety of the new and the comfort of the familiar?",
17918
+ "when_to_use": [
17919
+ "You need to understand unmet user needs before committing to solutions",
17920
+ "The problem space is ambiguous and requires structured exploration",
17921
+ "You want to reduce the risk of building the wrong thing"
17922
+ ],
17923
+ "when_not_to_use": [
17924
+ "The solution is well-understood and validated",
17925
+ "You are in a delivery phase with clear requirements"
17926
+ ]
17927
+ }
17593
17928
  }
17594
17929
  ];
17595
17930
  var UPG_FRAMEWORKS_BY_ID = Object.fromEntries(
@@ -18036,6 +18371,326 @@ function isUPGDocument(doc) {
18036
18371
  return validateUPGDocument(doc).valid;
18037
18372
  }
18038
18373
 
18374
+ // src/presentation/entity-emoji.ts
18375
+ var DEFAULT_ENTITY_EMOJI = "\u{1F4E6}";
18376
+ var ENTITY_EMOJI = {
18377
+ a11y_annotation: "\u{1F9BB}",
18378
+ a11y_audit: "\u267F",
18379
+ a11y_guideline: "\u{1F9AF}",
18380
+ a11y_issue: "\u{1F6AB}",
18381
+ a11y_standard: "\u{1F4CF}",
18382
+ acceptance_criterion: "\u2705",
18383
+ access_policy: "\u{1F511}",
18384
+ account: "\u{1F3E6}",
18385
+ acquisition_channel: "\u{1F3A3}",
18386
+ ad_creative: "\u{1F58C}\uFE0F",
18387
+ affinity_cluster: "\u{1F9F2}",
18388
+ agent_definition: "\u{1F9BE}",
18389
+ agent_hook: "\u{1F9F7}",
18390
+ agent_session: "\u{1F9D1}\u200D\u{1F4BB}",
18391
+ agent_skill: "\u{1FA84}",
18392
+ agent_task: "\u{1F3AB}",
18393
+ aggregate: "\u{1FAD9}",
18394
+ ai_cost_tracker: "\u{1F4B8}",
18395
+ ai_dataset: "\u{1FA86}",
18396
+ ai_experiment: "\u{1F47E}",
18397
+ ai_guardrail: "\u{1F6A6}",
18398
+ ai_model: "\u{1F916}",
18399
+ ai_trace: "\u{1FAA1}",
18400
+ alert_rule: "\u{1F6CE}\uFE0F",
18401
+ annotation: "\u{1F5EF}\uFE0F",
18402
+ api_contract: "\u{1F91D}",
18403
+ api_ecosystem: "\u{1F578}\uFE0F",
18404
+ api_endpoint: "\u{1F50C}",
18405
+ approval_record: "\u{1F50F}",
18406
+ assumption: "\u{1F914}",
18407
+ attribution_model: "\u{1F575}\uFE0F",
18408
+ audit_log_policy: "\u{1FAB5}",
18409
+ behavioral_segment: "\u{1F43E}",
18410
+ beta_program: "\u{1F423}",
18411
+ bounded_context: "\u{1F532}",
18412
+ brand_asset: "\u{1F5C2}\uFE0F",
18413
+ brand_colour: "\u{1F308}",
18414
+ brand_identity: "\u{1F4A0}",
18415
+ brand_imagery: "\u{1F5BC}\uFE0F",
18416
+ brand_logo: "\u{1F537}",
18417
+ brand_typography: "\u{1F524}",
18418
+ brand_voice: "\u{1F399}\uFE0F",
18419
+ bug: "\u{1F41B}",
18420
+ build_artifact: "\u{1F3FA}",
18421
+ business_model: "\u{1F4B0}",
18422
+ capability: "\u{1F4AA}",
18423
+ capacity_plan: "\u{1F5D3}\uFE0F",
18424
+ ceremony: "\u{1F514}",
18425
+ certification: "\u{1F3F5}\uFE0F",
18426
+ change_request: "\u270F\uFE0F",
18427
+ changelog: "\u{1F570}\uFE0F",
18428
+ churn_reason: "\u{1F494}",
18429
+ ci_pipeline: "\u{1F687}",
18430
+ classification_axis: "\u2194\uFE0F",
18431
+ classification_value: "\u{1F4CD}",
18432
+ code_repository: "\u{1F4BE}",
18433
+ cohort: "\u{1F465}",
18434
+ command: "\u2328\uFE0F",
18435
+ community_initiative: "\u{1F30D}",
18436
+ competitive_analysis: "\u{1F4CA}",
18437
+ competitive_battle_card: "\u2694\uFE0F",
18438
+ competitor: "\u{1F94A}",
18439
+ competitor_feature: "\u{1F52C}",
18440
+ compliance_framework: "\u{1F3DF}\uFE0F",
18441
+ compliance_requirement: "\u26F2",
18442
+ constraint: "\u{1F512}",
18443
+ contact: "\u{1F4C7}",
18444
+ content_calendar: "\u{1F4C5}",
18445
+ content_piece: "\u{1F5D2}\uFE0F",
18446
+ content_strategy: "\u270D\uFE0F",
18447
+ content_theme: "\u{1F4A1}",
18448
+ contract: "\u{1F4D1}",
18449
+ contract_clause: "\xA7",
18450
+ cost_structure: "\u{1F9EE}",
18451
+ cultural_adaptation: "\u{1F30F}",
18452
+ customer_feedback: "\u{1F536}",
18453
+ customer_health_score: "\u{1F49A}",
18454
+ customer_journey_stage: "\u{1F68F}",
18455
+ customer_relationship: "\u{1FAF6}",
18456
+ dashboard: "\u{1F39B}\uFE0F",
18457
+ data_classification: "\u{1F343}",
18458
+ data_contract: "\u{1F523}",
18459
+ data_domain: "\u{1F3F7}\uFE0F",
18460
+ data_flow: "\u2195\uFE0F",
18461
+ data_lineage: "\u{1F333}",
18462
+ data_model: "\u{1F5C3}\uFE0F",
18463
+ data_pipeline: "\u{1FAA3}",
18464
+ data_product: "\u{1F381}",
18465
+ data_quality_rule: "\u{1F9F9}",
18466
+ data_source: "\u{1F6E2}\uFE0F",
18467
+ database_schema: "\u{1F5C4}\uFE0F",
18468
+ deal: "\u{1F4BC}",
18469
+ decision: "\u2696\uFE0F",
18470
+ deliverable: "\u{1F380}",
18471
+ demand_gen_program: "\u{1F4E3}",
18472
+ department: "\u{1F3EC}",
18473
+ dependency: "\u26D3\uFE0F",
18474
+ deployment: "\u{1F4E4}",
18475
+ design_component: "\u{1F9F1}",
18476
+ design_concept: "\u{1F331}",
18477
+ design_guideline: "\u{1F4CC}",
18478
+ design_pattern: "\u{1F9E9}",
18479
+ design_question: "\u{1F4AD}",
18480
+ design_sprint: "\u{1F3C3}",
18481
+ design_system: "\u{1F9F0}",
18482
+ design_token: "\u{1FA99}",
18483
+ desired_outcome: "\u{1F31F}",
18484
+ developer_portal: "\u{1F391}",
18485
+ discount_strategy: "\u2702\uFE0F",
18486
+ distribution_channel: "\u{1F69A}",
18487
+ document: "\u{1F4C3}",
18488
+ documentation_template: "\u{1F58A}\uFE0F",
18489
+ domain_entity: "\u{1F4E6}",
18490
+ domain_event: "\u{1F4E1}",
18491
+ education_program: "\u{1F3EB}",
18492
+ email_sequence: "\u{1F4E7}",
18493
+ epic: "\u{1F4DC}",
18494
+ error_budget: "\u23F3",
18495
+ eval_benchmark: "\u{1F396}\uFE0F",
18496
+ eval_run: "\u{1F39F}\uFE0F",
18497
+ event: "\u{1F388}",
18498
+ event_schema: "\u{1F520}",
18499
+ evidence: "\u{1F50E}",
18500
+ experiment: "\u{1F9EB}",
18501
+ experiment_plan: "\u{1F4D0}",
18502
+ experiment_run: "\u25B6\uFE0F",
18503
+ external_api: "\u{1F310}",
18504
+ feasibility_study: "\u{1F3D7}\uFE0F",
18505
+ feature: "\u2B50",
18506
+ feature_area: "\u{1F4C1}",
18507
+ feature_flag: "\u{1F38C}",
18508
+ feature_request: "\u{1F64F}",
18509
+ feedback_program: "\u{1F3A4}",
18510
+ feedback_theme: "\u{1F4CE}",
18511
+ feedback_vote: "\u{1F44D}",
18512
+ fix: "\u{1FA9B}",
18513
+ forecast: "\u{1F52E}",
18514
+ framework_exercise: "\u{1F4CB}",
18515
+ funnel: "\u2B07\uFE0F",
18516
+ funnel_step: "\u{1F53D}",
18517
+ glossary_term: "\u{1F4D6}",
18518
+ growth_campaign: "\u{1F4E2}",
18519
+ growth_loop: "\u267E\uFE0F",
18520
+ gtm_strategy: "\u{1F3F9}",
18521
+ hallucination_report: "\u{1F47B}",
18522
+ help_video: "\u{1F3AC}",
18523
+ hypothesis: "\u{1F9EA}",
18524
+ ideal_customer_profile: "\u{1F464}",
18525
+ incident: "\u{1F6A8}",
18526
+ infrastructure_component: "\u{1F5A7}",
18527
+ initiative: "\u{1F680}",
18528
+ insight: "\u{1F526}",
18529
+ integration_partner: "\u{1F5FF}",
18530
+ integration_pattern: "\u{1F517}",
18531
+ interaction_spec: "\u{1F5B1}\uFE0F",
18532
+ interview_guide: "\u{1F4CB}",
18533
+ investigation: "\u{1F50D}",
18534
+ invoice: "\u{1F4B3}",
18535
+ ip_asset: "\xA9\uFE0F",
18536
+ job: "\u{1F528}",
18537
+ job_step: "\u{1F463}",
18538
+ journey_action: "\u26A1",
18539
+ journey_phase: "\u{1F516}",
18540
+ journey_step: "\u{1FA9C}",
18541
+ key_activity: "\u{1F6E0}\uFE0F",
18542
+ key_resource: "\u{1F3ED}",
18543
+ key_result: "\u{1F4C8}",
18544
+ knowledge_base_article: "\u{1F4D3}",
18545
+ launch: "\u{1F6F8}",
18546
+ lead: "\u{1F33F}",
18547
+ learning: "\u{1F9E0}",
18548
+ learning_path: "\u{1F97E}",
18549
+ legal_entity: "\u{1F3E2}",
18550
+ library_dependency: "\u{1F4DA}",
18551
+ locale: "\u{1F30E}",
18552
+ locale_config: "\u{1F5FE}",
18553
+ market_segment: "\u{1F3AF}",
18554
+ market_trend: "\u{1F4C9}",
18555
+ marketing_campaign_plan: "\u{1F4C6}",
18556
+ marketing_channel: "\u{1F4FB}",
18557
+ marketing_strategy: "\u{1F531}",
18558
+ marketplace_listing: "\u{1F6D2}",
18559
+ messaging: "\u2709\uFE0F",
18560
+ metric: "\u{1F522}",
18561
+ metric_quality_assessment: "\u{1FA7A}",
18562
+ milestone: "\u26F3",
18563
+ mission: "\u{1F9ED}",
18564
+ model_comparison: "\u{1F504}",
18565
+ monitor: "\u{1F4FA}",
18566
+ need: "\u{1FAC0}",
18567
+ nps_campaign: "\u{1F60A}",
18568
+ objection: "\u{1F6A7}",
18569
+ objective: "\u{1F3C1}",
18570
+ observation: "\u{1F441}\uFE0F",
18571
+ on_call_rotation: "\u{1F3D5}\uFE0F",
18572
+ opportunity: "\u{1F6AA}",
18573
+ organization: "\u{1F3D9}\uFE0F",
18574
+ outcome: "\u{1F3C6}",
18575
+ participant: "\u{1F64B}",
18576
+ partner_program: "\u{1F397}\uFE0F",
18577
+ partner_revenue_share: "\u{1F932}",
18578
+ partner_tier: "\u{1F948}",
18579
+ partnership: "\u{1FAF1}\u{1F3FB}\u200D\u{1FAF2}\u{1F3FC}",
18580
+ paywall: "\u{1F6C2}",
18581
+ penetration_test: "\u{1F5E1}\uFE0F",
18582
+ person: "\u{1F9D1}",
18583
+ persona: "\u{1F3AD}",
18584
+ pipeline_sales: "\u{1FA88}",
18585
+ pipeline_stage: "\u{1F9FD}",
18586
+ playbook: "\u{1F4D2}",
18587
+ portfolio: "\u{1F9F8}",
18588
+ positioning: "\u{1F3AA}",
18589
+ postmortem: "\u{1FA7B}",
18590
+ press_release: "\u{1F5DE}\uFE0F",
18591
+ pricing_strategy: "\u{1F4B1}",
18592
+ pricing_tier: "\u{1F949}",
18593
+ primitive: "\u{1F4CB}",
18594
+ privacy_policy: "\u{1F6E1}\uFE0F",
18595
+ product: "\u{1F9EC}",
18596
+ product_area: "\u{1FA80}",
18597
+ program: "\u{1F6CB}\uFE0F",
18598
+ project: "\u{1F9F3}",
18599
+ prompt_template: "\u2712\uFE0F",
18600
+ prompt_version: "\u{1F5E8}\uFE0F",
18601
+ proof_point: "\u{1F9FE}",
18602
+ prototype: "\u{1F4F1}",
18603
+ qa_session: "\u{1F41E}",
18604
+ queue_topic: "\u{1F4EC}",
18605
+ quote: "\u{1F5E3}\uFE0F",
18606
+ quote_document: "\u{1F4B2}",
18607
+ read_model: "\u{1FA9F}",
18608
+ rebuttal: "\u21A9\uFE0F",
18609
+ regional_pricing: "\u{1F4B4}",
18610
+ regression_test: "\u267B\uFE0F",
18611
+ release: "\u{1F6A2}",
18612
+ release_strategy: "\u{1FA82}",
18613
+ report: "\u{1F4F0}",
18614
+ research_plan: "\u{1F5FA}\uFE0F",
18615
+ research_question: "\u2753",
18616
+ research_study: "\u{1F9D1}\u200D\u{1F52C}",
18617
+ resource_allocation: "\u{1F967}",
18618
+ retrospective: "\u{1FA9E}",
18619
+ revenue_stream: "\u{1F4B5}",
18620
+ review_gate: "\u{1F6A5}",
18621
+ risk: "\u{1F3B2}",
18622
+ risk_register: "\u{1F9EF}",
18623
+ roadmap: "\u{1F6E3}\uFE0F",
18624
+ roadmap_item: "\u{1F6A9}",
18625
+ roadmap_theme: "\u{1F3A8}",
18626
+ role: "\u{1FAAA}",
18627
+ root_cause: "\u{1FA9D}",
18628
+ runbook: "\u{1F4D8}",
18629
+ sales_motion: "\u{1F501}",
18630
+ screen: "\u{1F5A5}\uFE0F",
18631
+ screen_state: "\u{1F533}",
18632
+ security_audit: "\u{1F6C3}",
18633
+ security_control: "\u{1F39A}\uFE0F",
18634
+ security_policy: "\u{1F510}",
18635
+ security_review: "\u{1F9D0}",
18636
+ seo_keyword: "#\uFE0F\u20E3",
18637
+ service: "\u2699\uFE0F",
18638
+ service_blueprint: "\u{1F7E3}",
18639
+ service_level_agreement: "\u23F1\uFE0F",
18640
+ service_level_indicator: "\u{1F321}\uFE0F",
18641
+ service_level_objective: "\u{1F945}",
18642
+ skill: "\u{1F393}",
18643
+ social_post: "\u{1F426}",
18644
+ solution: "\u{1F527}",
18645
+ specification: "\u{1F4CB}",
18646
+ stakeholder: "\u{1F9D1}\u200D\u{1F4BC}",
18647
+ status_report: "\u{1F4C4}",
18648
+ strategic_pillar: "\u{1F3DB}\uFE0F",
18649
+ strategic_theme: "\u{1F9F5}",
18650
+ subscription: "\u{1F502}",
18651
+ success_milestone: "\u{1F389}",
18652
+ support_ticket: "\u{1F198}",
18653
+ survey_response: "\u{1F4E8}",
18654
+ switching_cost: "\u2693",
18655
+ symptom: "\u26A0\uFE0F",
18656
+ task: "\u2611\uFE0F",
18657
+ team: "\u{1FAC2}",
18658
+ team_okr: "\u{1F3C5}",
18659
+ technical_debt_item: "\u{1FAA4}",
18660
+ territory: "\u{1F3F4}",
18661
+ test_case: "\u{1F335}",
18662
+ test_coverage_report: "\u{1F38F}",
18663
+ test_environment: "\u2697\uFE0F",
18664
+ test_plan: "\u{1F4DD}",
18665
+ test_result: "\u{1F3B0}",
18666
+ test_suite: "\u{1F4C2}",
18667
+ threat: "\u2620\uFE0F",
18668
+ threat_model: "\u{1F3F4}\u200D\u2620\uFE0F",
18669
+ touchpoint: "\u{1F446}",
18670
+ translation_bundle: "\u{1F202}\uFE0F",
18671
+ translation_key: "\u{1F5DD}\uFE0F",
18672
+ trial_config: "\u{1F193}",
18673
+ tutorial: "\u{1F9D1}\u200D\u{1F3EB}",
18674
+ unit_economics: "\u{1F4B9}",
18675
+ user_advisory_board: "\u{1FAF5}",
18676
+ user_flow: "\u{1F500}",
18677
+ user_journey: "\u{1F6E4}\uFE0F",
18678
+ user_story: "\u{1F4AC}",
18679
+ value_object: "\u{1F48E}",
18680
+ value_proposition: "\u2728",
18681
+ value_stream: "\u{1F30A}",
18682
+ variant: "\u{1F18E}",
18683
+ vision: "\u{1F52D}",
18684
+ vulnerability: "\u{1F513}",
18685
+ walkthrough: "\u{1F6B6}",
18686
+ webinar: "\u{1F3A5}",
18687
+ wireframe: "\u25AD",
18688
+ workflow_artifact: "\u{1F5F3}\uFE0F",
18689
+ workflow_run: "\u23EF\uFE0F",
18690
+ workflow_template: "\u{1F3BB}",
18691
+ workspace: "\u{1F3E0}"
18692
+ };
18693
+
18039
18694
  // src/presentation/labels.ts
18040
18695
  var PRIORITY_LABELS = [
18041
18696
  // ── need (CONSOLIDATED: replaces pain_point + user_need) ─────────────────────
@@ -18949,6 +19604,7 @@ var UPG_TYPE_LABELS = UPG_ACTIVE_TYPES.map((typeName) => {
18949
19604
  };
18950
19605
  return {
18951
19606
  ...priority,
19607
+ emoji: ENTITY_EMOJI[typeName] ?? DEFAULT_ENTITY_EMOJI,
18952
19608
  alt_labels: [...priority.alt_labels, ...newAliases, ...slotAliases2],
18953
19609
  framework_labels: mergedFrameworkLabels
18954
19610
  };
@@ -18961,6 +19617,7 @@ var UPG_TYPE_LABELS = UPG_ACTIVE_TYPES.map((typeName) => {
18961
19617
  return {
18962
19618
  id: typeName,
18963
19619
  canonical_label: toTitleCase(typeName),
19620
+ emoji: ENTITY_EMOJI[typeName] ?? DEFAULT_ENTITY_EMOJI,
18964
19621
  alt_labels: [...standard.alt_labels, ...newAliases, ...slotAliases2],
18965
19622
  framework_labels: generated?.framework_labels ?? {}
18966
19623
  };
@@ -18969,6 +19626,7 @@ var UPG_TYPE_LABELS = UPG_ACTIVE_TYPES.map((typeName) => {
18969
19626
  return {
18970
19627
  id: typeName,
18971
19628
  canonical_label: toTitleCase(typeName),
19629
+ emoji: ENTITY_EMOJI[typeName] ?? DEFAULT_ENTITY_EMOJI,
18972
19630
  alt_labels: [...migrationAliases, ...slotAliases],
18973
19631
  framework_labels: generated?.framework_labels ?? {}
18974
19632
  };
@@ -24178,6 +24836,47 @@ var UPG_ANTI_PATTERNS = [
24178
24836
  stages: ["beta", "launch", "growth", "mature"],
24179
24837
  severity: "medium",
24180
24838
  source: { kind: "practitioner", attribution: "Marty Cagan, Inspired (product discovery)" }
24839
+ },
24840
+ // ── Foundations layer (0.9.13): portfolio-scoped, registry-aware ──────────
24841
+ // These read the shared registry + cross-product edges, so they are evaluated
24842
+ // by portfolio_validate, not the single-graph evaluator. They carry no
24843
+ // structured_condition (the detector is cross-product, not a single-graph
24844
+ // IntelligenceCondition).
24845
+ {
24846
+ id: "specification-without-implementer",
24847
+ since: "0.9.13",
24848
+ scope: "portfolio",
24849
+ name: "Specification without implementer",
24850
+ description: "A specification in the shared registry has no product, feature, or api_contract implementing or conforming to it anywhere in the portfolio. A specification nobody implements is a document, not a contract: it states an intent the portfolio never honours.",
24851
+ why_it_matters: "An unimplemented specification carries authority it has not earned. Teams cite it as a standard while no surface actually conforms, so conformance claims cannot be trusted or traced.",
24852
+ remediation: "Link at least one product, feature, or api_contract to the specification via `product_implements_specification`, `product_exposes_specification`, `feature_conforms_to_specification`, or `api_contract_speaks_specification`; or retire the specification from the registry.",
24853
+ stages: ["validation", "build", "beta", "launch", "growth", "mature"],
24854
+ severity: "medium",
24855
+ source: { kind: "fundamental" }
24856
+ },
24857
+ {
24858
+ id: "primitive-scattered-without-canonical",
24859
+ since: "0.9.13",
24860
+ scope: "portfolio",
24861
+ name: "Primitive scattered without a canonical",
24862
+ description: "The same primitive concept appears as a product-local node in two or more products, but no canonical primitive in the shared registry unifies them. Each product redefines the building block on its own terms, so the portfolio carries several drifting copies of one shared idea instead of a single authoritative definition.",
24863
+ why_it_matters: "Scattered primitives drift apart in name, shape, and meaning. Cross-product reasoning breaks because the same concept reads as several unrelated entities, and a change to the shared building block has no single place to land.",
24864
+ remediation: "Define the shared primitive once in the registry with `define_canonical_entity`, then link each product copy via `register_instance` so the building block has one authoritative definition.",
24865
+ stages: ["build", "beta", "launch", "growth", "mature"],
24866
+ severity: "medium",
24867
+ source: { kind: "fundamental" }
24868
+ },
24869
+ {
24870
+ id: "product-reimplements-specification",
24871
+ since: "0.9.13",
24872
+ scope: "portfolio",
24873
+ name: "Specification reimplemented across products",
24874
+ description: "Two or more products independently implement the same registry specification rather than one depending on a shared implementation. Parallel implementations of a single contract multiply the surface that must stay in sync and usually signal a missing shared library or service.",
24875
+ why_it_matters: "Every independent reimplementation of a specification is another place a conformance bug can hide and another copy that drifts from the contract. The cost of a spec change scales with the number of reimplementers.",
24876
+ remediation: "Consolidate onto one implementation that the others depend on (`depends_on_product` / `hosts`), or confirm the duplication is deliberate and record why. Capture the stewarding organization with `create_registry_edge` so the contract has an owner.",
24877
+ stages: ["build", "beta", "launch", "growth", "mature"],
24878
+ severity: "low",
24879
+ source: { kind: "fundamental" }
24181
24880
  }
24182
24881
  ];
24183
24882
  function getAntiPatternById(id) {
@@ -24201,6 +24900,7 @@ function evaluateAntiPatterns(inputs, options) {
24201
24900
  const idFilter = options?.anti_pattern_ids ? new Set(options.anti_pattern_ids) : void 0;
24202
24901
  const fires = [];
24203
24902
  for (const ap of UPG_ANTI_PATTERNS) {
24903
+ if (ap.scope === "portfolio" || !ap.structured_condition) continue;
24204
24904
  if (severityFilter && ap.severity !== severityFilter) continue;
24205
24905
  if (idFilter && !idFilter.has(ap.id)) continue;
24206
24906
  if (inputs.productStage && !ap.stages.includes(inputs.productStage)) {
@@ -24361,6 +25061,7 @@ function buildViolation(ap) {
24361
25061
  }
24362
25062
  function collectTargetEntities(cond) {
24363
25063
  const types = /* @__PURE__ */ new Set();
25064
+ if (!cond) return [];
24364
25065
  walk(cond);
24365
25066
  return [...types].sort();
24366
25067
  function walk(c) {
@@ -27237,7 +27938,7 @@ function isCanonical(text) {
27237
27938
  }
27238
27939
 
27239
27940
  // src/index.ts
27240
- var UPG_VERSION = "0.9.12";
27941
+ var UPG_VERSION = "0.9.14";
27241
27942
  var UPG_FORMAT_VERSION = "0.4.0";
27242
27943
  var MARKDOWN_FORMAT_VERSION = "0.1";
27243
27944
  var UPG_TYPES = getTypes();
@@ -27306,8 +28007,10 @@ export {
27306
28007
  BUSINESS_GTM_GROWTH_PLAYBOOK,
27307
28008
  BUSINESS_MARKETING_AUDIENCE_FIRST_PLAYBOOK,
27308
28009
  CONTENT_DEPTH_WARNING_RULES,
28010
+ DEFAULT_ENTITY_EMOJI,
27309
28011
  DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK,
27310
28012
  ENGINEERING_PLATFORM_PLAYBOOK,
28013
+ ENTITY_EMOJI,
27311
28014
  EXPERIENCE_DESIGN_BRAND_PLAYBOOK,
27312
28015
  FOUNDATIONS_PLAYBOOK,
27313
28016
  LEGACY_PRODUCT_STAGES,