@unified-product-graph/core 0.23.2 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -1
- package/README.md +1 -1
- package/dist/index.cjs +151 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +187 -3
- package/dist/index.d.ts +187 -3
- package/dist/index.js +151 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3253,7 +3253,105 @@ var UPG_EDGE_CATALOG = {
|
|
|
3253
3253
|
// product's feature or capability, authored in a different graph within the
|
|
3254
3254
|
// portfolio, fits the 0.17.3 locked predicate.
|
|
3255
3255
|
objective_defers_feature: { forward_verb: "defers", reverse_verb: "deferred_by", classification: "cross-domain", source_type: "objective", target_type: "feature", carries_properties: true, property_schema: DEFER_EDGE_PROPERTY_SCHEMA, cross_product_eligible: true, deliberate_only: true },
|
|
3256
|
-
objective_defers_capability: { forward_verb: "defers", reverse_verb: "deferred_by", classification: "semantic", source_type: "objective", target_type: "capability", carries_properties: true, property_schema: DEFER_EDGE_PROPERTY_SCHEMA, cross_product_eligible: true, deliberate_only: true }
|
|
3256
|
+
objective_defers_capability: { forward_verb: "defers", reverse_verb: "deferred_by", classification: "semantic", source_type: "objective", target_type: "capability", carries_properties: true, property_schema: DEFER_EDGE_PROPERTY_SCHEMA, cross_product_eligible: true, deliberate_only: true },
|
|
3257
|
+
// ── Enterprise GTM coordination batch (0.24.0, Track 1 Wave A) ───────────────
|
|
3258
|
+
// The catalog modelled each go-to-market department's nouns but almost none of
|
|
3259
|
+
// the handoffs between them, and the enterprise motion IS the handoffs (audit
|
|
3260
|
+
// `2026-07-16-enterprise-gtm-coverage-audit.md`, §3). Sixteen additive edges
|
|
3261
|
+
// wire the buying committee onto the deal, give the enablement lattice a demand
|
|
3262
|
+
// side, close the pre-sale win/loss LEARN loop, make post-sale account-scoped,
|
|
3263
|
+
// and complete the audience-projection lattice. None are hierarchy — every one
|
|
3264
|
+
// is a lateral coordination link — so UPG_VALID_CHILDREN is untouched. Verbs
|
|
3265
|
+
// are precedent-matched (cited per row); classification per the standard
|
|
3266
|
+
// taxonomy. Two edges are portfolio-crossing by construction (a deal in a
|
|
3267
|
+
// field-ops graph blocked by a feature in a product graph; a win/loss study in
|
|
3268
|
+
// a research graph analysing a deal in another) → cross_product_eligible at
|
|
3269
|
+
// mint, one line rather than a later migration (audit §7-addendum decision 6).
|
|
3270
|
+
// Buying committee (F2). A contact was reachable only via account_contains_contact;
|
|
3271
|
+
// it could not attach to the deal it influences. This is the substrate of every
|
|
3272
|
+
// qualification framework (MEDDICC/SPICED) and of multi-threading. Semantic, not
|
|
3273
|
+
// hierarchy: the contact is parented under its account (account_contains_contact),
|
|
3274
|
+
// so a deal references it laterally, not by containment; and semantic, not
|
|
3275
|
+
// cross-domain, because deal and contact are both in the sales domain (T1.7
|
|
3276
|
+
// guardrail: a within-domain edge is not cross-domain). @example deal "Northwind
|
|
3277
|
+
// platform expansion" involves contact "VP Engineering" (buying_role: 'economic_buyer').
|
|
3278
|
+
deal_involves_contact: { forward_verb: "involves", reverse_verb: "involved_in", classification: "semantic", source_type: "deal", target_type: "contact" },
|
|
3279
|
+
// Enablement demand side (F3). GTM's objection→rebuttal→proof_point chain had
|
|
3280
|
+
// supply but nothing consuming it in a deal context. Mirrors the positioning
|
|
3281
|
+
// precedent (positioning_challenged_by_objection). @example deal "Northwind
|
|
3282
|
+
// platform expansion" challenged_by objection "no SOC 2 report yet".
|
|
3283
|
+
deal_challenged_by_objection: { forward_verb: "challenged_by", reverse_verb: "challenges", classification: "cross-domain", source_type: "deal", target_type: "objection" },
|
|
3284
|
+
// Enablement deployed in context (F3). Which battlecard was armed on which deal.
|
|
3285
|
+
// Mirrors gtm_strategy_arms_with_competitive_battle_card. @example deal armed_with
|
|
3286
|
+
// competitive_battle_card "vs. Meridian Cloud".
|
|
3287
|
+
deal_armed_with_competitive_battle_card: { forward_verb: "armed_with", reverse_verb: "arms", classification: "cross-domain", source_type: "deal", target_type: "competitive_battle_card" },
|
|
3288
|
+
// Loss cause (F3). Gives competitive_battle_card.win_rate its derivation path —
|
|
3289
|
+
// nothing in the graph could previously compute it. Causal (a directional
|
|
3290
|
+
// outcome), mirroring lead_becomes_account. @example deal "Sterling Data Systems
|
|
3291
|
+
// renewal" lost_to competitor "Meridian Cloud".
|
|
3292
|
+
deal_lost_to_competitor: { forward_verb: "lost_to", reverse_verb: "won", classification: "causal", source_type: "deal", target_type: "competitor" },
|
|
3293
|
+
// Close mechanism (F4). MSA/SOW/order form reachable from the deal; contract
|
|
3294
|
+
// previously bound only legal_entity and partnership. Mirrors
|
|
3295
|
+
// deal_quoted_via_quote_document. @example deal closed_via contract "Northwind MSA".
|
|
3296
|
+
deal_closed_via_contract: { forward_verb: "closed_via", reverse_verb: "closes", classification: "cross-domain", source_type: "deal", target_type: "contract" },
|
|
3297
|
+
// Pipeline blocker (F5). "Which roadmap items unblock how much pipeline"; plugs
|
|
3298
|
+
// into change_blast_radius. Mirrors epic_affected_by_bug. cross_product_eligible:
|
|
3299
|
+
// the deal lives in the field-ops graph, the blocking feature in the product
|
|
3300
|
+
// graph. @example deal blocked_by feature "SAML SSO".
|
|
3301
|
+
deal_blocked_by_feature: { forward_verb: "blocked_by", reverse_verb: "blocks", classification: "cross-domain", source_type: "deal", target_type: "feature", cross_product_eligible: true },
|
|
3302
|
+
// Win/loss LEARN loop (F3). Win/loss analysis is a research genre, not a new
|
|
3303
|
+
// type — a research_study analyses the deal. Closes the pre-sale learning loop
|
|
3304
|
+
// (the post-sale one already existed via support_ticket_reveals_need). Mirrors
|
|
3305
|
+
// proof_point_derived_from_insight's provenance shape. cross_product_eligible:
|
|
3306
|
+
// the study may live in a research graph distinct from the deal's field-ops
|
|
3307
|
+
// graph. @example research_study "Q3 competitive win/loss" analyzes deal
|
|
3308
|
+
// "Sterling Data Systems renewal".
|
|
3309
|
+
research_study_analyzes_deal: { forward_verb: "analyzes", reverse_verb: "analyzed_by", classification: "cross-domain", source_type: "research_study", target_type: "deal", cross_product_eligible: true },
|
|
3310
|
+
// Account-scoped sensing (F5). Nearly every CS edge hung off product; only one
|
|
3311
|
+
// scoped anything to an account. Mirrors product_supports_via_support_ticket.
|
|
3312
|
+
// @example account "Northwind Logistics" raises support_ticket "onboarding SSO
|
|
3313
|
+
// blocker".
|
|
3314
|
+
account_raises_support_ticket: { forward_verb: "raises", reverse_verb: "raised_by", classification: "cross-domain", source_type: "account", target_type: "support_ticket" },
|
|
3315
|
+
// Account health (F5). Mirrors product_health_scored_via_customer_health_score.
|
|
3316
|
+
// @example account health_scored_via customer_health_score "Northwind Q3 health".
|
|
3317
|
+
account_health_scored_via_customer_health_score: { forward_verb: "health_scored_via", reverse_verb: "scores", classification: "cross-domain", source_type: "account", target_type: "customer_health_score" },
|
|
3318
|
+
// Account churn (F5). Churn lands on the account, not just the product. Mirrors
|
|
3319
|
+
// product_loses_because_churn_reason. @example account lost_because churn_reason
|
|
3320
|
+
// "switched to incumbent suite".
|
|
3321
|
+
account_lost_because_churn_reason: { forward_verb: "lost_because", reverse_verb: "causes_churn_for", classification: "cross-domain", source_type: "account", target_type: "churn_reason" },
|
|
3322
|
+
// Onboarding / implementation (F5). Reuses the Program Management machinery
|
|
3323
|
+
// (project/milestone/deliverable/status_report) for enterprise onboarding.
|
|
3324
|
+
// Mirrors the operate-a-thing-via-a-plan shape of product_operated_via_playbook.
|
|
3325
|
+
// @example account implements_via project "Northwind rollout".
|
|
3326
|
+
account_implements_via_project: { forward_verb: "implements_via", reverse_verb: "implements", classification: "cross-domain", source_type: "account", target_type: "project" },
|
|
3327
|
+
// Renewal object-path (F5). A renewal is a deal of deal_type 'renewal'; this
|
|
3328
|
+
// completes the lead→account→deal→subscription→deal cycle. Causal (a directional
|
|
3329
|
+
// renewal event), mirroring quote_document_advances_deal. @example subscription
|
|
3330
|
+
// "Northwind annual" renews_via deal "Northwind FY27 renewal".
|
|
3331
|
+
subscription_renews_via_deal: { forward_verb: "renews_via", reverse_verb: "renews", classification: "causal", source_type: "subscription", target_type: "deal" },
|
|
3332
|
+
// Enterprise early access (F5, rider R1). An account participates in a beta
|
|
3333
|
+
// program. Mirrors product_runs_beta_program's noun. @example account
|
|
3334
|
+
// participates_in beta_program "SSO private beta".
|
|
3335
|
+
account_participates_in_beta_program: { forward_verb: "participates_in", reverse_verb: "has_participant", classification: "cross-domain", source_type: "account", target_type: "beta_program" },
|
|
3336
|
+
// Security gate (F4, rider R2). The security questionnaire/review as a deal gate,
|
|
3337
|
+
// reusing the Security noun rather than minting security_questionnaire. Mirrors
|
|
3338
|
+
// service_level_agreement_covers_account's account↔security cross-domain shape.
|
|
3339
|
+
// @example deal gated_by security_review "Northwind vendor security assessment".
|
|
3340
|
+
deal_gated_by_security_review: { forward_verb: "gated_by", reverse_verb: "gates", classification: "cross-domain", source_type: "deal", target_type: "security_review" },
|
|
3341
|
+
// Audience-projection subject axis (Ruling 4, A15). messaging's only subject edge
|
|
3342
|
+
// was positioning_communicated_via_messaging — messaging could not be ABOUT a
|
|
3343
|
+
// feature, so audience-scoped feature projections were unexpressable at the root.
|
|
3344
|
+
// Mirrors the positioning precedent. The rendered projection is NOT stored (views
|
|
3345
|
+
// philosophy); this edge stores the atom the lens queries. @example feature "SAML
|
|
3346
|
+
// SSO" communicated_via messaging "SSO beta enablement one-pager".
|
|
3347
|
+
feature_communicated_via_messaging: { forward_verb: "communicated_via", reverse_verb: "communicates", classification: "cross-domain", source_type: "feature", target_type: "messaging" },
|
|
3348
|
+
// Launch coordination seam (Ruling 4, A16). launch had edges to
|
|
3349
|
+
// release/feature/channel/campaign/metric/messaging but none to Program
|
|
3350
|
+
// Management — the GTM readiness checklist (who builds the demo env, trains the
|
|
3351
|
+
// SEs, by when) had no home. Reuses project/milestone/deliverable, the same move
|
|
3352
|
+
// as account_implements_via_project. @example launch "SSO GA" coordinated_via
|
|
3353
|
+
// project "SSO launch readiness".
|
|
3354
|
+
launch_coordinated_via_project: { forward_verb: "coordinated_via", reverse_verb: "coordinates", classification: "cross-domain", source_type: "launch", target_type: "project" }
|
|
3257
3355
|
};
|
|
3258
3356
|
var UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES = Object.keys(UPG_EDGE_CATALOG).filter(
|
|
3259
3357
|
(k) => UPG_EDGE_CATALOG[k].cross_product_eligible === true
|
|
@@ -6561,6 +6659,8 @@ var PROPERTY_SCALE_MAP = {
|
|
|
6561
6659
|
// market/risk (UPG-579 Option B)
|
|
6562
6660
|
probability: "confidence_5",
|
|
6563
6661
|
// sales/forecast (UPG-579 Option B)
|
|
6662
|
+
qualification_score: "confidence_5",
|
|
6663
|
+
// sales/deal — how confident the qualification is (0.24.0)
|
|
6564
6664
|
// ── Effort ───────────────────────────────────────────────────────────────
|
|
6565
6665
|
effort: "effort_5",
|
|
6566
6666
|
// discovery
|
|
@@ -10055,7 +10155,10 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10055
10155
|
account: {
|
|
10056
10156
|
account_type: { type: "string", enum: ["prospect", "customer", "partner", "churned"], description: "Relationship status of this account" },
|
|
10057
10157
|
industry: { type: "string", description: "Industry vertical the account operates in" },
|
|
10058
|
-
employee_count: { type: "number", description: "Number of employees at the account", modifier: "snapshot" }
|
|
10158
|
+
employee_count: { type: "number", description: "Number of employees at the account", modifier: "snapshot" },
|
|
10159
|
+
segment: { type: "string", enum: ["smb", "mid_market", "enterprise", "strategic"], description: "Go-to-market tier this account is served at. A segmentation *decision* (how the field org treats the account), distinct from `employee_count` (a raw fact) and aligned with but not identical to the ideal customer profile's `company_size` buckets. `strategic` is the tier that escalates to a dedicated account-plan graph (Tier 3 client model)." },
|
|
10160
|
+
annual_contract_value: { type: "number", description: "Annual contract value in the account's billing currency. The single most common enterprise account-tiering input; a snapshot that changes on expansion or renewal.", modifier: "snapshot" },
|
|
10161
|
+
region: { type: "string", description: 'Geographic region the account is managed in (e.g. "EMEA", "NA-West"). Free-form: territory taxonomies vary by org and are modelled structurally via the `territory` entity when they need to be queryable.' }
|
|
10059
10162
|
},
|
|
10060
10163
|
// AcquisitionChannelProperties: AcquisitionChannel entity.
|
|
10061
10164
|
acquisition_channel: {
|
|
@@ -10644,7 +10747,8 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10644
10747
|
// ContactProperties: Contact.
|
|
10645
10748
|
contact: {
|
|
10646
10749
|
contact_role: { type: "string", description: "Job title or role within the account" },
|
|
10647
|
-
is_decision_maker: { type: "boolean", description: "Whether this person has purchasing authority" }
|
|
10750
|
+
is_decision_maker: { type: "boolean", description: "Whether this person has purchasing authority" },
|
|
10751
|
+
buying_role: { type: "string", enum: ["champion", "economic_buyer", "technical_evaluator", "end_user", "detractor", "influencer", "procurement", "legal", "security"], description: "Role this contact plays in the buying committee (the decision-making unit). The substrate of enterprise multi-threading and of qualification frameworks (MEDDICC/SPICED): a deal with no `champion` and no `economic_buyer` mapped is single-threaded and at risk. `is_decision_maker` becomes largely derivable (`buying_role = economic_buyer`) but is kept for back-compat. @example 'economic_buyer'" }
|
|
10648
10752
|
},
|
|
10649
10753
|
// ContentCalendarProperties: Content calendar.
|
|
10650
10754
|
content_calendar: {
|
|
@@ -10840,7 +10944,24 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10840
10944
|
deal: {
|
|
10841
10945
|
deal_value: { type: "number", description: "Monetary value of the deal" },
|
|
10842
10946
|
close_date: { type: "string", description: "Expected close date (ISO format)" },
|
|
10843
|
-
probability: { type: "number", description: "Likelihood of closing (0-100%)" }
|
|
10947
|
+
probability: { type: "number", description: "Likelihood of closing (0-100%)" },
|
|
10948
|
+
deal_outcome: { type: "string", enum: ["won", "lost", "no_decision"], description: "Terminal result of the deal. An Event-axis outcome (the verdict on a one-time event), NOT a lifecycle phase, so it is `deal_outcome` and not `deal_status` per the status-convention Rule 3. Lifecycle (open/won/lost as phases) belongs on the base `status` slot; this records the win/loss verdict a closed deal carries and gives `deal_lost_to_competitor` / win-loss study derivations their anchor. @example 'won'" },
|
|
10949
|
+
deal_type: { type: "string", enum: ["new_business", "expansion", "renewal"], description: "Motion this deal belongs to. Mirrors `PipelineSales.pipeline_type` at the deal grain; `renewal` is the value `subscription_renews_via_deal` points at. @example 'expansion'" },
|
|
10950
|
+
next_step: { type: "string", description: "The single most-used CRM field: the next concrete action to move the deal. Free text on purpose (a coordination note, not a structured task). @example 'Send security questionnaire to procurement'" },
|
|
10951
|
+
next_step_date: { type: "string", description: "When the `next_step` is due (ISO format)." },
|
|
10952
|
+
qualification_framework: { type: "string", enum: ["meddicc", "bant", "spiced", "custom"], description: "Qualification framework this deal is scored against. Names the rubric so the `qualification_score` is interpretable; per-pillar booleans (MEDDICC's Metrics / Economic buyer / Decision criteria / \u2026) are deferred until `custom` recurrence proves the demand. @example 'meddicc'" },
|
|
10953
|
+
qualification_score: {
|
|
10954
|
+
type: "assessment",
|
|
10955
|
+
scale_id: "confidence_5",
|
|
10956
|
+
description: "How well-qualified the deal is, on the canonical `confidence_5` scale (UPGAssessment: numeric value plus a high/medium/low label). Coarse by design; the granular per-pillar breakdown is deferred (see `qualification_framework`).",
|
|
10957
|
+
properties: {
|
|
10958
|
+
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10959
|
+
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10960
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10961
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10962
|
+
},
|
|
10963
|
+
required: ["value", "label"]
|
|
10964
|
+
}
|
|
10844
10965
|
},
|
|
10845
10966
|
// DecisionProperties: Decision record. Strategic, product, engineering, or design.
|
|
10846
10967
|
decision: {
|
|
@@ -11873,7 +11994,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11873
11994
|
},
|
|
11874
11995
|
// MessagingProperties: Messaging entity. Each instance is a channel/stage variant.
|
|
11875
11996
|
messaging: {
|
|
11876
|
-
channel: { type: "string", enum: ["landing_page", "email", "social", "ad", "pitch", "press", "in_product", "other"], description: "Channel this messaging variant is crafted for" },
|
|
11997
|
+
channel: { type: "string", enum: ["landing_page", "email", "social", "ad", "pitch", "press", "in_product", "enablement", "other"], description: "Channel this messaging variant is crafted for. `enablement` is the internal field-ops channel (SE/PMM/SA enablement one-pagers, battlecards' narrative), distinct from `pitch` (external, customer-facing)." },
|
|
11877
11998
|
funnel_stage: { type: "string", enum: ["awareness", "consideration", "conversion", "retention"], description: "Marketing funnel stage this variant targets" },
|
|
11878
11999
|
headline: { type: "string", description: "Primary headline or hook" },
|
|
11879
12000
|
body: { type: "string", description: "Full message body copy" },
|
|
@@ -23283,6 +23404,12 @@ var GTM_GUIDE = {
|
|
|
23283
23404
|
description: "Strategy defines positioning, positioning spawns messaging variants, messaging addresses objections with rebuttals backed by proof points",
|
|
23284
23405
|
entity_types: ["positioning", "messaging", "objection", "rebuttal", "proof_point"],
|
|
23285
23406
|
edge_chain: ["gtm_strategy_positions_via_positioning", "positioning_communicated_via_messaging", "positioning_challenged_by_objection", "objection_countered_by_rebuttal", "rebuttal_evidenced_by_proof_point"]
|
|
23407
|
+
},
|
|
23408
|
+
{
|
|
23409
|
+
name: "Audience Projection Lattice",
|
|
23410
|
+
description: "One feature approaching launch needs many faces: what the internal field org (SE/PMM/SA) needs to know differs from what an enterprise champion needs at beta versus GA. Model the atoms, not the rendered pages. A feature is communicated_via messaging variants; each variant targets a persona (an internal field-ops persona or a customer persona) and is used_in a staged launch (beta, then GA); the launch is coordinated_via a project (the readiness checklist: demo env, SE training, by when). The projection itself is a query over these atoms, rendered by the product, never a stored copy that drifts.",
|
|
23411
|
+
entity_types: ["feature", "messaging", "persona", "launch", "project"],
|
|
23412
|
+
edge_chain: ["feature_communicated_via_messaging", "messaging_targets_persona", "launch_ships_feature", "launch_coordinated_via_project"]
|
|
23286
23413
|
}
|
|
23287
23414
|
],
|
|
23288
23415
|
required_bridges: [
|
|
@@ -23328,17 +23455,33 @@ var SALES_GUIDE = {
|
|
|
23328
23455
|
description: "Pipelines qualify leads, leads become accounts, accounts negotiate deals that progress through pipeline stages and convert to subscriptions",
|
|
23329
23456
|
entity_types: ["pipeline_sales", "lead", "account", "deal", "pipeline_stage", "subscription"],
|
|
23330
23457
|
edge_chain: ["pipeline_sales_qualifies_lead", "lead_becomes_account", "account_negotiates_deal", "deal_at_pipeline_stage", "pipeline_sales_converts_to_subscription"]
|
|
23458
|
+
},
|
|
23459
|
+
{
|
|
23460
|
+
name: "Enterprise Buying Committee",
|
|
23461
|
+
description: "An enterprise deal is a months-long coordination effort, not a forecast row. Attach the decision-making unit directly to the deal (each contact carries a buying_role: champion, economic buyer, technical evaluator, procurement, detractor), then wire the gauntlet the deal must clear: objections it faces, the security review that gates it, and the contract it closes via. A deal with no champion and no economic buyer mapped is single-threaded and at risk.",
|
|
23462
|
+
entity_types: ["deal", "contact", "objection", "security_review", "contract"],
|
|
23463
|
+
edge_chain: ["account_negotiates_deal", "deal_involves_contact", "deal_challenged_by_objection", "deal_gated_by_security_review", "deal_closed_via_contract"]
|
|
23464
|
+
},
|
|
23465
|
+
{
|
|
23466
|
+
name: "Win/Loss Learning Loop",
|
|
23467
|
+
description: "Close the pre-sale learning loop the way the post-sale one already closes (support_ticket reveals need). A deal is armed with a competitive battlecard; when it is lost to a competitor, a win/loss research_study analyses it. This gives competitive_battle_card.win_rate a derivation path (nothing could compute it before) and turns lost deals into structured competitive intelligence rather than a note in a closed record.",
|
|
23468
|
+
entity_types: ["deal", "competitive_battle_card", "competitor", "research_study"],
|
|
23469
|
+
edge_chain: ["deal_armed_with_competitive_battle_card", "deal_lost_to_competitor", "research_study_analyzes_deal"]
|
|
23331
23470
|
}
|
|
23332
23471
|
],
|
|
23333
23472
|
required_bridges: [
|
|
23334
23473
|
{ edge_type: "lead_sourced_from_acquisition_channel", target_domain: "growth", when: "Track where leads come from for attribution" },
|
|
23335
23474
|
{ edge_type: "subscription_subscribes_to_pricing_tier", target_domain: "pricing", when: "Subscriptions should link to the tier purchased" },
|
|
23336
|
-
{ edge_type: "account_partners_via_partnership", target_domain: "business_model", when: "Partner accounts should link to the partnership entity" }
|
|
23475
|
+
{ edge_type: "account_partners_via_partnership", target_domain: "business_model", when: "Partner accounts should link to the partnership entity" },
|
|
23476
|
+
{ edge_type: "deal_blocked_by_feature", target_domain: "product_spec", when: 'When a roadmap gap holds up pipeline, link the deal to the blocking feature so "which features unblock how much revenue" is queryable' },
|
|
23477
|
+
{ edge_type: "account_implements_via_project", target_domain: "program_mgmt", when: "Post-sale onboarding/implementation reuses the program-management machinery (project/milestone/deliverable), scoped to the account" }
|
|
23337
23478
|
],
|
|
23338
23479
|
anti_patterns: [
|
|
23339
23480
|
{ description: "Deals without pipeline stages: every deal needs a current position in the pipeline" },
|
|
23340
23481
|
{ description: "Leads without source attribution. Attribution drives channel optimisation." },
|
|
23341
|
-
{ description: "Forecasts without probability: weight deals by likelihood to close" }
|
|
23482
|
+
{ description: "Forecasts without probability: weight deals by likelihood to close" },
|
|
23483
|
+
{ name: "Single-threaded enterprise deal", description: "An enterprise deal with no contacts attached (deal_involves_contact) or no champion/economic_buyer among their buying_role values is single-threaded: the whole relationship rests on one unmapped person. Attach the buying committee and map at least the champion and economic buyer.", affected_entity: "deal", remediation: "Create deal_involves_contact edges to the committee and set each contact's buying_role." },
|
|
23484
|
+
{ name: "Won/lost recorded only as a phase", description: "The deal outcome (won/lost/no_decision) is an Event-axis fact and belongs on deal_outcome, not conflated with the lifecycle status. A lost deal with no deal_lost_to_competitor edge also strands the competitive signal that competitive_battle_card.win_rate depends on.", affected_entity: "deal", remediation: "Set deal_outcome, and on a loss create deal_lost_to_competitor plus a win/loss research_study via research_study_analyzes_deal." }
|
|
23342
23485
|
]
|
|
23343
23486
|
};
|
|
23344
23487
|
var MARKETING_GUIDE = {
|
|
@@ -29727,7 +29870,7 @@ function isCanonical(text) {
|
|
|
29727
29870
|
}
|
|
29728
29871
|
|
|
29729
29872
|
// src/index.ts
|
|
29730
|
-
var UPG_VERSION = "0.
|
|
29873
|
+
var UPG_VERSION = "0.24.0";
|
|
29731
29874
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
29732
29875
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
29733
29876
|
var UPG_TYPES = getTypes();
|