@unified-product-graph/core 0.23.1 → 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 +159 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +201 -3
- package/dist/index.d.ts +201 -3
- package/dist/index.js +159 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1438,8 +1438,14 @@ var UPG_EDGE_CATALOG = {
|
|
|
1438
1438
|
// feature-level edges (same verbs/classification), so `pickCanonicalEdge` /
|
|
1439
1439
|
// `resolveContainmentEdge('epic', 'task'|'bug')` and the adapter import path
|
|
1440
1440
|
// resolve them with no further wiring.
|
|
1441
|
-
|
|
1442
|
-
|
|
1441
|
+
// cross_product_eligible (feedback 9a10be30): an epic is a cross-team planning
|
|
1442
|
+
// unit — its implementing task or affecting bug may live in a different
|
|
1443
|
+
// product's engineering substrate (e.g. a consumer product's epic whose
|
|
1444
|
+
// backend work is tracked in a separate platform/infra graph). Dual-registered
|
|
1445
|
+
// like the objective↔dependency edges: valid within a product AND across
|
|
1446
|
+
// products (endpoints referenced by qualified id).
|
|
1447
|
+
epic_decomposes_into_task: { forward_verb: "decomposes_into", reverse_verb: "implements", classification: "hierarchy", source_type: "epic", target_type: "task", cross_product_eligible: true },
|
|
1448
|
+
epic_affected_by_bug: { forward_verb: "affected_by", reverse_verb: "affects", classification: "hierarchy", source_type: "epic", target_type: "bug", cross_product_eligible: true },
|
|
1443
1449
|
task_has_subtask: { forward_verb: "has_subtask", reverse_verb: "is_subtask_of", classification: "hierarchy", source_type: "task", target_type: "task" },
|
|
1444
1450
|
// ── Planning cadence (0.20.0) ────────────────────────────────────────────────
|
|
1445
1451
|
// The cadence axis. E1 self-nests the interval (a program-increment contains
|
|
@@ -3247,7 +3253,105 @@ var UPG_EDGE_CATALOG = {
|
|
|
3247
3253
|
// product's feature or capability, authored in a different graph within the
|
|
3248
3254
|
// portfolio, fits the 0.17.3 locked predicate.
|
|
3249
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 },
|
|
3250
|
-
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" }
|
|
3251
3355
|
};
|
|
3252
3356
|
var UPG_CROSS_ELIGIBLE_CATALOG_EDGE_TYPES = Object.keys(UPG_EDGE_CATALOG).filter(
|
|
3253
3357
|
(k) => UPG_EDGE_CATALOG[k].cross_product_eligible === true
|
|
@@ -6555,6 +6659,8 @@ var PROPERTY_SCALE_MAP = {
|
|
|
6555
6659
|
// market/risk (UPG-579 Option B)
|
|
6556
6660
|
probability: "confidence_5",
|
|
6557
6661
|
// sales/forecast (UPG-579 Option B)
|
|
6662
|
+
qualification_score: "confidence_5",
|
|
6663
|
+
// sales/deal — how confident the qualification is (0.24.0)
|
|
6558
6664
|
// ── Effort ───────────────────────────────────────────────────────────────
|
|
6559
6665
|
effort: "effort_5",
|
|
6560
6666
|
// discovery
|
|
@@ -10049,7 +10155,10 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10049
10155
|
account: {
|
|
10050
10156
|
account_type: { type: "string", enum: ["prospect", "customer", "partner", "churned"], description: "Relationship status of this account" },
|
|
10051
10157
|
industry: { type: "string", description: "Industry vertical the account operates in" },
|
|
10052
|
-
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.' }
|
|
10053
10162
|
},
|
|
10054
10163
|
// AcquisitionChannelProperties: AcquisitionChannel entity.
|
|
10055
10164
|
acquisition_channel: {
|
|
@@ -10638,7 +10747,8 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10638
10747
|
// ContactProperties: Contact.
|
|
10639
10748
|
contact: {
|
|
10640
10749
|
contact_role: { type: "string", description: "Job title or role within the account" },
|
|
10641
|
-
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'" }
|
|
10642
10752
|
},
|
|
10643
10753
|
// ContentCalendarProperties: Content calendar.
|
|
10644
10754
|
content_calendar: {
|
|
@@ -10834,7 +10944,24 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10834
10944
|
deal: {
|
|
10835
10945
|
deal_value: { type: "number", description: "Monetary value of the deal" },
|
|
10836
10946
|
close_date: { type: "string", description: "Expected close date (ISO format)" },
|
|
10837
|
-
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
|
+
}
|
|
10838
10965
|
},
|
|
10839
10966
|
// DecisionProperties: Decision record. Strategic, product, engineering, or design.
|
|
10840
10967
|
decision: {
|
|
@@ -11867,7 +11994,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11867
11994
|
},
|
|
11868
11995
|
// MessagingProperties: Messaging entity. Each instance is a channel/stage variant.
|
|
11869
11996
|
messaging: {
|
|
11870
|
-
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)." },
|
|
11871
11998
|
funnel_stage: { type: "string", enum: ["awareness", "consideration", "conversion", "retention"], description: "Marketing funnel stage this variant targets" },
|
|
11872
11999
|
headline: { type: "string", description: "Primary headline or hook" },
|
|
11873
12000
|
body: { type: "string", description: "Full message body copy" },
|
|
@@ -23277,6 +23404,12 @@ var GTM_GUIDE = {
|
|
|
23277
23404
|
description: "Strategy defines positioning, positioning spawns messaging variants, messaging addresses objections with rebuttals backed by proof points",
|
|
23278
23405
|
entity_types: ["positioning", "messaging", "objection", "rebuttal", "proof_point"],
|
|
23279
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"]
|
|
23280
23413
|
}
|
|
23281
23414
|
],
|
|
23282
23415
|
required_bridges: [
|
|
@@ -23322,17 +23455,33 @@ var SALES_GUIDE = {
|
|
|
23322
23455
|
description: "Pipelines qualify leads, leads become accounts, accounts negotiate deals that progress through pipeline stages and convert to subscriptions",
|
|
23323
23456
|
entity_types: ["pipeline_sales", "lead", "account", "deal", "pipeline_stage", "subscription"],
|
|
23324
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"]
|
|
23325
23470
|
}
|
|
23326
23471
|
],
|
|
23327
23472
|
required_bridges: [
|
|
23328
23473
|
{ edge_type: "lead_sourced_from_acquisition_channel", target_domain: "growth", when: "Track where leads come from for attribution" },
|
|
23329
23474
|
{ edge_type: "subscription_subscribes_to_pricing_tier", target_domain: "pricing", when: "Subscriptions should link to the tier purchased" },
|
|
23330
|
-
{ 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" }
|
|
23331
23478
|
],
|
|
23332
23479
|
anti_patterns: [
|
|
23333
23480
|
{ description: "Deals without pipeline stages: every deal needs a current position in the pipeline" },
|
|
23334
23481
|
{ description: "Leads without source attribution. Attribution drives channel optimisation." },
|
|
23335
|
-
{ 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." }
|
|
23336
23485
|
]
|
|
23337
23486
|
};
|
|
23338
23487
|
var MARKETING_GUIDE = {
|
|
@@ -29721,7 +29870,7 @@ function isCanonical(text) {
|
|
|
29721
29870
|
}
|
|
29722
29871
|
|
|
29723
29872
|
// src/index.ts
|
|
29724
|
-
var UPG_VERSION = "0.
|
|
29873
|
+
var UPG_VERSION = "0.24.0";
|
|
29725
29874
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
29726
29875
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
29727
29876
|
var UPG_TYPES = getTypes();
|