@unified-product-graph/core 0.9.5 → 0.9.7
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/CHANGELOG.md +40 -0
- package/dist/index.cjs +836 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +281 -4
- package/dist/index.d.ts +281 -4
- package/dist/index.js +835 -74
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
575
|
-
|
|
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
|
-
|
|
616
|
-
|
|
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
|
-
|
|
1649
|
-
|
|
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: "
|
|
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
|
|
@@ -2776,8 +2892,10 @@ var UPG_CROSS_EDGE_TYPES = [
|
|
|
2776
2892
|
"cannibalises",
|
|
2777
2893
|
"succeeds",
|
|
2778
2894
|
"hosts",
|
|
2779
|
-
"contributes_to"
|
|
2895
|
+
"contributes_to",
|
|
2896
|
+
"instance_of"
|
|
2780
2897
|
];
|
|
2898
|
+
var REGISTRY_PRODUCT_ID = "registry";
|
|
2781
2899
|
|
|
2782
2900
|
// src/registry/entity-type-resolution.ts
|
|
2783
2901
|
var TYPES = getTypes();
|
|
@@ -3060,7 +3178,11 @@ var UPG_VALID_CHILDREN = {
|
|
|
3060
3178
|
"survey_response"
|
|
3061
3179
|
],
|
|
3062
3180
|
observation: ["quote"],
|
|
3063
|
-
|
|
3181
|
+
// F6 (UPG-672): affinity_cluster owns the observations it groups, in addition
|
|
3182
|
+
// to the insights it synthesises. Pairs with `affinity_cluster_groups_observation`
|
|
3183
|
+
// in the edge catalog (hierarchy). An observation can be both directly owned by
|
|
3184
|
+
// its research_study and grouped under an affinity_cluster (multi-parent grammar).
|
|
3185
|
+
affinity_cluster: ["insight", "observation"],
|
|
3064
3186
|
// insight refines into insight; a raw insight can be distilled
|
|
3065
3187
|
// into a more specific insight (refines_into chain).
|
|
3066
3188
|
// v0.5.8 (UPG-528 Part 2d): insights own their evidencing quotes;
|
|
@@ -10278,6 +10400,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10278
10400
|
},
|
|
10279
10401
|
// LearningPathProperties: Learning path.
|
|
10280
10402
|
learning_path: {
|
|
10403
|
+
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." },
|
|
10281
10404
|
path_difficulty: { type: "string", enum: ["beginner", "intermediate", "advanced"], description: "Overall difficulty level of the learning path" },
|
|
10282
10405
|
item_count: { type: "number", description: "Number of items (tutorials, videos, etc.) in the path" },
|
|
10283
10406
|
estimated_hours: { type: "number", description: "Estimated total hours to complete the path" },
|
|
@@ -10427,6 +10550,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10427
10550
|
},
|
|
10428
10551
|
// MilestoneProperties: Milestone.
|
|
10429
10552
|
milestone: {
|
|
10553
|
+
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`." },
|
|
10430
10554
|
due_date: { type: "string", description: "Target due date (ISO format)" },
|
|
10431
10555
|
met_on_time: { type: "boolean", description: "Whether the milestone was met on time" }
|
|
10432
10556
|
},
|
|
@@ -10631,6 +10755,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10631
10755
|
},
|
|
10632
10756
|
// PartnerTierProperties: Partner tier.
|
|
10633
10757
|
partner_tier: {
|
|
10758
|
+
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." },
|
|
10634
10759
|
tier_level: { type: "number", description: "Numeric rank of the tier (higher = more prestigious)" },
|
|
10635
10760
|
requirements: { type: "string[]", description: "What a partner must achieve to reach this tier" },
|
|
10636
10761
|
benefits: { type: "string[]", description: "Benefits granted at this tier level" }
|
|
@@ -11053,6 +11178,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11053
11178
|
},
|
|
11054
11179
|
// ScreenStateProperties: Specific state of a screen.
|
|
11055
11180
|
screen_state: {
|
|
11181
|
+
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)." },
|
|
11056
11182
|
state_name: { type: "string", enum: ["empty", "loading", "error", "populated", "skeleton", "partial"], description: "State" },
|
|
11057
11183
|
trigger: { type: "string", description: "Cause for entering this state" },
|
|
11058
11184
|
condition: { type: "string", description: "Data or environmental condition the state represents" },
|
|
@@ -11565,6 +11691,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11565
11691
|
},
|
|
11566
11692
|
// UserFlowProperties: User flow.
|
|
11567
11693
|
user_flow: {
|
|
11694
|
+
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." },
|
|
11568
11695
|
trigger: { type: "string", description: "Initiating event" },
|
|
11569
11696
|
steps: { type: "string[]", description: "Ordered steps" },
|
|
11570
11697
|
success_state: { type: "string", description: "Successful completion" },
|
|
@@ -17628,7 +17755,10 @@ var PRIORITY_LABELS = [
|
|
|
17628
17755
|
{
|
|
17629
17756
|
id: "solution",
|
|
17630
17757
|
canonical_label: "Solution",
|
|
17631
|
-
|
|
17758
|
+
// 'concept' stripped (P-B / UPG-670): bare "concept" was shared with the
|
|
17759
|
+
// distinct `design_concept` type. `design_concept` keeps it; here a search
|
|
17760
|
+
// for a solution uses "approach" / "proposed solution".
|
|
17761
|
+
alt_labels: ["proposed solution", "solution idea", "approach"],
|
|
17632
17762
|
framework_labels: {
|
|
17633
17763
|
ost: "Solution",
|
|
17634
17764
|
design_thinking: "Solution",
|
|
@@ -17791,7 +17921,10 @@ var PRIORITY_LABELS = [
|
|
|
17791
17921
|
{
|
|
17792
17922
|
id: "outcome",
|
|
17793
17923
|
canonical_label: "Outcome",
|
|
17794
|
-
|
|
17924
|
+
// 'desired outcome' stripped (P-B / UPG-670): it was the canonical label of
|
|
17925
|
+
// the distinct `desired_outcome` (Ulwick JTBD) type. The OST framework_label
|
|
17926
|
+
// below still surfaces "Desired Outcome" in OST context, framework-scoped.
|
|
17927
|
+
alt_labels: ["product outcome", "business outcome", "target outcome"],
|
|
17795
17928
|
framework_labels: {
|
|
17796
17929
|
ost: "Desired Outcome",
|
|
17797
17930
|
okr_tree: "Outcome"
|
|
@@ -17819,7 +17952,10 @@ var PRIORITY_LABELS = [
|
|
|
17819
17952
|
{
|
|
17820
17953
|
id: "feature",
|
|
17821
17954
|
canonical_label: "Feature",
|
|
17822
|
-
|
|
17955
|
+
// 'capability' stripped (P-B / UPG-670): it is the canonical label of the
|
|
17956
|
+
// distinct `capability` type (Wardley / DDD). A search for "capability" must
|
|
17957
|
+
// resolve there, not to a feature.
|
|
17958
|
+
alt_labels: ["product feature", "functionality"],
|
|
17823
17959
|
framework_labels: {
|
|
17824
17960
|
rice: "Scored Item",
|
|
17825
17961
|
moscow: "Prioritised Item",
|
|
@@ -17890,7 +18026,10 @@ var PRIORITY_LABELS = [
|
|
|
17890
18026
|
{
|
|
17891
18027
|
id: "distribution_channel",
|
|
17892
18028
|
canonical_label: "Distribution Channel",
|
|
17893
|
-
|
|
18029
|
+
// bare 'channel' stripped (P-B / UPG-670): shared 3-way with
|
|
18030
|
+
// `acquisition_channel` and `marketing_channel`. BMC/Lean-Canvas framework
|
|
18031
|
+
// contexts still surface "Channel" via framework_labels below.
|
|
18032
|
+
alt_labels: ["distribution channel", "sales channel", "delivery channel", "distribution"],
|
|
17894
18033
|
framework_labels: {
|
|
17895
18034
|
bmc: "Channel",
|
|
17896
18035
|
lean_canvas: "Channel"
|
|
@@ -18070,7 +18209,8 @@ var PRIORITY_LABELS = [
|
|
|
18070
18209
|
];
|
|
18071
18210
|
var STANDARD_LABELS = {
|
|
18072
18211
|
// Strategic layer
|
|
18073
|
-
|
|
18212
|
+
// 'service' stripped (P-B / UPG-670): canonical label of the distinct `service` type.
|
|
18213
|
+
product: { alt_labels: ["offering", "app", "platform"] },
|
|
18074
18214
|
vision: { alt_labels: ["product vision", "north star vision", "long-term vision"] },
|
|
18075
18215
|
mission: { alt_labels: ["mission statement", "purpose"] },
|
|
18076
18216
|
strategic_theme: { alt_labels: ["focus area", "strategic focus area"] },
|
|
@@ -18088,7 +18228,8 @@ var STANDARD_LABELS = {
|
|
|
18088
18228
|
design_sprint: { alt_labels: ["sprint", "gv sprint", "google ventures sprint"] },
|
|
18089
18229
|
// Validation layer
|
|
18090
18230
|
learning: { alt_labels: ["validated learning", "lesson learned", "takeaway"] },
|
|
18091
|
-
|
|
18231
|
+
// 'experiment plan' stripped (P-B / UPG-670): canonical label of the distinct `experiment_plan` type.
|
|
18232
|
+
test_plan: { alt_labels: ["test strategy", "validation plan"] },
|
|
18092
18233
|
research_plan: { alt_labels: ["study plan", "research brief"] },
|
|
18093
18234
|
evidence: { alt_labels: ["proof", "supporting data", "signal"] },
|
|
18094
18235
|
variant: { alt_labels: ["test variant", "experiment arm", "variation"] },
|
|
@@ -18096,7 +18237,9 @@ var STANDARD_LABELS = {
|
|
|
18096
18237
|
competitor: { alt_labels: ["rival", "alternative", "competitive product", "competing product"] },
|
|
18097
18238
|
competitor_feature: { alt_labels: ["competitive feature", "rival capability"] },
|
|
18098
18239
|
market_trend: { alt_labels: ["trend", "industry trend", "macro trend"] },
|
|
18099
|
-
|
|
18240
|
+
// bare 'segment' stripped (P-B / UPG-670): shared 2-way with `behavioral_segment`.
|
|
18241
|
+
// 'market segment' is the qualified, unambiguous form.
|
|
18242
|
+
market_segment: { alt_labels: ["market segment", "market slice", "tam segment", "sam segment"] },
|
|
18100
18243
|
competitive_analysis: { alt_labels: ["competitor analysis", "competitive landscape", "market analysis"] },
|
|
18101
18244
|
// UX Research layer
|
|
18102
18245
|
research_study: { alt_labels: ["study", "user study", "research project", "ux study"] },
|
|
@@ -18132,7 +18275,8 @@ var STANDARD_LABELS = {
|
|
|
18132
18275
|
brand_typography: { alt_labels: ["typeface", "font family", "type system"] },
|
|
18133
18276
|
brand_voice: { alt_labels: ["tone of voice", "brand tone", "writing style"] },
|
|
18134
18277
|
// Product Specification layer
|
|
18135
|
-
|
|
18278
|
+
// 'initiative' stripped (P-B / UPG-670): canonical label of the distinct `initiative` type.
|
|
18279
|
+
epic: { alt_labels: ["large story", "feature set"] },
|
|
18136
18280
|
feature_area: { alt_labels: ["feature group", "capability area", "module"] },
|
|
18137
18281
|
acceptance_criterion: { alt_labels: ["ac", "done criterion", "acceptance criteria", "definition of done"] },
|
|
18138
18282
|
release: { alt_labels: ["version", "ship", "launch version", "build"] },
|
|
@@ -18146,8 +18290,10 @@ var STANDARD_LABELS = {
|
|
|
18146
18290
|
// Engineering layer
|
|
18147
18291
|
bounded_context: { alt_labels: ["context", "domain boundary", "module boundary"] },
|
|
18148
18292
|
service: { alt_labels: ["microservice", "backend service", "api service"] },
|
|
18149
|
-
|
|
18150
|
-
|
|
18293
|
+
// 'event' stripped (P-B / UPG-670): canonical label of the distinct `event` type.
|
|
18294
|
+
domain_event: { alt_labels: ["system event", "business event"] },
|
|
18295
|
+
// 'contract' stripped (P-B / UPG-670): canonical label of the distinct `contract` (legal) type.
|
|
18296
|
+
api_contract: { alt_labels: ["api spec", "api schema", "openapi spec"] },
|
|
18151
18297
|
technical_debt_item: { alt_labels: ["tech debt", "debt", "tech debt item", "cleanup"] },
|
|
18152
18298
|
feature_flag: { alt_labels: ["flag", "toggle", "feature toggle", "release flag"] },
|
|
18153
18299
|
aggregate: { alt_labels: ["aggregate root", "ddd aggregate"] },
|
|
@@ -18160,15 +18306,19 @@ var STANDARD_LABELS = {
|
|
|
18160
18306
|
queue_topic: { alt_labels: ["topic", "message queue", "event bus topic", "pubsub topic"] },
|
|
18161
18307
|
build_artifact: { alt_labels: ["artifact", "binary", "docker image", "package"] },
|
|
18162
18308
|
code_repository: { alt_labels: ["repo", "repository", "git repo", "codebase"] },
|
|
18163
|
-
|
|
18309
|
+
// 'dependency' stripped (P-B / UPG-670): canonical label of the distinct `dependency` type.
|
|
18310
|
+
library_dependency: { alt_labels: ["package", "library", "npm package"] },
|
|
18164
18311
|
integration_pattern: { alt_labels: ["integration", "pattern", "middleware pattern"] },
|
|
18165
18312
|
external_api: { alt_labels: ["third-party api", "vendor api", "saas integration"] },
|
|
18166
18313
|
data_flow: { alt_labels: ["data movement", "data transfer", "pipeline flow"] },
|
|
18167
18314
|
// Growth layer
|
|
18168
|
-
|
|
18315
|
+
// bare 'channel' stripped (P-B / UPG-670): shared 3-way (see distribution_channel).
|
|
18316
|
+
acquisition_channel: { alt_labels: ["acquisition channel", "traffic source", "user source"] },
|
|
18169
18317
|
growth_campaign: { alt_labels: ["campaign", "marketing campaign", "ad campaign", "growth campaign"] },
|
|
18170
18318
|
cohort: { alt_labels: ["user cohort", "retention cohort", "signup cohort"] },
|
|
18171
|
-
|
|
18319
|
+
// bare 'segment' stripped (P-B / UPG-670): shared 2-way with `market_segment`.
|
|
18320
|
+
// 'behavioral segment' / 'user segment' keep the affordance unambiguously.
|
|
18321
|
+
behavioral_segment: { alt_labels: ["user segment", "audience segment", "behavioural segment"] },
|
|
18172
18322
|
growth_loop: { alt_labels: ["viral loop", "referral loop", "flywheel"] },
|
|
18173
18323
|
attribution_model: { alt_labels: ["attribution", "marketing attribution", "channel attribution"] },
|
|
18174
18324
|
// Business Model layer
|
|
@@ -18197,7 +18347,8 @@ var STANDARD_LABELS = {
|
|
|
18197
18347
|
retrospective: { alt_labels: ["retro", "sprint retro", "team retro", "post-mortem"] },
|
|
18198
18348
|
dependency: { alt_labels: ["team dependency", "cross-team dependency", "blocker"] },
|
|
18199
18349
|
department: { alt_labels: ["org unit", "division", "business unit"] },
|
|
18200
|
-
|
|
18350
|
+
// 'capability' stripped (P-B / UPG-670): canonical label of the distinct `capability` type.
|
|
18351
|
+
skill: { alt_labels: ["competency", "expertise"] },
|
|
18201
18352
|
ceremony: { alt_labels: ["ritual", "meeting cadence", "standup", "retrospective meeting"] },
|
|
18202
18353
|
capacity_plan: { alt_labels: ["resourcing plan", "staffing plan", "headcount plan"] },
|
|
18203
18354
|
// Data & Analytics layer
|
|
@@ -18207,7 +18358,8 @@ var STANDARD_LABELS = {
|
|
|
18207
18358
|
data_model: { alt_labels: ["erd", "entity relationship diagram", "schema model"] },
|
|
18208
18359
|
data_quality_rule: { alt_labels: ["data rule", "quality check", "data validation"] },
|
|
18209
18360
|
data_product: { alt_labels: ["data asset", "data offering"] },
|
|
18210
|
-
|
|
18361
|
+
// 'data flow' stripped (P-B / UPG-670): canonical label of the distinct `data_flow` type.
|
|
18362
|
+
data_pipeline: { alt_labels: ["etl", "elt", "ingestion pipeline"] },
|
|
18211
18363
|
data_lineage: { alt_labels: ["lineage", "data provenance", "data trail"] },
|
|
18212
18364
|
glossary_term: { alt_labels: ["term", "definition", "business term"] },
|
|
18213
18365
|
data_domain: { alt_labels: ["data area", "data subject area"] },
|
|
@@ -18249,7 +18401,8 @@ var STANDARD_LABELS = {
|
|
|
18249
18401
|
error_budget: { alt_labels: ["reliability budget", "downtime budget"] },
|
|
18250
18402
|
investigation: { alt_labels: ["incident investigation", "root cause analysis", "debugging"] },
|
|
18251
18403
|
postmortem: { alt_labels: ["post-mortem", "incident review", "rca", "root cause analysis"] },
|
|
18252
|
-
|
|
18404
|
+
// 'playbook' stripped (P-B / UPG-670): canonical label of the distinct `playbook` type.
|
|
18405
|
+
runbook: { alt_labels: ["operations guide", "sop", "standard operating procedure"] },
|
|
18253
18406
|
monitor: { alt_labels: ["health check", "synthetic monitor", "uptime check"] },
|
|
18254
18407
|
alert_rule: { alt_labels: ["alert", "pager rule", "notification rule"] },
|
|
18255
18408
|
release_strategy: { alt_labels: ["rollout strategy", "deployment strategy", "canary release"] },
|
|
@@ -18264,17 +18417,26 @@ var STANDARD_LABELS = {
|
|
|
18264
18417
|
security_control: { alt_labels: ["control", "safeguard", "countermeasure", "mitigation"] },
|
|
18265
18418
|
security_policy: { alt_labels: ["infosec policy", "security standard"] },
|
|
18266
18419
|
penetration_test: { alt_labels: ["pentest", "pen test", "security test"] },
|
|
18267
|
-
|
|
18420
|
+
// bare 'audit' / 'security assessment' stripped (P-B / UPG-670): both owned by
|
|
18421
|
+
// `security_audit`. A `security_review` is a code-review-scoped activity; the
|
|
18422
|
+
// qualified 'security code review' keeps it findable without colliding.
|
|
18423
|
+
security_review: { alt_labels: ["code review", "security code review"] },
|
|
18268
18424
|
data_classification: { alt_labels: ["classification", "sensitivity level", "data label"] },
|
|
18269
18425
|
access_policy: { alt_labels: ["iam policy", "rbac rule", "permission", "access control"] },
|
|
18270
18426
|
// Sales & Revenue layer
|
|
18271
|
-
|
|
18272
|
-
|
|
18427
|
+
// 'organization' stripped (P-B / UPG-670): canonical label of the distinct `organization` type.
|
|
18428
|
+
account: { alt_labels: ["customer account", "client"] },
|
|
18429
|
+
// 'person' stripped (P-B / UPG-670): canonical label of the distinct `person` type.
|
|
18430
|
+
contact: { alt_labels: ["buyer", "champion"] },
|
|
18273
18431
|
lead: { alt_labels: ["prospect", "mql", "sql", "marketing lead"] },
|
|
18274
|
-
|
|
18432
|
+
// 'opportunity' stripped (P-B / UPG-670): canonical label of the distinct `opportunity` (OST) type.
|
|
18433
|
+
deal: { alt_labels: ["sales opportunity", "opp"] },
|
|
18275
18434
|
pipeline_sales: { alt_labels: ["sales pipeline", "deal pipeline", "revenue pipeline"] },
|
|
18276
18435
|
pipeline_stage: { alt_labels: ["deal stage", "sales stage"] },
|
|
18277
|
-
|
|
18436
|
+
// bare 'quote' qualified to 'sales quote' (P-B / UPG-670): 'quote' is the
|
|
18437
|
+
// canonical label of the distinct `quote` type. The qualified form keeps the
|
|
18438
|
+
// sales-document search affordance without misresolving.
|
|
18439
|
+
quote_document: { alt_labels: ["sales quote", "proposal", "estimate", "quotation"] },
|
|
18278
18440
|
subscription: { alt_labels: ["recurring revenue", "saas subscription", "plan"] },
|
|
18279
18441
|
invoice: { alt_labels: ["bill", "payment request"] },
|
|
18280
18442
|
forecast: { alt_labels: ["revenue forecast", "sales forecast", "projection"] },
|
|
@@ -18295,7 +18457,8 @@ var STANDARD_LABELS = {
|
|
|
18295
18457
|
a11y_annotation: { alt_labels: ["accessibility annotation", "aria note"] },
|
|
18296
18458
|
// Marketing & Communications layer
|
|
18297
18459
|
marketing_strategy: { alt_labels: ["marketing plan", "growth strategy"] },
|
|
18298
|
-
|
|
18460
|
+
// bare 'channel' stripped (P-B / UPG-670): shared 3-way (see distribution_channel).
|
|
18461
|
+
marketing_channel: { alt_labels: ["marketing channel", "paid channel", "organic channel"] },
|
|
18299
18462
|
marketing_campaign_plan: { alt_labels: ["campaign plan", "launch campaign"] },
|
|
18300
18463
|
email_sequence: { alt_labels: ["drip campaign", "nurture sequence", "email flow"] },
|
|
18301
18464
|
social_post: { alt_labels: ["tweet", "linkedin post", "social media post"] },
|
|
@@ -18369,7 +18532,9 @@ var STANDARD_LABELS = {
|
|
|
18369
18532
|
agent_session: { alt_labels: ["session", "agent run", "agent conversation"] },
|
|
18370
18533
|
review_gate: { alt_labels: ["approval gate", "quality gate", "stage gate"] },
|
|
18371
18534
|
approval_record: { alt_labels: ["approval", "sign-off", "authorization"] },
|
|
18372
|
-
|
|
18535
|
+
// bare 'skill' qualified to 'agent skill' (P-B / UPG-670): 'skill' is the
|
|
18536
|
+
// canonical label of the distinct team_org `skill` type.
|
|
18537
|
+
agent_skill: { alt_labels: ["agent skill", "tool", "agent capability"] },
|
|
18373
18538
|
agent_hook: { alt_labels: ["hook", "trigger", "callback"] },
|
|
18374
18539
|
workflow_artifact: { alt_labels: ["artifact", "output artifact", "generated artifact"] },
|
|
18375
18540
|
// Portfolio layer
|
|
@@ -23513,6 +23678,96 @@ var UPG_ANTI_PATTERNS = [
|
|
|
23513
23678
|
stages: ["concept", "validation", "build", "beta", "launch", "growth"],
|
|
23514
23679
|
severity: "high",
|
|
23515
23680
|
source: { kind: "fundamental" }
|
|
23681
|
+
},
|
|
23682
|
+
// ── F5 (UPG-671): anti-pattern enforcement ────────────────────────────────
|
|
23683
|
+
// P-C from the 36-domain wiring audit: domain-guide anti-patterns described
|
|
23684
|
+
// in prose with no machine-checkable detector. These two map cleanly to a
|
|
23685
|
+
// RelationshipCheck (edge presence/absence) and are promoted here.
|
|
23686
|
+
{
|
|
23687
|
+
id: "insights-without-evidence",
|
|
23688
|
+
name: "Insights without evidence",
|
|
23689
|
+
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.",
|
|
23690
|
+
structured_condition: {
|
|
23691
|
+
operator: "and",
|
|
23692
|
+
checks: [
|
|
23693
|
+
{ check: { type: "entity_count", entity_type: "insight", comparison: "nonzero" } },
|
|
23694
|
+
{
|
|
23695
|
+
check: {
|
|
23696
|
+
type: "relationship",
|
|
23697
|
+
source_type: "observation",
|
|
23698
|
+
edge_type: "observation_yields_insight",
|
|
23699
|
+
target_type: "insight",
|
|
23700
|
+
comparison: "not_exists"
|
|
23701
|
+
}
|
|
23702
|
+
},
|
|
23703
|
+
{
|
|
23704
|
+
check: {
|
|
23705
|
+
type: "relationship",
|
|
23706
|
+
source_type: "survey_response",
|
|
23707
|
+
edge_type: "survey_response_evidences_insight",
|
|
23708
|
+
target_type: "insight",
|
|
23709
|
+
comparison: "not_exists"
|
|
23710
|
+
}
|
|
23711
|
+
},
|
|
23712
|
+
{
|
|
23713
|
+
check: {
|
|
23714
|
+
type: "relationship",
|
|
23715
|
+
source_type: "insight",
|
|
23716
|
+
edge_type: "insight_evidenced_by_quote",
|
|
23717
|
+
target_type: "quote",
|
|
23718
|
+
comparison: "not_exists"
|
|
23719
|
+
}
|
|
23720
|
+
}
|
|
23721
|
+
]
|
|
23722
|
+
},
|
|
23723
|
+
why_it_matters: "Insights untethered from evidence cannot be trusted, contested, or traced. Downstream opportunities and design questions inherit an unfalsifiable claim.",
|
|
23724
|
+
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.",
|
|
23725
|
+
stages: ["concept", "validation", "build", "beta", "launch", "growth", "mature"],
|
|
23726
|
+
severity: "high",
|
|
23727
|
+
source: { kind: "practitioner", attribution: "Steve Portigal, Interviewing Users" }
|
|
23728
|
+
},
|
|
23729
|
+
{
|
|
23730
|
+
id: "feature-requests-without-provenance",
|
|
23731
|
+
name: "Feature requests without provenance",
|
|
23732
|
+
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.",
|
|
23733
|
+
structured_condition: {
|
|
23734
|
+
operator: "and",
|
|
23735
|
+
checks: [
|
|
23736
|
+
{ check: { type: "entity_count", entity_type: "feature_request", comparison: "nonzero" } },
|
|
23737
|
+
{
|
|
23738
|
+
check: {
|
|
23739
|
+
type: "relationship",
|
|
23740
|
+
source_type: "feedback_program",
|
|
23741
|
+
edge_type: "feedback_program_collects_feature_request",
|
|
23742
|
+
target_type: "feature_request",
|
|
23743
|
+
comparison: "not_exists"
|
|
23744
|
+
}
|
|
23745
|
+
},
|
|
23746
|
+
{
|
|
23747
|
+
check: {
|
|
23748
|
+
type: "relationship",
|
|
23749
|
+
source_type: "customer_feedback",
|
|
23750
|
+
edge_type: "customer_feedback_becomes_feature_request",
|
|
23751
|
+
target_type: "feature_request",
|
|
23752
|
+
comparison: "not_exists"
|
|
23753
|
+
}
|
|
23754
|
+
},
|
|
23755
|
+
{
|
|
23756
|
+
check: {
|
|
23757
|
+
type: "relationship",
|
|
23758
|
+
source_type: "feature_request",
|
|
23759
|
+
edge_type: "feature_request_from_behavioral_segment",
|
|
23760
|
+
target_type: "behavioral_segment",
|
|
23761
|
+
comparison: "not_exists"
|
|
23762
|
+
}
|
|
23763
|
+
}
|
|
23764
|
+
]
|
|
23765
|
+
},
|
|
23766
|
+
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.",
|
|
23767
|
+
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.",
|
|
23768
|
+
stages: ["beta", "launch", "growth", "mature"],
|
|
23769
|
+
severity: "medium",
|
|
23770
|
+
source: { kind: "practitioner", attribution: "Marty Cagan, Inspired (product discovery)" }
|
|
23516
23771
|
}
|
|
23517
23772
|
];
|
|
23518
23773
|
function getAntiPatternById(id) {
|
|
@@ -23851,6 +24106,10 @@ var UPG_REGIONS = [
|
|
|
23851
24106
|
"strategy"
|
|
23852
24107
|
],
|
|
23853
24108
|
entities: [
|
|
24109
|
+
{
|
|
24110
|
+
type: "product",
|
|
24111
|
+
role: "container"
|
|
24112
|
+
},
|
|
23854
24113
|
{
|
|
23855
24114
|
type: "vision",
|
|
23856
24115
|
role: "root"
|
|
@@ -23890,7 +24149,11 @@ var UPG_REGIONS = [
|
|
|
23890
24149
|
{
|
|
23891
24150
|
type: "metric",
|
|
23892
24151
|
role: "leaf",
|
|
23893
|
-
notes: "
|
|
24152
|
+
notes: "also anchors Analytics; canonical home is Strategy"
|
|
24153
|
+
},
|
|
24154
|
+
{
|
|
24155
|
+
type: "metric_quality_assessment",
|
|
24156
|
+
role: "leaf"
|
|
23894
24157
|
},
|
|
23895
24158
|
{
|
|
23896
24159
|
type: "decision",
|
|
@@ -23901,6 +24164,10 @@ var UPG_REGIONS = [
|
|
|
23901
24164
|
type: "assumption",
|
|
23902
24165
|
role: "leaf"
|
|
23903
24166
|
},
|
|
24167
|
+
{
|
|
24168
|
+
type: "constraint",
|
|
24169
|
+
role: "leaf"
|
|
24170
|
+
},
|
|
23904
24171
|
{
|
|
23905
24172
|
type: "outcome",
|
|
23906
24173
|
role: "hub"
|
|
@@ -24014,7 +24281,7 @@ var UPG_REGIONS = [
|
|
|
24014
24281
|
{
|
|
24015
24282
|
type: "participant",
|
|
24016
24283
|
role: "leaf",
|
|
24017
|
-
notes: "research-resolved persona"
|
|
24284
|
+
notes: "research-resolved persona; canonical home is Discovery/Research/Validation"
|
|
24018
24285
|
}
|
|
24019
24286
|
],
|
|
24020
24287
|
anchor: {
|
|
@@ -24185,6 +24452,14 @@ var UPG_REGIONS = [
|
|
|
24185
24452
|
role: "hub",
|
|
24186
24453
|
notes: "self-nesting"
|
|
24187
24454
|
},
|
|
24455
|
+
{
|
|
24456
|
+
type: "experiment_plan",
|
|
24457
|
+
role: "container"
|
|
24458
|
+
},
|
|
24459
|
+
{
|
|
24460
|
+
type: "experiment_run",
|
|
24461
|
+
role: "container"
|
|
24462
|
+
},
|
|
24188
24463
|
{
|
|
24189
24464
|
type: "learning",
|
|
24190
24465
|
role: "leaf"
|
|
@@ -24354,10 +24629,6 @@ var UPG_REGIONS = [
|
|
|
24354
24629
|
type: "competitive_analysis",
|
|
24355
24630
|
role: "container"
|
|
24356
24631
|
},
|
|
24357
|
-
{
|
|
24358
|
-
type: "territory",
|
|
24359
|
-
role: "leaf"
|
|
24360
|
-
},
|
|
24361
24632
|
{
|
|
24362
24633
|
type: "classification_axis",
|
|
24363
24634
|
role: "container",
|
|
@@ -24377,7 +24648,7 @@ var UPG_REGIONS = [
|
|
|
24377
24648
|
},
|
|
24378
24649
|
intra_edges: [
|
|
24379
24650
|
"competitor_offers_competitor_feature",
|
|
24380
|
-
"
|
|
24651
|
+
"competitive_analysis_analyses_competitor",
|
|
24381
24652
|
"competitive_analysis_dimensioned_by_classification_axis",
|
|
24382
24653
|
"classification_axis_includes_classification_value",
|
|
24383
24654
|
"competitor_classified_as_classification_value"
|
|
@@ -24478,6 +24749,10 @@ var UPG_REGIONS = [
|
|
|
24478
24749
|
type: "screen",
|
|
24479
24750
|
role: "leaf"
|
|
24480
24751
|
},
|
|
24752
|
+
{
|
|
24753
|
+
type: "screen_state",
|
|
24754
|
+
role: "leaf"
|
|
24755
|
+
},
|
|
24481
24756
|
{
|
|
24482
24757
|
type: "wireframe",
|
|
24483
24758
|
role: "leaf"
|
|
@@ -24555,6 +24830,18 @@ var UPG_REGIONS = [
|
|
|
24555
24830
|
type: "content_piece",
|
|
24556
24831
|
role: "leaf"
|
|
24557
24832
|
},
|
|
24833
|
+
{
|
|
24834
|
+
type: "knowledge_base_article",
|
|
24835
|
+
role: "leaf"
|
|
24836
|
+
},
|
|
24837
|
+
{
|
|
24838
|
+
type: "content_calendar",
|
|
24839
|
+
role: "container"
|
|
24840
|
+
},
|
|
24841
|
+
{
|
|
24842
|
+
type: "documentation_template",
|
|
24843
|
+
role: "leaf"
|
|
24844
|
+
},
|
|
24558
24845
|
{
|
|
24559
24846
|
type: "document",
|
|
24560
24847
|
role: "leaf"
|
|
@@ -24573,13 +24860,13 @@ var UPG_REGIONS = [
|
|
|
24573
24860
|
intra_edges: [
|
|
24574
24861
|
"user_journey_contains_journey_step",
|
|
24575
24862
|
"design_system_contains_design_component",
|
|
24576
|
-
"
|
|
24577
|
-
"
|
|
24863
|
+
"brand_identity_coloured_with_brand_colour",
|
|
24864
|
+
"design_component_composes_design_component"
|
|
24578
24865
|
],
|
|
24579
24866
|
boundary_edges: [
|
|
24580
24867
|
{
|
|
24581
24868
|
direction: "import",
|
|
24582
|
-
edge_id: "
|
|
24869
|
+
edge_id: "need_reframed_as_design_question",
|
|
24583
24870
|
crosses_into: "users_needs"
|
|
24584
24871
|
},
|
|
24585
24872
|
{
|
|
@@ -24603,8 +24890,8 @@ var UPG_REGIONS = [
|
|
|
24603
24890
|
crosses_into: "engineering_platform"
|
|
24604
24891
|
},
|
|
24605
24892
|
{
|
|
24606
|
-
direction: "
|
|
24607
|
-
edge_id: "
|
|
24893
|
+
direction: "export",
|
|
24894
|
+
edge_id: "wireframe_specifies_feature",
|
|
24608
24895
|
crosses_into: "product_delivery"
|
|
24609
24896
|
},
|
|
24610
24897
|
{
|
|
@@ -24679,20 +24966,68 @@ var UPG_REGIONS = [
|
|
|
24679
24966
|
role: "container",
|
|
24680
24967
|
notes: "semantic spanner, not containment"
|
|
24681
24968
|
},
|
|
24969
|
+
{
|
|
24970
|
+
type: "changelog",
|
|
24971
|
+
role: "leaf"
|
|
24972
|
+
},
|
|
24973
|
+
{
|
|
24974
|
+
type: "feedback_program",
|
|
24975
|
+
role: "container"
|
|
24976
|
+
},
|
|
24977
|
+
{
|
|
24978
|
+
type: "feature_request",
|
|
24979
|
+
role: "leaf"
|
|
24980
|
+
},
|
|
24981
|
+
{
|
|
24982
|
+
type: "feedback_vote",
|
|
24983
|
+
role: "leaf"
|
|
24984
|
+
},
|
|
24985
|
+
{
|
|
24986
|
+
type: "nps_campaign",
|
|
24987
|
+
role: "leaf"
|
|
24988
|
+
},
|
|
24989
|
+
{
|
|
24990
|
+
type: "user_advisory_board",
|
|
24991
|
+
role: "container"
|
|
24992
|
+
},
|
|
24993
|
+
{
|
|
24994
|
+
type: "beta_program",
|
|
24995
|
+
role: "leaf"
|
|
24996
|
+
},
|
|
24997
|
+
{
|
|
24998
|
+
type: "feedback_theme",
|
|
24999
|
+
role: "leaf"
|
|
25000
|
+
},
|
|
25001
|
+
{
|
|
25002
|
+
type: "program",
|
|
25003
|
+
role: "container"
|
|
25004
|
+
},
|
|
25005
|
+
{
|
|
25006
|
+
type: "project",
|
|
25007
|
+
role: "container"
|
|
25008
|
+
},
|
|
24682
25009
|
{
|
|
24683
25010
|
type: "milestone",
|
|
25011
|
+
role: "leaf"
|
|
25012
|
+
},
|
|
25013
|
+
{
|
|
25014
|
+
type: "risk_register",
|
|
24684
25015
|
role: "container"
|
|
24685
25016
|
},
|
|
24686
25017
|
{
|
|
24687
|
-
type: "
|
|
25018
|
+
type: "change_request",
|
|
24688
25019
|
role: "leaf"
|
|
24689
25020
|
},
|
|
24690
25021
|
{
|
|
24691
|
-
type: "
|
|
25022
|
+
type: "deliverable",
|
|
24692
25023
|
role: "leaf"
|
|
24693
25024
|
},
|
|
24694
25025
|
{
|
|
24695
|
-
type: "
|
|
25026
|
+
type: "resource_allocation",
|
|
25027
|
+
role: "leaf"
|
|
25028
|
+
},
|
|
25029
|
+
{
|
|
25030
|
+
type: "status_report",
|
|
24696
25031
|
role: "leaf"
|
|
24697
25032
|
}
|
|
24698
25033
|
],
|
|
@@ -24761,8 +25096,8 @@ var UPG_REGIONS = [
|
|
|
24761
25096
|
crosses_into: "discovery_research_validation"
|
|
24762
25097
|
},
|
|
24763
25098
|
{
|
|
24764
|
-
direction: "
|
|
24765
|
-
edge_id: "
|
|
25099
|
+
direction: "import",
|
|
25100
|
+
edge_id: "wireframe_specifies_feature",
|
|
24766
25101
|
crosses_into: "experience_design_brand"
|
|
24767
25102
|
},
|
|
24768
25103
|
{
|
|
@@ -24825,10 +25160,6 @@ var UPG_REGIONS = [
|
|
|
24825
25160
|
type: "database_schema",
|
|
24826
25161
|
role: "leaf"
|
|
24827
25162
|
},
|
|
24828
|
-
{
|
|
24829
|
-
type: "data_model",
|
|
24830
|
-
role: "leaf"
|
|
24831
|
-
},
|
|
24832
25163
|
{
|
|
24833
25164
|
type: "aggregate",
|
|
24834
25165
|
role: "container"
|
|
@@ -24893,6 +25224,111 @@ var UPG_REGIONS = [
|
|
|
24893
25224
|
{
|
|
24894
25225
|
type: "technical_debt_item",
|
|
24895
25226
|
role: "leaf"
|
|
25227
|
+
},
|
|
25228
|
+
{
|
|
25229
|
+
type: "investigation",
|
|
25230
|
+
role: "container"
|
|
25231
|
+
},
|
|
25232
|
+
{
|
|
25233
|
+
type: "root_cause",
|
|
25234
|
+
role: "container"
|
|
25235
|
+
},
|
|
25236
|
+
{
|
|
25237
|
+
type: "symptom",
|
|
25238
|
+
role: "leaf"
|
|
25239
|
+
},
|
|
25240
|
+
{
|
|
25241
|
+
type: "fix",
|
|
25242
|
+
role: "leaf"
|
|
25243
|
+
},
|
|
25244
|
+
{
|
|
25245
|
+
type: "ai_model",
|
|
25246
|
+
role: "container"
|
|
25247
|
+
},
|
|
25248
|
+
{
|
|
25249
|
+
type: "prompt_template",
|
|
25250
|
+
role: "leaf"
|
|
25251
|
+
},
|
|
25252
|
+
{
|
|
25253
|
+
type: "prompt_version",
|
|
25254
|
+
role: "leaf"
|
|
25255
|
+
},
|
|
25256
|
+
{
|
|
25257
|
+
type: "eval_benchmark",
|
|
25258
|
+
role: "container"
|
|
25259
|
+
},
|
|
25260
|
+
{
|
|
25261
|
+
type: "eval_run",
|
|
25262
|
+
role: "leaf"
|
|
25263
|
+
},
|
|
25264
|
+
{
|
|
25265
|
+
type: "ai_cost_tracker",
|
|
25266
|
+
role: "leaf"
|
|
25267
|
+
},
|
|
25268
|
+
{
|
|
25269
|
+
type: "hallucination_report",
|
|
25270
|
+
role: "leaf"
|
|
25271
|
+
},
|
|
25272
|
+
{
|
|
25273
|
+
type: "ai_guardrail",
|
|
25274
|
+
role: "leaf"
|
|
25275
|
+
},
|
|
25276
|
+
{
|
|
25277
|
+
type: "model_comparison",
|
|
25278
|
+
role: "leaf"
|
|
25279
|
+
},
|
|
25280
|
+
{
|
|
25281
|
+
type: "ai_experiment",
|
|
25282
|
+
role: "leaf"
|
|
25283
|
+
},
|
|
25284
|
+
{
|
|
25285
|
+
type: "ai_dataset",
|
|
25286
|
+
role: "leaf"
|
|
25287
|
+
},
|
|
25288
|
+
{
|
|
25289
|
+
type: "ai_trace",
|
|
25290
|
+
role: "container",
|
|
25291
|
+
notes: "self-nesting inference chain"
|
|
25292
|
+
},
|
|
25293
|
+
{
|
|
25294
|
+
type: "workflow_template",
|
|
25295
|
+
role: "container"
|
|
25296
|
+
},
|
|
25297
|
+
{
|
|
25298
|
+
type: "workflow_run",
|
|
25299
|
+
role: "container"
|
|
25300
|
+
},
|
|
25301
|
+
{
|
|
25302
|
+
type: "workflow_artifact",
|
|
25303
|
+
role: "leaf"
|
|
25304
|
+
},
|
|
25305
|
+
{
|
|
25306
|
+
type: "agent_definition",
|
|
25307
|
+
role: "container"
|
|
25308
|
+
},
|
|
25309
|
+
{
|
|
25310
|
+
type: "agent_session",
|
|
25311
|
+
role: "leaf"
|
|
25312
|
+
},
|
|
25313
|
+
{
|
|
25314
|
+
type: "agent_skill",
|
|
25315
|
+
role: "leaf"
|
|
25316
|
+
},
|
|
25317
|
+
{
|
|
25318
|
+
type: "agent_hook",
|
|
25319
|
+
role: "leaf"
|
|
25320
|
+
},
|
|
25321
|
+
{
|
|
25322
|
+
type: "agent_task",
|
|
25323
|
+
role: "leaf"
|
|
25324
|
+
},
|
|
25325
|
+
{
|
|
25326
|
+
type: "review_gate",
|
|
25327
|
+
role: "container"
|
|
25328
|
+
},
|
|
25329
|
+
{
|
|
25330
|
+
type: "approval_record",
|
|
25331
|
+
role: "leaf"
|
|
24896
25332
|
}
|
|
24897
25333
|
],
|
|
24898
25334
|
anchor: {
|
|
@@ -24911,7 +25347,7 @@ var UPG_REGIONS = [
|
|
|
24911
25347
|
"service_depends_on_library_dependency",
|
|
24912
25348
|
"service_carries_technical_debt_item",
|
|
24913
25349
|
"service_toggles_feature_flag",
|
|
24914
|
-
"
|
|
25350
|
+
"service_affected_by_root_cause",
|
|
24915
25351
|
"service_investigated_via_investigation"
|
|
24916
25352
|
],
|
|
24917
25353
|
boundary_edges: [
|
|
@@ -24995,6 +25431,26 @@ var UPG_REGIONS = [
|
|
|
24995
25431
|
type: "unit_economics",
|
|
24996
25432
|
role: "leaf"
|
|
24997
25433
|
},
|
|
25434
|
+
{
|
|
25435
|
+
type: "partnership",
|
|
25436
|
+
role: "leaf"
|
|
25437
|
+
},
|
|
25438
|
+
{
|
|
25439
|
+
type: "key_resource",
|
|
25440
|
+
role: "leaf"
|
|
25441
|
+
},
|
|
25442
|
+
{
|
|
25443
|
+
type: "key_activity",
|
|
25444
|
+
role: "leaf"
|
|
25445
|
+
},
|
|
25446
|
+
{
|
|
25447
|
+
type: "customer_relationship",
|
|
25448
|
+
role: "leaf"
|
|
25449
|
+
},
|
|
25450
|
+
{
|
|
25451
|
+
type: "distribution_channel",
|
|
25452
|
+
role: "leaf"
|
|
25453
|
+
},
|
|
24998
25454
|
{
|
|
24999
25455
|
type: "pricing_strategy",
|
|
25000
25456
|
role: "root"
|
|
@@ -25003,6 +25459,18 @@ var UPG_REGIONS = [
|
|
|
25003
25459
|
type: "pricing_tier",
|
|
25004
25460
|
role: "leaf"
|
|
25005
25461
|
},
|
|
25462
|
+
{
|
|
25463
|
+
type: "discount_strategy",
|
|
25464
|
+
role: "leaf"
|
|
25465
|
+
},
|
|
25466
|
+
{
|
|
25467
|
+
type: "trial_config",
|
|
25468
|
+
role: "leaf"
|
|
25469
|
+
},
|
|
25470
|
+
{
|
|
25471
|
+
type: "paywall",
|
|
25472
|
+
role: "leaf"
|
|
25473
|
+
},
|
|
25006
25474
|
{
|
|
25007
25475
|
type: "gtm_strategy",
|
|
25008
25476
|
role: "root"
|
|
@@ -25019,10 +25487,30 @@ var UPG_REGIONS = [
|
|
|
25019
25487
|
type: "messaging",
|
|
25020
25488
|
role: "leaf"
|
|
25021
25489
|
},
|
|
25490
|
+
{
|
|
25491
|
+
type: "content_strategy",
|
|
25492
|
+
role: "container"
|
|
25493
|
+
},
|
|
25494
|
+
{
|
|
25495
|
+
type: "sales_motion",
|
|
25496
|
+
role: "leaf"
|
|
25497
|
+
},
|
|
25498
|
+
{
|
|
25499
|
+
type: "demand_gen_program",
|
|
25500
|
+
role: "leaf"
|
|
25501
|
+
},
|
|
25502
|
+
{
|
|
25503
|
+
type: "territory",
|
|
25504
|
+
role: "leaf"
|
|
25505
|
+
},
|
|
25022
25506
|
{
|
|
25023
25507
|
type: "objection",
|
|
25024
25508
|
role: "leaf"
|
|
25025
25509
|
},
|
|
25510
|
+
{
|
|
25511
|
+
type: "rebuttal",
|
|
25512
|
+
role: "container"
|
|
25513
|
+
},
|
|
25026
25514
|
{
|
|
25027
25515
|
type: "proof_point",
|
|
25028
25516
|
role: "leaf"
|
|
@@ -25070,6 +25558,114 @@ var UPG_REGIONS = [
|
|
|
25070
25558
|
{
|
|
25071
25559
|
type: "variant",
|
|
25072
25560
|
role: "leaf"
|
|
25561
|
+
},
|
|
25562
|
+
{
|
|
25563
|
+
type: "account",
|
|
25564
|
+
role: "container"
|
|
25565
|
+
},
|
|
25566
|
+
{
|
|
25567
|
+
type: "contact",
|
|
25568
|
+
role: "leaf"
|
|
25569
|
+
},
|
|
25570
|
+
{
|
|
25571
|
+
type: "lead",
|
|
25572
|
+
role: "leaf"
|
|
25573
|
+
},
|
|
25574
|
+
{
|
|
25575
|
+
type: "deal",
|
|
25576
|
+
role: "container"
|
|
25577
|
+
},
|
|
25578
|
+
{
|
|
25579
|
+
type: "pipeline_sales",
|
|
25580
|
+
role: "container"
|
|
25581
|
+
},
|
|
25582
|
+
{
|
|
25583
|
+
type: "pipeline_stage",
|
|
25584
|
+
role: "leaf"
|
|
25585
|
+
},
|
|
25586
|
+
{
|
|
25587
|
+
type: "quote_document",
|
|
25588
|
+
role: "leaf"
|
|
25589
|
+
},
|
|
25590
|
+
{
|
|
25591
|
+
type: "subscription",
|
|
25592
|
+
role: "container"
|
|
25593
|
+
},
|
|
25594
|
+
{
|
|
25595
|
+
type: "invoice",
|
|
25596
|
+
role: "leaf"
|
|
25597
|
+
},
|
|
25598
|
+
{
|
|
25599
|
+
type: "forecast",
|
|
25600
|
+
role: "leaf"
|
|
25601
|
+
},
|
|
25602
|
+
{
|
|
25603
|
+
type: "marketing_strategy",
|
|
25604
|
+
role: "container"
|
|
25605
|
+
},
|
|
25606
|
+
{
|
|
25607
|
+
type: "marketing_channel",
|
|
25608
|
+
role: "container"
|
|
25609
|
+
},
|
|
25610
|
+
{
|
|
25611
|
+
type: "marketing_campaign_plan",
|
|
25612
|
+
role: "container"
|
|
25613
|
+
},
|
|
25614
|
+
{
|
|
25615
|
+
type: "email_sequence",
|
|
25616
|
+
role: "leaf"
|
|
25617
|
+
},
|
|
25618
|
+
{
|
|
25619
|
+
type: "social_post",
|
|
25620
|
+
role: "leaf"
|
|
25621
|
+
},
|
|
25622
|
+
{
|
|
25623
|
+
type: "seo_keyword",
|
|
25624
|
+
role: "leaf"
|
|
25625
|
+
},
|
|
25626
|
+
{
|
|
25627
|
+
type: "ad_creative",
|
|
25628
|
+
role: "leaf"
|
|
25629
|
+
},
|
|
25630
|
+
{
|
|
25631
|
+
type: "press_release",
|
|
25632
|
+
role: "leaf"
|
|
25633
|
+
},
|
|
25634
|
+
{
|
|
25635
|
+
type: "event",
|
|
25636
|
+
role: "leaf"
|
|
25637
|
+
},
|
|
25638
|
+
{
|
|
25639
|
+
type: "community_initiative",
|
|
25640
|
+
role: "leaf"
|
|
25641
|
+
},
|
|
25642
|
+
{
|
|
25643
|
+
type: "partner_program",
|
|
25644
|
+
role: "container"
|
|
25645
|
+
},
|
|
25646
|
+
{
|
|
25647
|
+
type: "partner_tier",
|
|
25648
|
+
role: "leaf"
|
|
25649
|
+
},
|
|
25650
|
+
{
|
|
25651
|
+
type: "api_ecosystem",
|
|
25652
|
+
role: "container"
|
|
25653
|
+
},
|
|
25654
|
+
{
|
|
25655
|
+
type: "marketplace_listing",
|
|
25656
|
+
role: "leaf"
|
|
25657
|
+
},
|
|
25658
|
+
{
|
|
25659
|
+
type: "developer_portal",
|
|
25660
|
+
role: "leaf"
|
|
25661
|
+
},
|
|
25662
|
+
{
|
|
25663
|
+
type: "integration_partner",
|
|
25664
|
+
role: "leaf"
|
|
25665
|
+
},
|
|
25666
|
+
{
|
|
25667
|
+
type: "partner_revenue_share",
|
|
25668
|
+
role: "leaf"
|
|
25073
25669
|
}
|
|
25074
25670
|
],
|
|
25075
25671
|
anchor: {
|
|
@@ -25176,7 +25772,8 @@ var UPG_REGIONS = [
|
|
|
25176
25772
|
entities: [
|
|
25177
25773
|
{
|
|
25178
25774
|
type: "metric",
|
|
25179
|
-
role: "anchor"
|
|
25775
|
+
role: "anchor",
|
|
25776
|
+
notes: "canonical home is Strategy; anchors Analytics as the measurement plane"
|
|
25180
25777
|
},
|
|
25181
25778
|
{
|
|
25182
25779
|
type: "data_source",
|
|
@@ -25190,24 +25787,36 @@ var UPG_REGIONS = [
|
|
|
25190
25787
|
type: "dashboard",
|
|
25191
25788
|
role: "container"
|
|
25192
25789
|
},
|
|
25790
|
+
{
|
|
25791
|
+
type: "data_model",
|
|
25792
|
+
role: "leaf"
|
|
25793
|
+
},
|
|
25193
25794
|
{
|
|
25194
25795
|
type: "data_domain",
|
|
25195
25796
|
role: "container"
|
|
25196
25797
|
},
|
|
25197
25798
|
{
|
|
25198
|
-
type: "
|
|
25799
|
+
type: "data_product",
|
|
25199
25800
|
role: "leaf"
|
|
25200
25801
|
},
|
|
25201
25802
|
{
|
|
25202
|
-
type: "
|
|
25803
|
+
type: "data_pipeline",
|
|
25203
25804
|
role: "leaf"
|
|
25204
25805
|
},
|
|
25205
25806
|
{
|
|
25206
|
-
type: "
|
|
25807
|
+
type: "data_lineage",
|
|
25207
25808
|
role: "leaf"
|
|
25208
25809
|
},
|
|
25209
25810
|
{
|
|
25210
|
-
type: "
|
|
25811
|
+
type: "glossary_term",
|
|
25812
|
+
role: "leaf"
|
|
25813
|
+
},
|
|
25814
|
+
{
|
|
25815
|
+
type: "report",
|
|
25816
|
+
role: "leaf"
|
|
25817
|
+
},
|
|
25818
|
+
{
|
|
25819
|
+
type: "data_quality_rule",
|
|
25211
25820
|
role: "leaf"
|
|
25212
25821
|
}
|
|
25213
25822
|
],
|
|
@@ -25333,7 +25942,27 @@ var UPG_REGIONS = [
|
|
|
25333
25942
|
{
|
|
25334
25943
|
type: "deployment",
|
|
25335
25944
|
role: "leaf",
|
|
25336
|
-
notes: "
|
|
25945
|
+
notes: "canonical home is Engineering; release event surfaced to Ops"
|
|
25946
|
+
},
|
|
25947
|
+
{
|
|
25948
|
+
type: "alert_rule",
|
|
25949
|
+
role: "leaf"
|
|
25950
|
+
},
|
|
25951
|
+
{
|
|
25952
|
+
type: "ci_pipeline",
|
|
25953
|
+
role: "container"
|
|
25954
|
+
},
|
|
25955
|
+
{
|
|
25956
|
+
type: "release_strategy",
|
|
25957
|
+
role: "leaf"
|
|
25958
|
+
},
|
|
25959
|
+
{
|
|
25960
|
+
type: "on_call_rotation",
|
|
25961
|
+
role: "leaf"
|
|
25962
|
+
},
|
|
25963
|
+
{
|
|
25964
|
+
type: "infrastructure_component",
|
|
25965
|
+
role: "container"
|
|
25337
25966
|
},
|
|
25338
25967
|
{
|
|
25339
25968
|
type: "test_suite",
|
|
@@ -25351,10 +25980,26 @@ var UPG_REGIONS = [
|
|
|
25351
25980
|
type: "test_result",
|
|
25352
25981
|
role: "leaf"
|
|
25353
25982
|
},
|
|
25983
|
+
{
|
|
25984
|
+
type: "regression_test",
|
|
25985
|
+
role: "leaf"
|
|
25986
|
+
},
|
|
25987
|
+
{
|
|
25988
|
+
type: "test_coverage_report",
|
|
25989
|
+
role: "leaf"
|
|
25990
|
+
},
|
|
25991
|
+
{
|
|
25992
|
+
type: "test_environment",
|
|
25993
|
+
role: "leaf"
|
|
25994
|
+
},
|
|
25354
25995
|
{
|
|
25355
25996
|
type: "threat_model",
|
|
25356
25997
|
role: "root"
|
|
25357
25998
|
},
|
|
25999
|
+
{
|
|
26000
|
+
type: "threat",
|
|
26001
|
+
role: "leaf"
|
|
26002
|
+
},
|
|
25358
26003
|
{
|
|
25359
26004
|
type: "security_control",
|
|
25360
26005
|
role: "leaf"
|
|
@@ -25371,14 +26016,34 @@ var UPG_REGIONS = [
|
|
|
25371
26016
|
type: "penetration_test",
|
|
25372
26017
|
role: "leaf"
|
|
25373
26018
|
},
|
|
26019
|
+
{
|
|
26020
|
+
type: "security_review",
|
|
26021
|
+
role: "container"
|
|
26022
|
+
},
|
|
26023
|
+
{
|
|
26024
|
+
type: "data_classification",
|
|
26025
|
+
role: "leaf"
|
|
26026
|
+
},
|
|
26027
|
+
{
|
|
26028
|
+
type: "access_policy",
|
|
26029
|
+
role: "leaf"
|
|
26030
|
+
},
|
|
25374
26031
|
{
|
|
25375
26032
|
type: "a11y_standard",
|
|
25376
26033
|
role: "leaf"
|
|
25377
26034
|
},
|
|
26035
|
+
{
|
|
26036
|
+
type: "a11y_guideline",
|
|
26037
|
+
role: "leaf"
|
|
26038
|
+
},
|
|
25378
26039
|
{
|
|
25379
26040
|
type: "a11y_audit",
|
|
25380
26041
|
role: "leaf"
|
|
25381
26042
|
},
|
|
26043
|
+
{
|
|
26044
|
+
type: "a11y_issue",
|
|
26045
|
+
role: "leaf"
|
|
26046
|
+
},
|
|
25382
26047
|
{
|
|
25383
26048
|
type: "a11y_annotation",
|
|
25384
26049
|
role: "leaf"
|
|
@@ -25396,11 +26061,15 @@ var UPG_REGIONS = [
|
|
|
25396
26061
|
role: "leaf"
|
|
25397
26062
|
},
|
|
25398
26063
|
{
|
|
25399
|
-
type: "
|
|
26064
|
+
type: "data_contract",
|
|
25400
26065
|
role: "leaf"
|
|
25401
26066
|
},
|
|
25402
26067
|
{
|
|
25403
|
-
type: "
|
|
26068
|
+
type: "audit_log_policy",
|
|
26069
|
+
role: "leaf"
|
|
26070
|
+
},
|
|
26071
|
+
{
|
|
26072
|
+
type: "security_audit",
|
|
25404
26073
|
role: "leaf"
|
|
25405
26074
|
},
|
|
25406
26075
|
{
|
|
@@ -25429,16 +26098,16 @@ var UPG_REGIONS = [
|
|
|
25429
26098
|
role: "root"
|
|
25430
26099
|
},
|
|
25431
26100
|
{
|
|
25432
|
-
type: "
|
|
26101
|
+
type: "customer_journey_stage",
|
|
25433
26102
|
role: "container"
|
|
25434
26103
|
},
|
|
25435
26104
|
{
|
|
25436
|
-
type: "
|
|
25437
|
-
role: "
|
|
26105
|
+
type: "touchpoint",
|
|
26106
|
+
role: "leaf"
|
|
25438
26107
|
},
|
|
25439
26108
|
{
|
|
25440
|
-
type: "
|
|
25441
|
-
role: "
|
|
26109
|
+
type: "success_milestone",
|
|
26110
|
+
role: "leaf"
|
|
25442
26111
|
},
|
|
25443
26112
|
{
|
|
25444
26113
|
type: "team",
|
|
@@ -25452,6 +26121,10 @@ var UPG_REGIONS = [
|
|
|
25452
26121
|
type: "role",
|
|
25453
26122
|
role: "leaf"
|
|
25454
26123
|
},
|
|
26124
|
+
{
|
|
26125
|
+
type: "person",
|
|
26126
|
+
role: "leaf"
|
|
26127
|
+
},
|
|
25455
26128
|
{
|
|
25456
26129
|
type: "stakeholder",
|
|
25457
26130
|
role: "leaf",
|
|
@@ -25479,6 +26152,78 @@ var UPG_REGIONS = [
|
|
|
25479
26152
|
},
|
|
25480
26153
|
{
|
|
25481
26154
|
type: "capacity_plan",
|
|
26155
|
+
role: "leaf"
|
|
26156
|
+
},
|
|
26157
|
+
{
|
|
26158
|
+
type: "legal_entity",
|
|
26159
|
+
role: "container"
|
|
26160
|
+
},
|
|
26161
|
+
{
|
|
26162
|
+
type: "ip_asset",
|
|
26163
|
+
role: "leaf"
|
|
26164
|
+
},
|
|
26165
|
+
{
|
|
26166
|
+
type: "contract",
|
|
26167
|
+
role: "container"
|
|
26168
|
+
},
|
|
26169
|
+
{
|
|
26170
|
+
type: "contract_clause",
|
|
26171
|
+
role: "leaf"
|
|
26172
|
+
},
|
|
26173
|
+
{
|
|
26174
|
+
type: "privacy_policy",
|
|
26175
|
+
role: "leaf"
|
|
26176
|
+
},
|
|
26177
|
+
{
|
|
26178
|
+
type: "locale",
|
|
26179
|
+
role: "container"
|
|
26180
|
+
},
|
|
26181
|
+
{
|
|
26182
|
+
type: "translation_key",
|
|
26183
|
+
role: "leaf"
|
|
26184
|
+
},
|
|
26185
|
+
{
|
|
26186
|
+
type: "translation_bundle",
|
|
26187
|
+
role: "container"
|
|
26188
|
+
},
|
|
26189
|
+
{
|
|
26190
|
+
type: "locale_config",
|
|
26191
|
+
role: "leaf"
|
|
26192
|
+
},
|
|
26193
|
+
{
|
|
26194
|
+
type: "cultural_adaptation",
|
|
26195
|
+
role: "leaf"
|
|
26196
|
+
},
|
|
26197
|
+
{
|
|
26198
|
+
type: "regional_pricing",
|
|
26199
|
+
role: "leaf"
|
|
26200
|
+
},
|
|
26201
|
+
{
|
|
26202
|
+
type: "education_program",
|
|
26203
|
+
role: "container"
|
|
26204
|
+
},
|
|
26205
|
+
{
|
|
26206
|
+
type: "tutorial",
|
|
26207
|
+
role: "leaf"
|
|
26208
|
+
},
|
|
26209
|
+
{
|
|
26210
|
+
type: "walkthrough",
|
|
26211
|
+
role: "leaf"
|
|
26212
|
+
},
|
|
26213
|
+
{
|
|
26214
|
+
type: "webinar",
|
|
26215
|
+
role: "leaf"
|
|
26216
|
+
},
|
|
26217
|
+
{
|
|
26218
|
+
type: "certification",
|
|
26219
|
+
role: "leaf"
|
|
26220
|
+
},
|
|
26221
|
+
{
|
|
26222
|
+
type: "help_video",
|
|
26223
|
+
role: "leaf"
|
|
26224
|
+
},
|
|
26225
|
+
{
|
|
26226
|
+
type: "learning_path",
|
|
25482
26227
|
role: "container"
|
|
25483
26228
|
}
|
|
25484
26229
|
],
|
|
@@ -25495,7 +26240,6 @@ var UPG_REGIONS = [
|
|
|
25495
26240
|
"incident_analysed_in_postmortem",
|
|
25496
26241
|
"incident_triggers_postmortem",
|
|
25497
26242
|
"incident_breaches_service_level_objective",
|
|
25498
|
-
"incident_caused_by_root_cause",
|
|
25499
26243
|
"incident_exploits_vulnerability"
|
|
25500
26244
|
],
|
|
25501
26245
|
boundary_edges: [
|
|
@@ -25516,8 +26260,8 @@ var UPG_REGIONS = [
|
|
|
25516
26260
|
},
|
|
25517
26261
|
{
|
|
25518
26262
|
direction: "export",
|
|
25519
|
-
edge_id: "
|
|
25520
|
-
crosses_into: "
|
|
26263
|
+
edge_id: "incident_caused_by_root_cause",
|
|
26264
|
+
crosses_into: "engineering_platform"
|
|
25521
26265
|
},
|
|
25522
26266
|
{
|
|
25523
26267
|
direction: "export",
|
|
@@ -25913,7 +26657,16 @@ function portfolioBody(doc) {
|
|
|
25913
26657
|
product_areas: [...doc.product_areas ?? []].sort((a, b) => byCodeUnit(a.id ?? "", b.id ?? "")).map((a) => orderedObject(a, ["id", "title", "description", "parent_area_id", "strategic_priority", "products"], { forceKeys: ["id", "title"] })),
|
|
25914
26658
|
portfolios: [...doc.portfolios ?? []].sort((a, b) => byCodeUnit(a.id ?? "", b.id ?? "")).map((p) => orderedObject(p, ["id", "title", "description", "parent_portfolio_id", "hierarchy_model", "products"], { forceKeys: ["id", "title"] })),
|
|
25915
26659
|
products,
|
|
25916
|
-
cross_edges: sortEdges(doc.cross_edges ?? []).map(canonicalCrossEdge)
|
|
26660
|
+
cross_edges: sortEdges(doc.cross_edges ?? []).map(canonicalCrossEdge),
|
|
26661
|
+
// Registry tier (shared vocabulary). Emitted only when non-empty so existing
|
|
26662
|
+
// portfolio files without a registry stay byte-identical. Canonical entities
|
|
26663
|
+
// are normal nodes, serialised with the same node/edge canonical rules.
|
|
26664
|
+
...doc.registry && doc.registry.nodes.length > 0 ? {
|
|
26665
|
+
registry: {
|
|
26666
|
+
nodes: sortNodes(doc.registry.nodes).map(canonicalNode),
|
|
26667
|
+
...doc.registry.edges && doc.registry.edges.length > 0 ? { edges: sortEdges(doc.registry.edges).map(canonicalEdge) } : {}
|
|
26668
|
+
}
|
|
26669
|
+
} : {}
|
|
25917
26670
|
};
|
|
25918
26671
|
}
|
|
25919
26672
|
function computeBodyChecksum(doc) {
|
|
@@ -26013,6 +26766,13 @@ function normalizeDocument(obj) {
|
|
|
26013
26766
|
})),
|
|
26014
26767
|
cross_edges: raw.cross_edges ?? []
|
|
26015
26768
|
};
|
|
26769
|
+
const rawRegistry = raw.registry;
|
|
26770
|
+
if (rawRegistry && Array.isArray(rawRegistry.nodes)) {
|
|
26771
|
+
out2.registry = {
|
|
26772
|
+
nodes: rawRegistry.nodes.map((n) => repairNodeDrift(n)),
|
|
26773
|
+
...Array.isArray(rawRegistry.edges) ? { edges: rawRegistry.edges } : {}
|
|
26774
|
+
};
|
|
26775
|
+
}
|
|
26016
26776
|
return out2;
|
|
26017
26777
|
}
|
|
26018
26778
|
const out = {
|
|
@@ -26035,7 +26795,7 @@ function isCanonical(text) {
|
|
|
26035
26795
|
}
|
|
26036
26796
|
|
|
26037
26797
|
// src/index.ts
|
|
26038
|
-
var UPG_VERSION = "0.9.
|
|
26798
|
+
var UPG_VERSION = "0.9.7";
|
|
26039
26799
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
26040
26800
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
26041
26801
|
var UPG_TYPES = getTypes();
|
|
@@ -26114,6 +26874,7 @@ export {
|
|
|
26114
26874
|
PRODUCT_DELIVERY_PLAYBOOK,
|
|
26115
26875
|
PROPERTY_SCALE_MAP,
|
|
26116
26876
|
REFLECT_MODES,
|
|
26877
|
+
REGISTRY_PRODUCT_ID,
|
|
26117
26878
|
STRATEGY_OUTCOMES_PLAYBOOK,
|
|
26118
26879
|
UPG_ACTIVE_TYPES,
|
|
26119
26880
|
UPG_ANTI_PATTERNS,
|