@unified-product-graph/core 0.9.6 → 0.9.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
@@ -514,7 +514,9 @@ var UPG_ENTITY_META = [
514
514
  { name: "objective", type_id: "ent_004", maturity: "stable", since: "0.1.0" },
515
515
  { name: "key_result", type_id: "ent_005", maturity: "stable", since: "0.1.0" },
516
516
  { name: "metric", type_id: "ent_006", maturity: "stable", since: "0.1.0" },
517
- { name: "metric_quality_assessment", type_id: "ent_339", maturity: "proposed", since: "0.2.2" },
517
+ // F7 (UPG-673): graduated proposed → stable at v0.9.x — proposed since 0.2.2,
518
+ // the metric-quality assessment artefact is settled with no open restructure.
519
+ { name: "metric_quality_assessment", type_id: "ent_339", maturity: "stable", since: "0.2.2" },
518
520
  { name: "vision", type_id: "ent_007", maturity: "stable", since: "0.1.0" },
519
521
  { name: "mission", type_id: "ent_008", maturity: "stable", since: "0.1.0" },
520
522
  { name: "strategic_theme", type_id: "ent_009", maturity: "stable", since: "0.1.0" },
@@ -571,8 +573,11 @@ var UPG_ENTITY_META = [
571
573
  { name: "market_segment", type_id: "ent_036", maturity: "stable", since: "0.1.0" },
572
574
  { name: "competitive_analysis", type_id: "ent_037", maturity: "stable", since: "0.1.0" },
573
575
  // Classification taxonomy hosted by competitive_analysis.
574
- { name: "classification_axis", type_id: "ent_346", maturity: "proposed", since: "0.4.0" },
575
- { name: "classification_value", type_id: "ent_347", maturity: "proposed", since: "0.4.0" },
576
+ // F7 (UPG-673): graduated proposed → stable at v0.9.x — two minor releases
577
+ // stable since 0.4.0, the taxonomy-axis/value pair backs the competitive-
578
+ // analysis classification spine with no open rename/restructure ticket.
579
+ { name: "classification_axis", type_id: "ent_346", maturity: "stable", since: "0.4.0" },
580
+ { name: "classification_value", type_id: "ent_347", maturity: "stable", since: "0.4.0" },
576
581
  // ── UX Research ──
577
582
  { name: "research_study", type_id: "ent_038", maturity: "stable", since: "0.1.0" },
578
583
  { name: "research_insight", type_id: "ent_039", maturity: "deprecated", since: "0.1.0", deprecated_in: "0.1.0", replacement: "insight" },
@@ -612,8 +617,10 @@ var UPG_ENTITY_META = [
612
617
  { name: "journey_phase", type_id: "ent_330", maturity: "proposed", since: "0.2.0" },
613
618
  { name: "journey_action", type_id: "ent_331", maturity: "proposed", since: "0.2.0" },
614
619
  { name: "design_decision", type_id: "ent_319", maturity: "deprecated", since: "0.2.0", deprecated_in: "0.2.0", replacement: "decision" },
615
- { name: "brand_logo", type_id: "ent_321", maturity: "proposed", since: "0.2.0" },
616
- { name: "brand_imagery", type_id: "ent_322", maturity: "proposed", since: "0.2.0" },
620
+ // F7 (UPG-673): graduated proposed → stable at v0.9.x — proposed since 0.2.0,
621
+ // the brand-identity set (logo + imagery) is settled with no open rename.
622
+ { name: "brand_logo", type_id: "ent_321", maturity: "stable", since: "0.2.0" },
623
+ { name: "brand_imagery", type_id: "ent_322", maturity: "stable", since: "0.2.0" },
617
624
  // ── Product Spec ──
618
625
  { name: "feature_area", type_id: "ent_314", maturity: "stable", since: "0.1.0" },
619
626
  { name: "feature", type_id: "ent_071", maturity: "stable", since: "0.1.0" },
@@ -629,6 +636,15 @@ var UPG_ENTITY_META = [
629
636
  // alias. `story_task` (the original work half) was already collapsed into
630
637
  // canonical `task` at v0.4.0. So the canonical shape is: user_story (statement)
631
638
  // + task (work), linked by `task_implements_user_story`.
639
+ //
640
+ // F7 (UPG-673) — DEFERRED, deliberately kept `proposed`. The audit flagged
641
+ // user_story as a stable-spine candidate, but the v0.7.0 re-canon contract
642
+ // (UPG-571) freezes maturity at `proposed` until the re-canonicalised name
643
+ // has soaked across a full migration window. `user-story-split.test.ts`
644
+ // ("user_story is canonical again (ent_073, proposed, not deprecated)")
645
+ // asserts `proposed` as the post-re-canon invariant. Graduating here would
646
+ // break that contract; promotion is a separate, ticketed decision once the
647
+ // story_statement → user_story migration has fully aged out.
632
648
  { name: "user_story", type_id: "ent_073", maturity: "proposed", since: "0.1.0" },
633
649
  { name: "story_statement", type_id: "ent_342", maturity: "deprecated", since: "0.2.7", deprecated_in: "0.7.0", replacement: "user_story" },
634
650
  { name: "story_task", type_id: "ent_343", maturity: "deprecated", since: "0.2.7", deprecated_in: "0.4.0", replacement: "task" },
@@ -1645,8 +1661,11 @@ var UPG_EDGE_CATALOG = {
1645
1661
  value_proposition_targets_persona_cross_domain: { forward_verb: "targets", reverse_verb: "targeted_by", classification: "cross-domain", source_type: "value_proposition", target_type: "persona" },
1646
1662
  revenue_stream_drives_metric: { forward_verb: "drives", reverse_verb: "driven_by", classification: "cross-domain", source_type: "revenue_stream", target_type: "metric" },
1647
1663
  // Ring 5 structural edges
1648
- funnel_step_maps_to_journey_step: { forward_verb: "maps_to", reverse_verb: "mapped_by", classification: "cross-domain", source_type: "funnel", target_type: "journey_step" },
1649
- customer_journey_stage_contains_funnel_step: { forward_verb: "contains", reverse_verb: "contained_in", classification: "cross-domain", source_type: "customer_journey_stage", target_type: "funnel" },
1664
+ // (UPG-668, P-I) These three edges name `funnel_step` but were typed against
1665
+ // `funnel`, so they resolved from the wrong side and were invisible on the
1666
+ // funnel_step card. Repointed to `funnel_step`; keys unchanged.
1667
+ funnel_step_maps_to_journey_step: { forward_verb: "maps_to", reverse_verb: "mapped_by", classification: "cross-domain", source_type: "funnel_step", target_type: "journey_step" },
1668
+ customer_journey_stage_contains_funnel_step: { forward_verb: "contains", reverse_verb: "contained_in", classification: "cross-domain", source_type: "customer_journey_stage", target_type: "funnel_step" },
1650
1669
  customer_journey_stage_spans_journey_step: { forward_verb: "spans", reverse_verb: "spanned_by", classification: "cross-domain", source_type: "customer_journey_stage", target_type: "journey_step" },
1651
1670
  dependency_blocks_team: { forward_verb: "blocks", reverse_verb: "blocked_by", classification: "cross-domain", source_type: "dependency", target_type: "team" },
1652
1671
  dependency_depends_on_team: { forward_verb: "depends_on", reverse_verb: "depended_on_by", classification: "cross-domain", source_type: "dependency", target_type: "team" },
@@ -1699,7 +1718,7 @@ var UPG_EDGE_CATALOG = {
1699
1718
  positioning_within_market_segment: { forward_verb: "within", reverse_verb: "positioned_by", classification: "cross-domain", source_type: "positioning", target_type: "market_segment" },
1700
1719
  ideal_customer_profile_targets_market_segment: { forward_verb: "targets", reverse_verb: "targeted_by", classification: "cross-domain", source_type: "ideal_customer_profile", target_type: "market_segment" },
1701
1720
  launch_amplified_by_marketing_channel: { forward_verb: "amplified_by", reverse_verb: "amplifies", classification: "cross-domain", source_type: "launch", target_type: "marketing_channel" },
1702
- sales_motion_qualifies_via_funnel_step: { forward_verb: "qualifies_via", reverse_verb: "qualifies_for", classification: "cross-domain", source_type: "sales_motion", target_type: "funnel" },
1721
+ sales_motion_qualifies_via_funnel_step: { forward_verb: "qualifies_via", reverse_verb: "qualifies_for", classification: "cross-domain", source_type: "sales_motion", target_type: "funnel_step" },
1703
1722
  objection_sourced_from_quote: { forward_verb: "sourced_from", reverse_verb: "surfaced_objection", classification: "cross-domain", source_type: "objection", target_type: "quote" },
1704
1723
  proof_point_derived_from_evidence: { forward_verb: "derived_from", reverse_verb: "evidences", classification: "cross-domain", source_type: "proof_point", target_type: "evidence" },
1705
1724
  proof_point_derived_from_insight: { forward_verb: "derived_from", reverse_verb: "evidences", classification: "cross-domain", source_type: "proof_point", target_type: "insight" },
@@ -2713,7 +2732,104 @@ var UPG_EDGE_CATALOG = {
2713
2732
  // to `journey_step_reveals_need` (existing); both express "what
2714
2733
  // research surfaces at this step". Useful for any journey-based
2715
2734
  // research method (CX mapping, service blueprint, behavioural cohort).
2716
- journey_step_yields_observation: { forward_verb: "yields", reverse_verb: "yielded_in", classification: "cross-domain", source_type: "journey_step", target_type: "observation" }
2735
+ journey_step_yields_observation: { forward_verb: "yields", reverse_verb: "yielded_in", classification: "cross-domain", source_type: "journey_step", target_type: "observation" },
2736
+ // ── Part 11: F6 (UPG-672) dead-end & missing-bridge pass ────────────────────
2737
+ // P-A (scored / synthesis / verdict leaves with 0 outbound) + P-D (missing
2738
+ // forward bridges) from the 36-domain wiring audit. Every edge below closes a
2739
+ // confirmed dead-end or missing direction. Naming respects the F2 prefix gate
2740
+ // (key begins with its `source_type` as a whole token) and the F3 dup gate (no
2741
+ // source→target pair already in the catalog). Verified against the catalog at
2742
+ // build time; see the F6 commit body for the audit ledger references.
2743
+ // ── F6: Priority 1 — both-sides-verified cross-domain bridges ──────────────
2744
+ // data_classification ↔ privacy_policy (security SEC-3/L5 + legal). The
2745
+ // classification leaf reached only data_source; it could not reach the policy
2746
+ // that governs how it must be handled. A privacy_policy GOVERNS a data
2747
+ // classification (sets retention / handling rules for that sensitivity tier).
2748
+ data_classification_governed_by_privacy_policy: { forward_verb: "governed_by", reverse_verb: "governs", classification: "cross-domain", source_type: "data_classification", target_type: "privacy_policy" },
2749
+ // design_component → a11y conformance (design_system DS-3 + accessibility A).
2750
+ // The whole conformance DIRECTION was missing: a11y_issue → design_component
2751
+ // existed (defect points back), but no component → standard/guideline link
2752
+ // expressing "this component CONFORMS TO this rule". Both the testable
2753
+ // standard and the human-readable guideline are valid conformance targets.
2754
+ design_component_conforms_to_a11y_standard: { forward_verb: "conforms_to", reverse_verb: "governs_conformance_of", classification: "cross-domain", source_type: "design_component", target_type: "a11y_standard" },
2755
+ design_component_conforms_to_a11y_guideline: { forward_verb: "conforms_to", reverse_verb: "governs_conformance_of", classification: "cross-domain", source_type: "design_component", target_type: "a11y_guideline" },
2756
+ // feature_request → feature ship-closure (feedback + product_spec). A request
2757
+ // could reach an opportunity but never the feature that ships it, so the loop
2758
+ // from "user asked" to "we built it" had no closing edge. A feature_request
2759
+ // BECOMES a feature when the team commits to building it.
2760
+ feature_request_becomes_feature: { forward_verb: "becomes", reverse_verb: "originated_from", classification: "cross-domain", source_type: "feature_request", target_type: "feature" },
2761
+ // objective → outcome (OKR spine). objective reached key_result and metric but
2762
+ // not the outcome it exists to move; the strategic spine was severed at its
2763
+ // anchor (0 outbound to outcome). An objective ADVANCES an outcome. Intra-
2764
+ // domain (both in strategy) and directional → causal.
2765
+ objective_advances_outcome: { forward_verb: "advances", reverse_verb: "advanced_by", classification: "causal", source_type: "objective", target_type: "outcome" },
2766
+ // ── F6: Priority 2 — scored / synthesis / verdict dead-end leaves (P-A) ─────
2767
+ // desired_outcome (Ulwick-scored: importance × satisfaction) had 0 outbound —
2768
+ // the scores could not flow anywhere. An under-served desired_outcome REVEALS
2769
+ // an opportunity, and is QUANTIFIED BY the metric that tracks its satisfaction.
2770
+ desired_outcome_reveals_opportunity: { forward_verb: "reveals", reverse_verb: "revealed_by", classification: "cross-domain", source_type: "desired_outcome", target_type: "opportunity" },
2771
+ desired_outcome_quantified_by_metric: { forward_verb: "quantified_by", reverse_verb: "quantifies", classification: "cross-domain", source_type: "desired_outcome", target_type: "metric" },
2772
+ // feasibility_study + design_sprint: discovery VERDICTS with 0 outbound — they
2773
+ // could not reach the decision, solution, or learning they exist to produce.
2774
+ // A study/sprint INFORMS a decision, RECOMMENDS a solution, and PRODUCES a
2775
+ // learning. solution is intra-discovery (semantic); decision (strategy) and
2776
+ // learning (validation) are cross-domain.
2777
+ feasibility_study_informs_decision: { forward_verb: "informs", reverse_verb: "informed_by", classification: "cross-domain", source_type: "feasibility_study", target_type: "decision" },
2778
+ feasibility_study_recommends_solution: { forward_verb: "recommends", reverse_verb: "recommended_by", classification: "semantic", source_type: "feasibility_study", target_type: "solution" },
2779
+ feasibility_study_produces_learning: { forward_verb: "produces", reverse_verb: "produced_by", classification: "cross-domain", source_type: "feasibility_study", target_type: "learning" },
2780
+ design_sprint_informs_decision: { forward_verb: "informs", reverse_verb: "informed_by", classification: "cross-domain", source_type: "design_sprint", target_type: "decision" },
2781
+ design_sprint_recommends_solution: { forward_verb: "recommends", reverse_verb: "recommended_by", classification: "semantic", source_type: "design_sprint", target_type: "solution" },
2782
+ design_sprint_produces_learning: { forward_verb: "produces", reverse_verb: "produced_by", classification: "cross-domain", source_type: "design_sprint", target_type: "learning" },
2783
+ // affinity_cluster → observation (user_research). A cluster synthesised an
2784
+ // insight but could not OWN the raw observations it groups; the cluster's
2785
+ // membership was unrepresentable. Intra-domain ownership → hierarchy.
2786
+ affinity_cluster_groups_observation: { forward_verb: "groups", reverse_verb: "grouped_in", classification: "hierarchy", source_type: "affinity_cluster", target_type: "observation" },
2787
+ // feedback_theme → opportunity (feedback). A theme validated needs and
2788
+ // surfaced insights but could not point at the opportunity it implies — the
2789
+ // theme could not become actionable discovery input.
2790
+ feedback_theme_reveals_opportunity: { forward_verb: "reveals", reverse_verb: "revealed_by", classification: "cross-domain", source_type: "feedback_theme", target_type: "opportunity" },
2791
+ // competitor_feature → capability (market_intelligence). A competitor feature
2792
+ // inspired our solution/feature but could not map to the capability it
2793
+ // demonstrates — competitive capability benchmarking was unrepresentable.
2794
+ competitor_feature_benchmarks_capability: { forward_verb: "benchmarks", reverse_verb: "benchmarked_by", classification: "cross-domain", source_type: "competitor_feature", target_type: "capability" },
2795
+ // switching_cost → competitor (user). A switching cost is the friction of
2796
+ // leaving an incumbent, but the leaf had 0 outbound — it could not name the
2797
+ // competitor it locks the user into. It LOCKS IN a competitor.
2798
+ switching_cost_locks_in_competitor: { forward_verb: "locks_in", reverse_verb: "locked_in_by", classification: "cross-domain", source_type: "switching_cost", target_type: "competitor" },
2799
+ // ── F6: region tail — confirmed dead-end leaves across remaining domains ────
2800
+ // test_result (testing) had 0 outbound — a failing result could not file the
2801
+ // defect it found. A test_result REPORTS a bug.
2802
+ test_result_reports_bug: { forward_verb: "reports", reverse_verb: "reported_by", classification: "cross-domain", source_type: "test_result", target_type: "bug" },
2803
+ // content_piece → social_post (content → marketing). Content reached messaging
2804
+ // and campaigns but not the social post it is repurposed into — the atomisation
2805
+ // step had no edge.
2806
+ content_piece_repurposed_as_social_post: { forward_verb: "repurposed_as", reverse_verb: "repurposed_from", classification: "cross-domain", source_type: "content_piece", target_type: "social_post" },
2807
+ // translation_key (localisation) had 0 outbound — it could neither reach the
2808
+ // content it localises nor the locale it targets. Both bridges close the leaf.
2809
+ // translation_key → content_piece is cross-domain; → locale is intra-domain.
2810
+ translation_key_localises_content_piece: { forward_verb: "localises", reverse_verb: "localised_by", classification: "cross-domain", source_type: "translation_key", target_type: "content_piece" },
2811
+ translation_key_targets_locale: { forward_verb: "targets", reverse_verb: "targeted_by", classification: "semantic", source_type: "translation_key", target_type: "locale" },
2812
+ // partner_revenue_share → revenue_stream (ecosystem → business_model). The
2813
+ // share governed a partner tier but never fed the revenue stream it
2814
+ // contributes to — partner economics could not roll up to the model.
2815
+ partner_revenue_share_feeds_revenue_stream: { forward_verb: "feeds", reverse_verb: "fed_by", classification: "cross-domain", source_type: "partner_revenue_share", target_type: "revenue_stream" },
2816
+ // retrospective (team_org) had 0 outbound — its outputs (learnings, decisions/
2817
+ // action items) could not leave the ceremony. A retrospective PRODUCES a
2818
+ // learning and YIELDS a decision. Both targets cross-domain.
2819
+ retrospective_produces_learning: { forward_verb: "produces", reverse_verb: "produced_in", classification: "cross-domain", source_type: "retrospective", target_type: "learning" },
2820
+ retrospective_yields_decision: { forward_verb: "yields", reverse_verb: "decided_in", classification: "cross-domain", source_type: "retrospective", target_type: "decision" },
2821
+ // status_report → milestone (program_mgmt). A report had 0 outbound; it could
2822
+ // not name the milestone whose status it reports. Intra-domain → semantic.
2823
+ status_report_reports_on_milestone: { forward_verb: "reports_on", reverse_verb: "reported_in", classification: "semantic", source_type: "status_report", target_type: "milestone" },
2824
+ // quote_document → deal (sales). A quote had 0 outbound; it could not advance
2825
+ // the deal it prices. Intra-domain and directional → causal.
2826
+ quote_document_advances_deal: { forward_verb: "advances", reverse_verb: "advanced_by", classification: "causal", source_type: "quote_document", target_type: "deal" },
2827
+ // data_quality_rule → data_source (data_analytics). A quality rule had 0
2828
+ // outbound; it could not name the source it governs. Intra-domain → semantic.
2829
+ data_quality_rule_governs_data_source: { forward_verb: "governs", reverse_verb: "governed_by", classification: "semantic", source_type: "data_quality_rule", target_type: "data_source" },
2830
+ // press_release → launch (marketing → go_to_market). A press release had 0
2831
+ // outbound; it could not name the launch it announces.
2832
+ press_release_announces_launch: { forward_verb: "announces", reverse_verb: "announced_by", classification: "cross-domain", source_type: "press_release", target_type: "launch" }
2717
2833
  };
2718
2834
  var UPG_POLYMORPHIC_EDGE_KEYS = [
2719
2835
  // Universal semantic verbs
@@ -2777,7 +2893,10 @@ var UPG_CROSS_EDGE_TYPES = [
2777
2893
  "succeeds",
2778
2894
  "hosts",
2779
2895
  "contributes_to",
2780
- "instance_of"
2896
+ "instance_of",
2897
+ "area_serves_persona",
2898
+ "area_targets_market_segment",
2899
+ "rolls_up_to"
2781
2900
  ];
2782
2901
  var REGISTRY_PRODUCT_ID = "registry";
2783
2902
 
@@ -3062,7 +3181,11 @@ var UPG_VALID_CHILDREN = {
3062
3181
  "survey_response"
3063
3182
  ],
3064
3183
  observation: ["quote"],
3065
- affinity_cluster: ["insight"],
3184
+ // F6 (UPG-672): affinity_cluster owns the observations it groups, in addition
3185
+ // to the insights it synthesises. Pairs with `affinity_cluster_groups_observation`
3186
+ // in the edge catalog (hierarchy). An observation can be both directly owned by
3187
+ // its research_study and grouped under an affinity_cluster (multi-parent grammar).
3188
+ affinity_cluster: ["insight", "observation"],
3066
3189
  // insight refines into insight; a raw insight can be distilled
3067
3190
  // into a more specific insight (refines_into chain).
3068
3191
  // v0.5.8 (UPG-528 Part 2d): insights own their evidencing quotes;
@@ -10280,6 +10403,7 @@ var UPG_PROPERTY_SCHEMA = {
10280
10403
  },
10281
10404
  // LearningPathProperties: Learning path.
10282
10405
  learning_path: {
10406
+ path_order: { type: "number", description: "Display order of this path within a curriculum or program (0-indexed). The scalar ordering convention shared with `journey_step.step_order` and `journey_action.action_order` (UPG-663 / UPG-674). Makes a learning_path a deterministically orderable sequence among sibling paths rather than a star." },
10283
10407
  path_difficulty: { type: "string", enum: ["beginner", "intermediate", "advanced"], description: "Overall difficulty level of the learning path" },
10284
10408
  item_count: { type: "number", description: "Number of items (tutorials, videos, etc.) in the path" },
10285
10409
  estimated_hours: { type: "number", description: "Estimated total hours to complete the path" },
@@ -10429,6 +10553,7 @@ var UPG_PROPERTY_SCHEMA = {
10429
10553
  },
10430
10554
  // MilestoneProperties: Milestone.
10431
10555
  milestone: {
10556
+ milestone_order: { type: "number", description: "Display order of this milestone within its parent project (0-indexed). The scalar ordering convention shared with `journey_step.step_order` and `journey_action.action_order` (UPG-663 / UPG-674). Orders the delivery milestones a project moves through, independent of `due_date`." },
10432
10557
  due_date: { type: "string", description: "Target due date (ISO format)" },
10433
10558
  met_on_time: { type: "boolean", description: "Whether the milestone was met on time" }
10434
10559
  },
@@ -10633,6 +10758,7 @@ var UPG_PROPERTY_SCHEMA = {
10633
10758
  },
10634
10759
  // PartnerTierProperties: Partner tier.
10635
10760
  partner_tier: {
10761
+ tier_order: { type: "number", description: "Display order of this tier among sibling partner tiers (1 = first tier shown). Mirrors `pricing_tier.tier_order`; part of the spec-wide `*_order` sequence convention (UPG-663 / UPG-674). Distinct from `tier_level`, which is a prestige rank, not a presentation order." },
10636
10762
  tier_level: { type: "number", description: "Numeric rank of the tier (higher = more prestigious)" },
10637
10763
  requirements: { type: "string[]", description: "What a partner must achieve to reach this tier" },
10638
10764
  benefits: { type: "string[]", description: "Benefits granted at this tier level" }
@@ -11055,6 +11181,7 @@ var UPG_PROPERTY_SCHEMA = {
11055
11181
  },
11056
11182
  // ScreenStateProperties: Specific state of a screen.
11057
11183
  screen_state: {
11184
+ state_order: { type: "number", description: "Display order of this state within its parent screen (0-indexed). The scalar ordering convention shared with `journey_step.step_order` and `journey_action.action_order` (UPG-663 / UPG-674). Orders the states a screen moves through (e.g. skeleton, loading, populated)." },
11058
11185
  state_name: { type: "string", enum: ["empty", "loading", "error", "populated", "skeleton", "partial"], description: "State" },
11059
11186
  trigger: { type: "string", description: "Cause for entering this state" },
11060
11187
  condition: { type: "string", description: "Data or environmental condition the state represents" },
@@ -11567,6 +11694,7 @@ var UPG_PROPERTY_SCHEMA = {
11567
11694
  },
11568
11695
  // UserFlowProperties: User flow.
11569
11696
  user_flow: {
11697
+ flow_order: { type: "number", description: "Display order of this flow among sibling flows (0-indexed). The scalar ordering convention shared with `journey_step.step_order` and `journey_action.action_order` (UPG-663 / UPG-674). The free-text `steps` array below still captures the within-flow narrative; this scalar makes the flow itself a deterministically orderable sibling." },
11570
11698
  trigger: { type: "string", description: "Initiating event" },
11571
11699
  steps: { type: "string[]", description: "Ordered steps" },
11572
11700
  success_state: { type: "string", description: "Successful completion" },
@@ -17630,7 +17758,10 @@ var PRIORITY_LABELS = [
17630
17758
  {
17631
17759
  id: "solution",
17632
17760
  canonical_label: "Solution",
17633
- alt_labels: ["proposed solution", "solution idea", "concept", "approach"],
17761
+ // 'concept' stripped (P-B / UPG-670): bare "concept" was shared with the
17762
+ // distinct `design_concept` type. `design_concept` keeps it; here a search
17763
+ // for a solution uses "approach" / "proposed solution".
17764
+ alt_labels: ["proposed solution", "solution idea", "approach"],
17634
17765
  framework_labels: {
17635
17766
  ost: "Solution",
17636
17767
  design_thinking: "Solution",
@@ -17793,7 +17924,10 @@ var PRIORITY_LABELS = [
17793
17924
  {
17794
17925
  id: "outcome",
17795
17926
  canonical_label: "Outcome",
17796
- alt_labels: ["desired outcome", "product outcome", "business outcome", "target outcome"],
17927
+ // 'desired outcome' stripped (P-B / UPG-670): it was the canonical label of
17928
+ // the distinct `desired_outcome` (Ulwick JTBD) type. The OST framework_label
17929
+ // below still surfaces "Desired Outcome" in OST context, framework-scoped.
17930
+ alt_labels: ["product outcome", "business outcome", "target outcome"],
17797
17931
  framework_labels: {
17798
17932
  ost: "Desired Outcome",
17799
17933
  okr_tree: "Outcome"
@@ -17821,7 +17955,10 @@ var PRIORITY_LABELS = [
17821
17955
  {
17822
17956
  id: "feature",
17823
17957
  canonical_label: "Feature",
17824
- alt_labels: ["capability", "product feature", "functionality"],
17958
+ // 'capability' stripped (P-B / UPG-670): it is the canonical label of the
17959
+ // distinct `capability` type (Wardley / DDD). A search for "capability" must
17960
+ // resolve there, not to a feature.
17961
+ alt_labels: ["product feature", "functionality"],
17825
17962
  framework_labels: {
17826
17963
  rice: "Scored Item",
17827
17964
  moscow: "Prioritised Item",
@@ -17892,7 +18029,10 @@ var PRIORITY_LABELS = [
17892
18029
  {
17893
18030
  id: "distribution_channel",
17894
18031
  canonical_label: "Distribution Channel",
17895
- alt_labels: ["channel", "sales channel", "delivery channel", "distribution"],
18032
+ // bare 'channel' stripped (P-B / UPG-670): shared 3-way with
18033
+ // `acquisition_channel` and `marketing_channel`. BMC/Lean-Canvas framework
18034
+ // contexts still surface "Channel" via framework_labels below.
18035
+ alt_labels: ["distribution channel", "sales channel", "delivery channel", "distribution"],
17896
18036
  framework_labels: {
17897
18037
  bmc: "Channel",
17898
18038
  lean_canvas: "Channel"
@@ -18072,7 +18212,8 @@ var PRIORITY_LABELS = [
18072
18212
  ];
18073
18213
  var STANDARD_LABELS = {
18074
18214
  // Strategic layer
18075
- product: { alt_labels: ["offering", "app", "service", "platform"] },
18215
+ // 'service' stripped (P-B / UPG-670): canonical label of the distinct `service` type.
18216
+ product: { alt_labels: ["offering", "app", "platform"] },
18076
18217
  vision: { alt_labels: ["product vision", "north star vision", "long-term vision"] },
18077
18218
  mission: { alt_labels: ["mission statement", "purpose"] },
18078
18219
  strategic_theme: { alt_labels: ["focus area", "strategic focus area"] },
@@ -18090,7 +18231,8 @@ var STANDARD_LABELS = {
18090
18231
  design_sprint: { alt_labels: ["sprint", "gv sprint", "google ventures sprint"] },
18091
18232
  // Validation layer
18092
18233
  learning: { alt_labels: ["validated learning", "lesson learned", "takeaway"] },
18093
- test_plan: { alt_labels: ["experiment plan", "validation plan"] },
18234
+ // 'experiment plan' stripped (P-B / UPG-670): canonical label of the distinct `experiment_plan` type.
18235
+ test_plan: { alt_labels: ["test strategy", "validation plan"] },
18094
18236
  research_plan: { alt_labels: ["study plan", "research brief"] },
18095
18237
  evidence: { alt_labels: ["proof", "supporting data", "signal"] },
18096
18238
  variant: { alt_labels: ["test variant", "experiment arm", "variation"] },
@@ -18098,7 +18240,9 @@ var STANDARD_LABELS = {
18098
18240
  competitor: { alt_labels: ["rival", "alternative", "competitive product", "competing product"] },
18099
18241
  competitor_feature: { alt_labels: ["competitive feature", "rival capability"] },
18100
18242
  market_trend: { alt_labels: ["trend", "industry trend", "macro trend"] },
18101
- market_segment: { alt_labels: ["segment", "market slice", "tam segment", "sam segment"] },
18243
+ // bare 'segment' stripped (P-B / UPG-670): shared 2-way with `behavioral_segment`.
18244
+ // 'market segment' is the qualified, unambiguous form.
18245
+ market_segment: { alt_labels: ["market segment", "market slice", "tam segment", "sam segment"] },
18102
18246
  competitive_analysis: { alt_labels: ["competitor analysis", "competitive landscape", "market analysis"] },
18103
18247
  // UX Research layer
18104
18248
  research_study: { alt_labels: ["study", "user study", "research project", "ux study"] },
@@ -18134,7 +18278,8 @@ var STANDARD_LABELS = {
18134
18278
  brand_typography: { alt_labels: ["typeface", "font family", "type system"] },
18135
18279
  brand_voice: { alt_labels: ["tone of voice", "brand tone", "writing style"] },
18136
18280
  // Product Specification layer
18137
- epic: { alt_labels: ["initiative", "large story", "feature set"] },
18281
+ // 'initiative' stripped (P-B / UPG-670): canonical label of the distinct `initiative` type.
18282
+ epic: { alt_labels: ["large story", "feature set"] },
18138
18283
  feature_area: { alt_labels: ["feature group", "capability area", "module"] },
18139
18284
  acceptance_criterion: { alt_labels: ["ac", "done criterion", "acceptance criteria", "definition of done"] },
18140
18285
  release: { alt_labels: ["version", "ship", "launch version", "build"] },
@@ -18148,8 +18293,10 @@ var STANDARD_LABELS = {
18148
18293
  // Engineering layer
18149
18294
  bounded_context: { alt_labels: ["context", "domain boundary", "module boundary"] },
18150
18295
  service: { alt_labels: ["microservice", "backend service", "api service"] },
18151
- domain_event: { alt_labels: ["event", "system event", "business event"] },
18152
- api_contract: { alt_labels: ["api spec", "api schema", "contract", "openapi spec"] },
18296
+ // 'event' stripped (P-B / UPG-670): canonical label of the distinct `event` type.
18297
+ domain_event: { alt_labels: ["system event", "business event"] },
18298
+ // 'contract' stripped (P-B / UPG-670): canonical label of the distinct `contract` (legal) type.
18299
+ api_contract: { alt_labels: ["api spec", "api schema", "openapi spec"] },
18153
18300
  technical_debt_item: { alt_labels: ["tech debt", "debt", "tech debt item", "cleanup"] },
18154
18301
  feature_flag: { alt_labels: ["flag", "toggle", "feature toggle", "release flag"] },
18155
18302
  aggregate: { alt_labels: ["aggregate root", "ddd aggregate"] },
@@ -18162,15 +18309,19 @@ var STANDARD_LABELS = {
18162
18309
  queue_topic: { alt_labels: ["topic", "message queue", "event bus topic", "pubsub topic"] },
18163
18310
  build_artifact: { alt_labels: ["artifact", "binary", "docker image", "package"] },
18164
18311
  code_repository: { alt_labels: ["repo", "repository", "git repo", "codebase"] },
18165
- library_dependency: { alt_labels: ["dependency", "package", "library", "npm package"] },
18312
+ // 'dependency' stripped (P-B / UPG-670): canonical label of the distinct `dependency` type.
18313
+ library_dependency: { alt_labels: ["package", "library", "npm package"] },
18166
18314
  integration_pattern: { alt_labels: ["integration", "pattern", "middleware pattern"] },
18167
18315
  external_api: { alt_labels: ["third-party api", "vendor api", "saas integration"] },
18168
18316
  data_flow: { alt_labels: ["data movement", "data transfer", "pipeline flow"] },
18169
18317
  // Growth layer
18170
- acquisition_channel: { alt_labels: ["channel", "traffic source", "user source"] },
18318
+ // bare 'channel' stripped (P-B / UPG-670): shared 3-way (see distribution_channel).
18319
+ acquisition_channel: { alt_labels: ["acquisition channel", "traffic source", "user source"] },
18171
18320
  growth_campaign: { alt_labels: ["campaign", "marketing campaign", "ad campaign", "growth campaign"] },
18172
18321
  cohort: { alt_labels: ["user cohort", "retention cohort", "signup cohort"] },
18173
- behavioral_segment: { alt_labels: ["segment", "user segment", "audience segment", "behavioural segment"] },
18322
+ // bare 'segment' stripped (P-B / UPG-670): shared 2-way with `market_segment`.
18323
+ // 'behavioral segment' / 'user segment' keep the affordance unambiguously.
18324
+ behavioral_segment: { alt_labels: ["user segment", "audience segment", "behavioural segment"] },
18174
18325
  growth_loop: { alt_labels: ["viral loop", "referral loop", "flywheel"] },
18175
18326
  attribution_model: { alt_labels: ["attribution", "marketing attribution", "channel attribution"] },
18176
18327
  // Business Model layer
@@ -18199,7 +18350,8 @@ var STANDARD_LABELS = {
18199
18350
  retrospective: { alt_labels: ["retro", "sprint retro", "team retro", "post-mortem"] },
18200
18351
  dependency: { alt_labels: ["team dependency", "cross-team dependency", "blocker"] },
18201
18352
  department: { alt_labels: ["org unit", "division", "business unit"] },
18202
- skill: { alt_labels: ["competency", "capability", "expertise"] },
18353
+ // 'capability' stripped (P-B / UPG-670): canonical label of the distinct `capability` type.
18354
+ skill: { alt_labels: ["competency", "expertise"] },
18203
18355
  ceremony: { alt_labels: ["ritual", "meeting cadence", "standup", "retrospective meeting"] },
18204
18356
  capacity_plan: { alt_labels: ["resourcing plan", "staffing plan", "headcount plan"] },
18205
18357
  // Data & Analytics layer
@@ -18209,7 +18361,8 @@ var STANDARD_LABELS = {
18209
18361
  data_model: { alt_labels: ["erd", "entity relationship diagram", "schema model"] },
18210
18362
  data_quality_rule: { alt_labels: ["data rule", "quality check", "data validation"] },
18211
18363
  data_product: { alt_labels: ["data asset", "data offering"] },
18212
- data_pipeline: { alt_labels: ["etl", "elt", "ingestion pipeline", "data flow"] },
18364
+ // 'data flow' stripped (P-B / UPG-670): canonical label of the distinct `data_flow` type.
18365
+ data_pipeline: { alt_labels: ["etl", "elt", "ingestion pipeline"] },
18213
18366
  data_lineage: { alt_labels: ["lineage", "data provenance", "data trail"] },
18214
18367
  glossary_term: { alt_labels: ["term", "definition", "business term"] },
18215
18368
  data_domain: { alt_labels: ["data area", "data subject area"] },
@@ -18251,7 +18404,8 @@ var STANDARD_LABELS = {
18251
18404
  error_budget: { alt_labels: ["reliability budget", "downtime budget"] },
18252
18405
  investigation: { alt_labels: ["incident investigation", "root cause analysis", "debugging"] },
18253
18406
  postmortem: { alt_labels: ["post-mortem", "incident review", "rca", "root cause analysis"] },
18254
- runbook: { alt_labels: ["operations guide", "playbook", "sop", "standard operating procedure"] },
18407
+ // 'playbook' stripped (P-B / UPG-670): canonical label of the distinct `playbook` type.
18408
+ runbook: { alt_labels: ["operations guide", "sop", "standard operating procedure"] },
18255
18409
  monitor: { alt_labels: ["health check", "synthetic monitor", "uptime check"] },
18256
18410
  alert_rule: { alt_labels: ["alert", "pager rule", "notification rule"] },
18257
18411
  release_strategy: { alt_labels: ["rollout strategy", "deployment strategy", "canary release"] },
@@ -18266,17 +18420,26 @@ var STANDARD_LABELS = {
18266
18420
  security_control: { alt_labels: ["control", "safeguard", "countermeasure", "mitigation"] },
18267
18421
  security_policy: { alt_labels: ["infosec policy", "security standard"] },
18268
18422
  penetration_test: { alt_labels: ["pentest", "pen test", "security test"] },
18269
- security_review: { alt_labels: ["code review", "security assessment", "audit"] },
18423
+ // bare 'audit' / 'security assessment' stripped (P-B / UPG-670): both owned by
18424
+ // `security_audit`. A `security_review` is a code-review-scoped activity; the
18425
+ // qualified 'security code review' keeps it findable without colliding.
18426
+ security_review: { alt_labels: ["code review", "security code review"] },
18270
18427
  data_classification: { alt_labels: ["classification", "sensitivity level", "data label"] },
18271
18428
  access_policy: { alt_labels: ["iam policy", "rbac rule", "permission", "access control"] },
18272
18429
  // Sales & Revenue layer
18273
- account: { alt_labels: ["customer account", "client", "organization"] },
18274
- contact: { alt_labels: ["person", "buyer", "champion"] },
18430
+ // 'organization' stripped (P-B / UPG-670): canonical label of the distinct `organization` type.
18431
+ account: { alt_labels: ["customer account", "client"] },
18432
+ // 'person' stripped (P-B / UPG-670): canonical label of the distinct `person` type.
18433
+ contact: { alt_labels: ["buyer", "champion"] },
18275
18434
  lead: { alt_labels: ["prospect", "mql", "sql", "marketing lead"] },
18276
- deal: { alt_labels: ["opportunity", "sales opportunity", "opp"] },
18435
+ // 'opportunity' stripped (P-B / UPG-670): canonical label of the distinct `opportunity` (OST) type.
18436
+ deal: { alt_labels: ["sales opportunity", "opp"] },
18277
18437
  pipeline_sales: { alt_labels: ["sales pipeline", "deal pipeline", "revenue pipeline"] },
18278
18438
  pipeline_stage: { alt_labels: ["deal stage", "sales stage"] },
18279
- quote_document: { alt_labels: ["quote", "proposal", "estimate", "quotation"] },
18439
+ // bare 'quote' qualified to 'sales quote' (P-B / UPG-670): 'quote' is the
18440
+ // canonical label of the distinct `quote` type. The qualified form keeps the
18441
+ // sales-document search affordance without misresolving.
18442
+ quote_document: { alt_labels: ["sales quote", "proposal", "estimate", "quotation"] },
18280
18443
  subscription: { alt_labels: ["recurring revenue", "saas subscription", "plan"] },
18281
18444
  invoice: { alt_labels: ["bill", "payment request"] },
18282
18445
  forecast: { alt_labels: ["revenue forecast", "sales forecast", "projection"] },
@@ -18297,7 +18460,8 @@ var STANDARD_LABELS = {
18297
18460
  a11y_annotation: { alt_labels: ["accessibility annotation", "aria note"] },
18298
18461
  // Marketing & Communications layer
18299
18462
  marketing_strategy: { alt_labels: ["marketing plan", "growth strategy"] },
18300
- marketing_channel: { alt_labels: ["channel", "paid channel", "organic channel"] },
18463
+ // bare 'channel' stripped (P-B / UPG-670): shared 3-way (see distribution_channel).
18464
+ marketing_channel: { alt_labels: ["marketing channel", "paid channel", "organic channel"] },
18301
18465
  marketing_campaign_plan: { alt_labels: ["campaign plan", "launch campaign"] },
18302
18466
  email_sequence: { alt_labels: ["drip campaign", "nurture sequence", "email flow"] },
18303
18467
  social_post: { alt_labels: ["tweet", "linkedin post", "social media post"] },
@@ -18371,7 +18535,9 @@ var STANDARD_LABELS = {
18371
18535
  agent_session: { alt_labels: ["session", "agent run", "agent conversation"] },
18372
18536
  review_gate: { alt_labels: ["approval gate", "quality gate", "stage gate"] },
18373
18537
  approval_record: { alt_labels: ["approval", "sign-off", "authorization"] },
18374
- agent_skill: { alt_labels: ["skill", "tool", "agent capability"] },
18538
+ // bare 'skill' qualified to 'agent skill' (P-B / UPG-670): 'skill' is the
18539
+ // canonical label of the distinct team_org `skill` type.
18540
+ agent_skill: { alt_labels: ["agent skill", "tool", "agent capability"] },
18375
18541
  agent_hook: { alt_labels: ["hook", "trigger", "callback"] },
18376
18542
  workflow_artifact: { alt_labels: ["artifact", "output artifact", "generated artifact"] },
18377
18543
  // Portfolio layer
@@ -23515,6 +23681,96 @@ var UPG_ANTI_PATTERNS = [
23515
23681
  stages: ["concept", "validation", "build", "beta", "launch", "growth"],
23516
23682
  severity: "high",
23517
23683
  source: { kind: "fundamental" }
23684
+ },
23685
+ // ── F5 (UPG-671): anti-pattern enforcement ────────────────────────────────
23686
+ // P-C from the 36-domain wiring audit: domain-guide anti-patterns described
23687
+ // in prose with no machine-checkable detector. These two map cleanly to a
23688
+ // RelationshipCheck (edge presence/absence) and are promoted here.
23689
+ {
23690
+ id: "insights-without-evidence",
23691
+ name: "Insights without evidence",
23692
+ description: "The graph has insight entities but none are backed by a primary-evidence link: no observation yields them (`observation_yields_insight`), no survey response evidences them (`survey_response_evidences_insight`), and no quote is attached (`insight_evidenced_by_quote`). An insight with no evidence behind it is an opinion wearing a research label.",
23693
+ structured_condition: {
23694
+ operator: "and",
23695
+ checks: [
23696
+ { check: { type: "entity_count", entity_type: "insight", comparison: "nonzero" } },
23697
+ {
23698
+ check: {
23699
+ type: "relationship",
23700
+ source_type: "observation",
23701
+ edge_type: "observation_yields_insight",
23702
+ target_type: "insight",
23703
+ comparison: "not_exists"
23704
+ }
23705
+ },
23706
+ {
23707
+ check: {
23708
+ type: "relationship",
23709
+ source_type: "survey_response",
23710
+ edge_type: "survey_response_evidences_insight",
23711
+ target_type: "insight",
23712
+ comparison: "not_exists"
23713
+ }
23714
+ },
23715
+ {
23716
+ check: {
23717
+ type: "relationship",
23718
+ source_type: "insight",
23719
+ edge_type: "insight_evidenced_by_quote",
23720
+ target_type: "quote",
23721
+ comparison: "not_exists"
23722
+ }
23723
+ }
23724
+ ]
23725
+ },
23726
+ why_it_matters: "Insights untethered from evidence cannot be trusted, contested, or traced. Downstream opportunities and design questions inherit an unfalsifiable claim.",
23727
+ remediation: "Back each insight with at least one primary record via `observation_yields_insight`, `survey_response_evidences_insight`, or `insight_evidenced_by_quote`. Capture the supporting observation or quote first.",
23728
+ stages: ["concept", "validation", "build", "beta", "launch", "growth", "mature"],
23729
+ severity: "high",
23730
+ source: { kind: "practitioner", attribution: "Steve Portigal, Interviewing Users" }
23731
+ },
23732
+ {
23733
+ id: "feature-requests-without-provenance",
23734
+ name: "Feature requests without provenance",
23735
+ description: "The graph has feature_request entities but none trace back to a source: no feedback program collects them (`feedback_program_collects_feature_request`), no customer feedback becomes one (`customer_feedback_becomes_feature_request`), and none originate from a behavioural segment (`feature_request_from_behavioral_segment`). A request with no provenance cannot be weighed against who asked or how many.",
23736
+ structured_condition: {
23737
+ operator: "and",
23738
+ checks: [
23739
+ { check: { type: "entity_count", entity_type: "feature_request", comparison: "nonzero" } },
23740
+ {
23741
+ check: {
23742
+ type: "relationship",
23743
+ source_type: "feedback_program",
23744
+ edge_type: "feedback_program_collects_feature_request",
23745
+ target_type: "feature_request",
23746
+ comparison: "not_exists"
23747
+ }
23748
+ },
23749
+ {
23750
+ check: {
23751
+ type: "relationship",
23752
+ source_type: "customer_feedback",
23753
+ edge_type: "customer_feedback_becomes_feature_request",
23754
+ target_type: "feature_request",
23755
+ comparison: "not_exists"
23756
+ }
23757
+ },
23758
+ {
23759
+ check: {
23760
+ type: "relationship",
23761
+ source_type: "feature_request",
23762
+ edge_type: "feature_request_from_behavioral_segment",
23763
+ target_type: "behavioral_segment",
23764
+ comparison: "not_exists"
23765
+ }
23766
+ }
23767
+ ]
23768
+ },
23769
+ why_it_matters: "Requests without a source get prioritised on volume of voice, not on the strength or fit of who is asking. The loudest channel wins by default.",
23770
+ remediation: "Attach provenance to each `feature_request` via `feedback_program_collects_feature_request`, `customer_feedback_becomes_feature_request`, or `feature_request_from_behavioral_segment` before it enters prioritisation.",
23771
+ stages: ["beta", "launch", "growth", "mature"],
23772
+ severity: "medium",
23773
+ source: { kind: "practitioner", attribution: "Marty Cagan, Inspired (product discovery)" }
23518
23774
  }
23519
23775
  ];
23520
23776
  function getAntiPatternById(id) {
@@ -23853,6 +24109,10 @@ var UPG_REGIONS = [
23853
24109
  "strategy"
23854
24110
  ],
23855
24111
  entities: [
24112
+ {
24113
+ type: "product",
24114
+ role: "container"
24115
+ },
23856
24116
  {
23857
24117
  type: "vision",
23858
24118
  role: "root"
@@ -23892,7 +24152,11 @@ var UPG_REGIONS = [
23892
24152
  {
23893
24153
  type: "metric",
23894
24154
  role: "leaf",
23895
- notes: "shared with Analytics"
24155
+ notes: "also anchors Analytics; canonical home is Strategy"
24156
+ },
24157
+ {
24158
+ type: "metric_quality_assessment",
24159
+ role: "leaf"
23896
24160
  },
23897
24161
  {
23898
24162
  type: "decision",
@@ -23903,6 +24167,10 @@ var UPG_REGIONS = [
23903
24167
  type: "assumption",
23904
24168
  role: "leaf"
23905
24169
  },
24170
+ {
24171
+ type: "constraint",
24172
+ role: "leaf"
24173
+ },
23906
24174
  {
23907
24175
  type: "outcome",
23908
24176
  role: "hub"
@@ -24016,7 +24284,7 @@ var UPG_REGIONS = [
24016
24284
  {
24017
24285
  type: "participant",
24018
24286
  role: "leaf",
24019
- notes: "research-resolved persona"
24287
+ notes: "research-resolved persona; canonical home is Discovery/Research/Validation"
24020
24288
  }
24021
24289
  ],
24022
24290
  anchor: {
@@ -24187,6 +24455,14 @@ var UPG_REGIONS = [
24187
24455
  role: "hub",
24188
24456
  notes: "self-nesting"
24189
24457
  },
24458
+ {
24459
+ type: "experiment_plan",
24460
+ role: "container"
24461
+ },
24462
+ {
24463
+ type: "experiment_run",
24464
+ role: "container"
24465
+ },
24190
24466
  {
24191
24467
  type: "learning",
24192
24468
  role: "leaf"
@@ -24356,10 +24632,6 @@ var UPG_REGIONS = [
24356
24632
  type: "competitive_analysis",
24357
24633
  role: "container"
24358
24634
  },
24359
- {
24360
- type: "territory",
24361
- role: "leaf"
24362
- },
24363
24635
  {
24364
24636
  type: "classification_axis",
24365
24637
  role: "container",
@@ -24379,7 +24651,7 @@ var UPG_REGIONS = [
24379
24651
  },
24380
24652
  intra_edges: [
24381
24653
  "competitor_offers_competitor_feature",
24382
- "competitive_analysis_contains_competitor",
24654
+ "competitive_analysis_analyses_competitor",
24383
24655
  "competitive_analysis_dimensioned_by_classification_axis",
24384
24656
  "classification_axis_includes_classification_value",
24385
24657
  "competitor_classified_as_classification_value"
@@ -24480,6 +24752,10 @@ var UPG_REGIONS = [
24480
24752
  type: "screen",
24481
24753
  role: "leaf"
24482
24754
  },
24755
+ {
24756
+ type: "screen_state",
24757
+ role: "leaf"
24758
+ },
24483
24759
  {
24484
24760
  type: "wireframe",
24485
24761
  role: "leaf"
@@ -24557,6 +24833,18 @@ var UPG_REGIONS = [
24557
24833
  type: "content_piece",
24558
24834
  role: "leaf"
24559
24835
  },
24836
+ {
24837
+ type: "knowledge_base_article",
24838
+ role: "leaf"
24839
+ },
24840
+ {
24841
+ type: "content_calendar",
24842
+ role: "container"
24843
+ },
24844
+ {
24845
+ type: "documentation_template",
24846
+ role: "leaf"
24847
+ },
24560
24848
  {
24561
24849
  type: "document",
24562
24850
  role: "leaf"
@@ -24575,13 +24863,13 @@ var UPG_REGIONS = [
24575
24863
  intra_edges: [
24576
24864
  "user_journey_contains_journey_step",
24577
24865
  "design_system_contains_design_component",
24578
- "brand_identity_contains_brand_colour",
24579
- "design_component_self_nests"
24866
+ "brand_identity_coloured_with_brand_colour",
24867
+ "design_component_composes_design_component"
24580
24868
  ],
24581
24869
  boundary_edges: [
24582
24870
  {
24583
24871
  direction: "import",
24584
- edge_id: "need_informs_design_question",
24872
+ edge_id: "need_reframed_as_design_question",
24585
24873
  crosses_into: "users_needs"
24586
24874
  },
24587
24875
  {
@@ -24605,8 +24893,8 @@ var UPG_REGIONS = [
24605
24893
  crosses_into: "engineering_platform"
24606
24894
  },
24607
24895
  {
24608
- direction: "sideways",
24609
- edge_id: "feature_sketched_in_wireframe",
24896
+ direction: "export",
24897
+ edge_id: "wireframe_specifies_feature",
24610
24898
  crosses_into: "product_delivery"
24611
24899
  },
24612
24900
  {
@@ -24681,20 +24969,68 @@ var UPG_REGIONS = [
24681
24969
  role: "container",
24682
24970
  notes: "semantic spanner, not containment"
24683
24971
  },
24972
+ {
24973
+ type: "changelog",
24974
+ role: "leaf"
24975
+ },
24976
+ {
24977
+ type: "feedback_program",
24978
+ role: "container"
24979
+ },
24980
+ {
24981
+ type: "feature_request",
24982
+ role: "leaf"
24983
+ },
24984
+ {
24985
+ type: "feedback_vote",
24986
+ role: "leaf"
24987
+ },
24988
+ {
24989
+ type: "nps_campaign",
24990
+ role: "leaf"
24991
+ },
24992
+ {
24993
+ type: "user_advisory_board",
24994
+ role: "container"
24995
+ },
24996
+ {
24997
+ type: "beta_program",
24998
+ role: "leaf"
24999
+ },
25000
+ {
25001
+ type: "feedback_theme",
25002
+ role: "leaf"
25003
+ },
25004
+ {
25005
+ type: "program",
25006
+ role: "container"
25007
+ },
25008
+ {
25009
+ type: "project",
25010
+ role: "container"
25011
+ },
24684
25012
  {
24685
25013
  type: "milestone",
25014
+ role: "leaf"
25015
+ },
25016
+ {
25017
+ type: "risk_register",
24686
25018
  role: "container"
24687
25019
  },
24688
25020
  {
24689
- type: "changelog",
25021
+ type: "change_request",
24690
25022
  role: "leaf"
24691
25023
  },
24692
25024
  {
24693
- type: "feature_request",
25025
+ type: "deliverable",
24694
25026
  role: "leaf"
24695
25027
  },
24696
25028
  {
24697
- type: "feedback_vote",
25029
+ type: "resource_allocation",
25030
+ role: "leaf"
25031
+ },
25032
+ {
25033
+ type: "status_report",
24698
25034
  role: "leaf"
24699
25035
  }
24700
25036
  ],
@@ -24763,8 +25099,8 @@ var UPG_REGIONS = [
24763
25099
  crosses_into: "discovery_research_validation"
24764
25100
  },
24765
25101
  {
24766
- direction: "sideways",
24767
- edge_id: "feature_sketched_in_wireframe",
25102
+ direction: "import",
25103
+ edge_id: "wireframe_specifies_feature",
24768
25104
  crosses_into: "experience_design_brand"
24769
25105
  },
24770
25106
  {
@@ -24827,10 +25163,6 @@ var UPG_REGIONS = [
24827
25163
  type: "database_schema",
24828
25164
  role: "leaf"
24829
25165
  },
24830
- {
24831
- type: "data_model",
24832
- role: "leaf"
24833
- },
24834
25166
  {
24835
25167
  type: "aggregate",
24836
25168
  role: "container"
@@ -24895,6 +25227,111 @@ var UPG_REGIONS = [
24895
25227
  {
24896
25228
  type: "technical_debt_item",
24897
25229
  role: "leaf"
25230
+ },
25231
+ {
25232
+ type: "investigation",
25233
+ role: "container"
25234
+ },
25235
+ {
25236
+ type: "root_cause",
25237
+ role: "container"
25238
+ },
25239
+ {
25240
+ type: "symptom",
25241
+ role: "leaf"
25242
+ },
25243
+ {
25244
+ type: "fix",
25245
+ role: "leaf"
25246
+ },
25247
+ {
25248
+ type: "ai_model",
25249
+ role: "container"
25250
+ },
25251
+ {
25252
+ type: "prompt_template",
25253
+ role: "leaf"
25254
+ },
25255
+ {
25256
+ type: "prompt_version",
25257
+ role: "leaf"
25258
+ },
25259
+ {
25260
+ type: "eval_benchmark",
25261
+ role: "container"
25262
+ },
25263
+ {
25264
+ type: "eval_run",
25265
+ role: "leaf"
25266
+ },
25267
+ {
25268
+ type: "ai_cost_tracker",
25269
+ role: "leaf"
25270
+ },
25271
+ {
25272
+ type: "hallucination_report",
25273
+ role: "leaf"
25274
+ },
25275
+ {
25276
+ type: "ai_guardrail",
25277
+ role: "leaf"
25278
+ },
25279
+ {
25280
+ type: "model_comparison",
25281
+ role: "leaf"
25282
+ },
25283
+ {
25284
+ type: "ai_experiment",
25285
+ role: "leaf"
25286
+ },
25287
+ {
25288
+ type: "ai_dataset",
25289
+ role: "leaf"
25290
+ },
25291
+ {
25292
+ type: "ai_trace",
25293
+ role: "container",
25294
+ notes: "self-nesting inference chain"
25295
+ },
25296
+ {
25297
+ type: "workflow_template",
25298
+ role: "container"
25299
+ },
25300
+ {
25301
+ type: "workflow_run",
25302
+ role: "container"
25303
+ },
25304
+ {
25305
+ type: "workflow_artifact",
25306
+ role: "leaf"
25307
+ },
25308
+ {
25309
+ type: "agent_definition",
25310
+ role: "container"
25311
+ },
25312
+ {
25313
+ type: "agent_session",
25314
+ role: "leaf"
25315
+ },
25316
+ {
25317
+ type: "agent_skill",
25318
+ role: "leaf"
25319
+ },
25320
+ {
25321
+ type: "agent_hook",
25322
+ role: "leaf"
25323
+ },
25324
+ {
25325
+ type: "agent_task",
25326
+ role: "leaf"
25327
+ },
25328
+ {
25329
+ type: "review_gate",
25330
+ role: "container"
25331
+ },
25332
+ {
25333
+ type: "approval_record",
25334
+ role: "leaf"
24898
25335
  }
24899
25336
  ],
24900
25337
  anchor: {
@@ -24913,7 +25350,7 @@ var UPG_REGIONS = [
24913
25350
  "service_depends_on_library_dependency",
24914
25351
  "service_carries_technical_debt_item",
24915
25352
  "service_toggles_feature_flag",
24916
- "service_caused_by_root_cause",
25353
+ "service_affected_by_root_cause",
24917
25354
  "service_investigated_via_investigation"
24918
25355
  ],
24919
25356
  boundary_edges: [
@@ -24997,6 +25434,26 @@ var UPG_REGIONS = [
24997
25434
  type: "unit_economics",
24998
25435
  role: "leaf"
24999
25436
  },
25437
+ {
25438
+ type: "partnership",
25439
+ role: "leaf"
25440
+ },
25441
+ {
25442
+ type: "key_resource",
25443
+ role: "leaf"
25444
+ },
25445
+ {
25446
+ type: "key_activity",
25447
+ role: "leaf"
25448
+ },
25449
+ {
25450
+ type: "customer_relationship",
25451
+ role: "leaf"
25452
+ },
25453
+ {
25454
+ type: "distribution_channel",
25455
+ role: "leaf"
25456
+ },
25000
25457
  {
25001
25458
  type: "pricing_strategy",
25002
25459
  role: "root"
@@ -25005,6 +25462,18 @@ var UPG_REGIONS = [
25005
25462
  type: "pricing_tier",
25006
25463
  role: "leaf"
25007
25464
  },
25465
+ {
25466
+ type: "discount_strategy",
25467
+ role: "leaf"
25468
+ },
25469
+ {
25470
+ type: "trial_config",
25471
+ role: "leaf"
25472
+ },
25473
+ {
25474
+ type: "paywall",
25475
+ role: "leaf"
25476
+ },
25008
25477
  {
25009
25478
  type: "gtm_strategy",
25010
25479
  role: "root"
@@ -25021,10 +25490,30 @@ var UPG_REGIONS = [
25021
25490
  type: "messaging",
25022
25491
  role: "leaf"
25023
25492
  },
25493
+ {
25494
+ type: "content_strategy",
25495
+ role: "container"
25496
+ },
25497
+ {
25498
+ type: "sales_motion",
25499
+ role: "leaf"
25500
+ },
25501
+ {
25502
+ type: "demand_gen_program",
25503
+ role: "leaf"
25504
+ },
25505
+ {
25506
+ type: "territory",
25507
+ role: "leaf"
25508
+ },
25024
25509
  {
25025
25510
  type: "objection",
25026
25511
  role: "leaf"
25027
25512
  },
25513
+ {
25514
+ type: "rebuttal",
25515
+ role: "container"
25516
+ },
25028
25517
  {
25029
25518
  type: "proof_point",
25030
25519
  role: "leaf"
@@ -25072,6 +25561,114 @@ var UPG_REGIONS = [
25072
25561
  {
25073
25562
  type: "variant",
25074
25563
  role: "leaf"
25564
+ },
25565
+ {
25566
+ type: "account",
25567
+ role: "container"
25568
+ },
25569
+ {
25570
+ type: "contact",
25571
+ role: "leaf"
25572
+ },
25573
+ {
25574
+ type: "lead",
25575
+ role: "leaf"
25576
+ },
25577
+ {
25578
+ type: "deal",
25579
+ role: "container"
25580
+ },
25581
+ {
25582
+ type: "pipeline_sales",
25583
+ role: "container"
25584
+ },
25585
+ {
25586
+ type: "pipeline_stage",
25587
+ role: "leaf"
25588
+ },
25589
+ {
25590
+ type: "quote_document",
25591
+ role: "leaf"
25592
+ },
25593
+ {
25594
+ type: "subscription",
25595
+ role: "container"
25596
+ },
25597
+ {
25598
+ type: "invoice",
25599
+ role: "leaf"
25600
+ },
25601
+ {
25602
+ type: "forecast",
25603
+ role: "leaf"
25604
+ },
25605
+ {
25606
+ type: "marketing_strategy",
25607
+ role: "container"
25608
+ },
25609
+ {
25610
+ type: "marketing_channel",
25611
+ role: "container"
25612
+ },
25613
+ {
25614
+ type: "marketing_campaign_plan",
25615
+ role: "container"
25616
+ },
25617
+ {
25618
+ type: "email_sequence",
25619
+ role: "leaf"
25620
+ },
25621
+ {
25622
+ type: "social_post",
25623
+ role: "leaf"
25624
+ },
25625
+ {
25626
+ type: "seo_keyword",
25627
+ role: "leaf"
25628
+ },
25629
+ {
25630
+ type: "ad_creative",
25631
+ role: "leaf"
25632
+ },
25633
+ {
25634
+ type: "press_release",
25635
+ role: "leaf"
25636
+ },
25637
+ {
25638
+ type: "event",
25639
+ role: "leaf"
25640
+ },
25641
+ {
25642
+ type: "community_initiative",
25643
+ role: "leaf"
25644
+ },
25645
+ {
25646
+ type: "partner_program",
25647
+ role: "container"
25648
+ },
25649
+ {
25650
+ type: "partner_tier",
25651
+ role: "leaf"
25652
+ },
25653
+ {
25654
+ type: "api_ecosystem",
25655
+ role: "container"
25656
+ },
25657
+ {
25658
+ type: "marketplace_listing",
25659
+ role: "leaf"
25660
+ },
25661
+ {
25662
+ type: "developer_portal",
25663
+ role: "leaf"
25664
+ },
25665
+ {
25666
+ type: "integration_partner",
25667
+ role: "leaf"
25668
+ },
25669
+ {
25670
+ type: "partner_revenue_share",
25671
+ role: "leaf"
25075
25672
  }
25076
25673
  ],
25077
25674
  anchor: {
@@ -25178,7 +25775,8 @@ var UPG_REGIONS = [
25178
25775
  entities: [
25179
25776
  {
25180
25777
  type: "metric",
25181
- role: "anchor"
25778
+ role: "anchor",
25779
+ notes: "canonical home is Strategy; anchors Analytics as the measurement plane"
25182
25780
  },
25183
25781
  {
25184
25782
  type: "data_source",
@@ -25192,24 +25790,36 @@ var UPG_REGIONS = [
25192
25790
  type: "dashboard",
25193
25791
  role: "container"
25194
25792
  },
25793
+ {
25794
+ type: "data_model",
25795
+ role: "leaf"
25796
+ },
25195
25797
  {
25196
25798
  type: "data_domain",
25197
25799
  role: "container"
25198
25800
  },
25199
25801
  {
25200
- type: "glossary_term",
25802
+ type: "data_product",
25201
25803
  role: "leaf"
25202
25804
  },
25203
25805
  {
25204
- type: "forecast",
25806
+ type: "data_pipeline",
25205
25807
  role: "leaf"
25206
25808
  },
25207
25809
  {
25208
- type: "data_quality_rule",
25810
+ type: "data_lineage",
25209
25811
  role: "leaf"
25210
25812
  },
25211
25813
  {
25212
- type: "data_contract",
25814
+ type: "glossary_term",
25815
+ role: "leaf"
25816
+ },
25817
+ {
25818
+ type: "report",
25819
+ role: "leaf"
25820
+ },
25821
+ {
25822
+ type: "data_quality_rule",
25213
25823
  role: "leaf"
25214
25824
  }
25215
25825
  ],
@@ -25335,7 +25945,27 @@ var UPG_REGIONS = [
25335
25945
  {
25336
25946
  type: "deployment",
25337
25947
  role: "leaf",
25338
- notes: "shared with Engineering"
25948
+ notes: "canonical home is Engineering; release event surfaced to Ops"
25949
+ },
25950
+ {
25951
+ type: "alert_rule",
25952
+ role: "leaf"
25953
+ },
25954
+ {
25955
+ type: "ci_pipeline",
25956
+ role: "container"
25957
+ },
25958
+ {
25959
+ type: "release_strategy",
25960
+ role: "leaf"
25961
+ },
25962
+ {
25963
+ type: "on_call_rotation",
25964
+ role: "leaf"
25965
+ },
25966
+ {
25967
+ type: "infrastructure_component",
25968
+ role: "container"
25339
25969
  },
25340
25970
  {
25341
25971
  type: "test_suite",
@@ -25353,10 +25983,26 @@ var UPG_REGIONS = [
25353
25983
  type: "test_result",
25354
25984
  role: "leaf"
25355
25985
  },
25986
+ {
25987
+ type: "regression_test",
25988
+ role: "leaf"
25989
+ },
25990
+ {
25991
+ type: "test_coverage_report",
25992
+ role: "leaf"
25993
+ },
25994
+ {
25995
+ type: "test_environment",
25996
+ role: "leaf"
25997
+ },
25356
25998
  {
25357
25999
  type: "threat_model",
25358
26000
  role: "root"
25359
26001
  },
26002
+ {
26003
+ type: "threat",
26004
+ role: "leaf"
26005
+ },
25360
26006
  {
25361
26007
  type: "security_control",
25362
26008
  role: "leaf"
@@ -25373,14 +26019,34 @@ var UPG_REGIONS = [
25373
26019
  type: "penetration_test",
25374
26020
  role: "leaf"
25375
26021
  },
26022
+ {
26023
+ type: "security_review",
26024
+ role: "container"
26025
+ },
26026
+ {
26027
+ type: "data_classification",
26028
+ role: "leaf"
26029
+ },
26030
+ {
26031
+ type: "access_policy",
26032
+ role: "leaf"
26033
+ },
25376
26034
  {
25377
26035
  type: "a11y_standard",
25378
26036
  role: "leaf"
25379
26037
  },
26038
+ {
26039
+ type: "a11y_guideline",
26040
+ role: "leaf"
26041
+ },
25380
26042
  {
25381
26043
  type: "a11y_audit",
25382
26044
  role: "leaf"
25383
26045
  },
26046
+ {
26047
+ type: "a11y_issue",
26048
+ role: "leaf"
26049
+ },
25384
26050
  {
25385
26051
  type: "a11y_annotation",
25386
26052
  role: "leaf"
@@ -25398,11 +26064,15 @@ var UPG_REGIONS = [
25398
26064
  role: "leaf"
25399
26065
  },
25400
26066
  {
25401
- type: "root_cause",
26067
+ type: "data_contract",
25402
26068
  role: "leaf"
25403
26069
  },
25404
26070
  {
25405
- type: "investigation",
26071
+ type: "audit_log_policy",
26072
+ role: "leaf"
26073
+ },
26074
+ {
26075
+ type: "security_audit",
25406
26076
  role: "leaf"
25407
26077
  },
25408
26078
  {
@@ -25431,16 +26101,16 @@ var UPG_REGIONS = [
25431
26101
  role: "root"
25432
26102
  },
25433
26103
  {
25434
- type: "beta_program",
26104
+ type: "customer_journey_stage",
25435
26105
  role: "container"
25436
26106
  },
25437
26107
  {
25438
- type: "feedback_program",
25439
- role: "container"
26108
+ type: "touchpoint",
26109
+ role: "leaf"
25440
26110
  },
25441
26111
  {
25442
- type: "user_advisory_board",
25443
- role: "container"
26112
+ type: "success_milestone",
26113
+ role: "leaf"
25444
26114
  },
25445
26115
  {
25446
26116
  type: "team",
@@ -25454,6 +26124,10 @@ var UPG_REGIONS = [
25454
26124
  type: "role",
25455
26125
  role: "leaf"
25456
26126
  },
26127
+ {
26128
+ type: "person",
26129
+ role: "leaf"
26130
+ },
25457
26131
  {
25458
26132
  type: "stakeholder",
25459
26133
  role: "leaf",
@@ -25481,6 +26155,78 @@ var UPG_REGIONS = [
25481
26155
  },
25482
26156
  {
25483
26157
  type: "capacity_plan",
26158
+ role: "leaf"
26159
+ },
26160
+ {
26161
+ type: "legal_entity",
26162
+ role: "container"
26163
+ },
26164
+ {
26165
+ type: "ip_asset",
26166
+ role: "leaf"
26167
+ },
26168
+ {
26169
+ type: "contract",
26170
+ role: "container"
26171
+ },
26172
+ {
26173
+ type: "contract_clause",
26174
+ role: "leaf"
26175
+ },
26176
+ {
26177
+ type: "privacy_policy",
26178
+ role: "leaf"
26179
+ },
26180
+ {
26181
+ type: "locale",
26182
+ role: "container"
26183
+ },
26184
+ {
26185
+ type: "translation_key",
26186
+ role: "leaf"
26187
+ },
26188
+ {
26189
+ type: "translation_bundle",
26190
+ role: "container"
26191
+ },
26192
+ {
26193
+ type: "locale_config",
26194
+ role: "leaf"
26195
+ },
26196
+ {
26197
+ type: "cultural_adaptation",
26198
+ role: "leaf"
26199
+ },
26200
+ {
26201
+ type: "regional_pricing",
26202
+ role: "leaf"
26203
+ },
26204
+ {
26205
+ type: "education_program",
26206
+ role: "container"
26207
+ },
26208
+ {
26209
+ type: "tutorial",
26210
+ role: "leaf"
26211
+ },
26212
+ {
26213
+ type: "walkthrough",
26214
+ role: "leaf"
26215
+ },
26216
+ {
26217
+ type: "webinar",
26218
+ role: "leaf"
26219
+ },
26220
+ {
26221
+ type: "certification",
26222
+ role: "leaf"
26223
+ },
26224
+ {
26225
+ type: "help_video",
26226
+ role: "leaf"
26227
+ },
26228
+ {
26229
+ type: "learning_path",
25484
26230
  role: "container"
25485
26231
  }
25486
26232
  ],
@@ -25497,7 +26243,6 @@ var UPG_REGIONS = [
25497
26243
  "incident_analysed_in_postmortem",
25498
26244
  "incident_triggers_postmortem",
25499
26245
  "incident_breaches_service_level_objective",
25500
- "incident_caused_by_root_cause",
25501
26246
  "incident_exploits_vulnerability"
25502
26247
  ],
25503
26248
  boundary_edges: [
@@ -25518,8 +26263,8 @@ var UPG_REGIONS = [
25518
26263
  },
25519
26264
  {
25520
26265
  direction: "export",
25521
- edge_id: "beta_program_runs_experiment",
25522
- crosses_into: "discovery_research_validation"
26266
+ edge_id: "incident_caused_by_root_cause",
26267
+ crosses_into: "engineering_platform"
25523
26268
  },
25524
26269
  {
25525
26270
  direction: "export",
@@ -25860,7 +26605,7 @@ var NODE_KEY_ORDER = [
25860
26605
  "properties"
25861
26606
  ];
25862
26607
  var EDGE_KEY_ORDER = ["id", "source", "target", "type", "mapping_confidence", "properties"];
25863
- var CROSS_EDGE_KEY_ORDER = ["id", "source", "target", "type", "source_product_id", "target_product_id", "mapping_confidence"];
26608
+ var CROSS_EDGE_KEY_ORDER = ["id", "source", "target", "type", "source_product_id", "target_product_id", "mapping_confidence", "alias", "relevance", "audience_role"];
25864
26609
  var PRODUCT_KEY_ORDER = ["id", "title", "description", "stage", "properties"];
25865
26610
  function canonicalNode(node) {
25866
26611
  const repaired = repairNodeDrift(node);
@@ -26053,7 +26798,7 @@ function isCanonical(text) {
26053
26798
  }
26054
26799
 
26055
26800
  // src/index.ts
26056
- var UPG_VERSION = "0.9.6";
26801
+ var UPG_VERSION = "0.9.8";
26057
26802
  var UPG_FORMAT_VERSION = "0.4.0";
26058
26803
  var MARKDOWN_FORMAT_VERSION = "0.1";
26059
26804
  var UPG_TYPES = getTypes();