@unified-product-graph/core 0.7.1 → 0.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -13,20 +13,20 @@
13
13
  type UPGEntityType = 'product' | 'outcome' | 'objective' | 'key_result' | 'metric' | 'metric_quality_assessment' | 'vision' | 'mission' | 'strategic_theme' | 'initiative' | 'capability' | 'value_stream' | 'strategic_pillar' | 'assumption' | 'decision' | 'constraint' | 'persona' | 'job' | 'need' | 'desired_outcome' | 'job_step' | 'switching_cost' | 'opportunity' | 'solution' | 'feasibility_study' | 'design_sprint' | 'hypothesis' | 'hypothesis_evidence' | 'experiment' | 'experiment_plan' | 'experiment_run' | 'learning' | 'test_plan' | 'evidence' | 'research_plan' | 'competitor' | 'competitor_feature' | 'market_trend' | 'market_segment' | 'competitive_analysis' | 'classification_axis' | 'classification_value' | 'research_study' | 'insight' | 'participant' | 'observation' | 'quote' | 'affinity_cluster' | 'research_question' | 'interview_guide' | 'survey_response' | 'user_journey' | 'journey_step' | 'journey_phase' | 'journey_action' | 'design_question' | 'design_concept' | 'prototype' | 'wireframe' | 'user_flow' | 'screen' | 'screen_state' | 'annotation' | 'interaction_spec' | 'design_component' | 'design_token' | 'design_system' | 'design_pattern' | 'design_guideline' | 'brand_identity' | 'brand_colour' | 'brand_typography' | 'brand_voice' | 'brand_logo' | 'brand_imagery' | 'feature_area' | 'feature' | 'epic' | 'user_story' | 'story_statement' | 'story_task' | 'acceptance_criterion' | 'release' | 'task' | 'bug' | 'roadmap' | 'roadmap_item' | 'theme' | 'changelog' | 'bounded_context' | 'service' | 'domain_event' | 'api_contract' | 'technical_debt_item' | 'feature_flag' | 'deployment' | 'aggregate' | 'domain_entity' | 'value_object' | 'command' | 'read_model' | 'api_endpoint' | 'database_schema' | 'queue_topic' | 'build_artifact' | 'code_repository' | 'library_dependency' | 'integration_pattern' | 'external_api' | 'data_flow' | 'investigation' | 'root_cause' | 'symptom' | 'fix' | 'funnel' | 'funnel_step' | 'acquisition_channel' | 'growth_campaign' | 'cohort' | 'behavioral_segment' | 'growth_loop' | 'variant' | 'attribution_model' | 'business_model' | 'value_proposition' | 'revenue_stream' | 'pricing_tier' | 'cost_structure' | 'unit_economics' | 'partnership' | 'key_resource' | 'key_activity' | 'customer_relationship' | 'distribution_channel' | 'gtm_strategy' | 'ideal_customer_profile' | 'positioning' | 'messaging' | 'launch' | 'content_strategy' | 'sales_motion' | 'competitive_battle_card' | 'demand_gen_program' | 'territory' | 'objection' | 'rebuttal' | 'proof_point' | 'team' | 'role' | 'stakeholder' | 'person' | 'team_okr' | 'retrospective' | 'dependency' | 'department' | 'skill' | 'ceremony' | 'capacity_plan' | 'data_source' | 'event_schema' | 'dashboard' | 'data_model' | 'data_quality_rule' | 'data_product' | 'data_pipeline' | 'data_lineage' | 'glossary_term' | 'data_domain' | 'report' | 'content_piece' | 'knowledge_base_article' | 'brand_asset' | 'prompt_template' | 'content_calendar' | 'content_theme' | 'documentation_template' | 'document' | 'legal_entity' | 'ip_asset' | 'contract' | 'contract_clause' | 'privacy_policy' | 'compliance_requirement' | 'risk' | 'data_contract' | 'audit_log_policy' | 'compliance_framework' | 'security_audit' | 'service_level_indicator' | 'service_level_objective' | 'error_budget' | 'incident' | 'postmortem' | 'runbook' | 'monitor' | 'alert_rule' | 'ci_pipeline' | 'release_strategy' | 'on_call_rotation' | 'infrastructure_component' | 'threat_model' | 'threat' | 'vulnerability' | 'security_control' | 'security_policy' | 'penetration_test' | 'security_review' | 'data_classification' | 'access_policy' | 'a11y_standard' | 'a11y_guideline' | 'a11y_audit' | 'a11y_issue' | 'a11y_annotation' | 'test_suite' | 'test_case' | 'qa_session' | 'regression_test' | 'test_coverage_report' | 'test_environment' | 'test_result' | 'feedback_program' | 'feature_request' | 'feedback_vote' | 'nps_campaign' | 'user_advisory_board' | 'beta_program' | 'feedback_theme' | 'pricing_strategy' | 'discount_strategy' | 'trial_config' | 'paywall' | 'ai_model' | 'prompt_version' | 'eval_benchmark' | 'eval_run' | 'ai_cost_tracker' | 'hallucination_report' | 'ai_guardrail' | 'model_comparison' | 'ai_experiment' | 'ai_dataset' | 'ai_trace' | 'workflow_template' | 'workflow_run' | 'agent_definition' | 'agent_session' | 'review_gate' | 'approval_record' | 'agent_skill' | 'agent_hook' | 'workflow_artifact' | 'agent_task' | 'organization' | 'portfolio' | 'product_area' | 'workspace' | 'account' | 'contact' | 'lead' | 'deal' | 'pipeline_sales' | 'pipeline_stage' | 'quote_document' | 'subscription' | 'invoice' | 'forecast' | 'program' | 'project' | 'milestone' | 'risk_register' | 'change_request' | 'deliverable' | 'resource_allocation' | 'status_report' | 'marketing_strategy' | 'marketing_channel' | 'marketing_campaign_plan' | 'email_sequence' | 'social_post' | 'seo_keyword' | 'ad_creative' | 'press_release' | 'event' | 'community_initiative' | 'support_ticket' | 'customer_feedback' | 'churn_reason' | 'customer_health_score' | 'playbook' | 'service_level_agreement' | 'customer_journey_stage' | 'touchpoint' | 'success_milestone' | 'service_blueprint' | 'locale' | 'translation_key' | 'translation_bundle' | 'locale_config' | 'cultural_adaptation' | 'regional_pricing' | 'education_program' | 'tutorial' | 'walkthrough' | 'webinar' | 'certification' | 'help_video' | 'learning_path' | 'partner_program' | 'partner_tier' | 'api_ecosystem' | 'marketplace_listing' | 'developer_portal' | 'integration_partner' | 'partner_revenue_share';
14
14
  /**
15
15
  * No entity types are currently deprecated; this union is `never`. The
16
- * deprecated-name bridge — which previously widened this union to early
17
- * aliases (`jtbd`, `pain_point`, `kpi`, …) — is closed, so runtime callers no
16
+ * deprecated-name bridge, which previously widened this union to early
17
+ * aliases (`jtbd`, `pain_point`, `kpi`, …), is closed, so runtime callers no
18
18
  * longer need an alias-aware type.
19
19
  *
20
20
  * Narrowed to `never` so any code that still references this union for
21
21
  * widening cascades a type error and gets cleaned up. Migration runtime
22
22
  * (`migrateNode`, `UPG_MIGRATIONS`, `getReplacementType`) keeps its own
23
- * internal list of historical names — it does NOT depend on this union.
23
+ * internal list of historical names; it does NOT depend on this union.
24
24
  *
25
- * @see ../grammar/migrations.ts — runtime migration helpers
26
- * @see scripts/check-no-deprecated-symbols.ts — string-literal guard
25
+ * @see ../grammar/migrations.ts for runtime migration helpers
26
+ * @see scripts/check-no-deprecated-symbols.ts for the string-literal guard
27
27
  */
28
28
  type DeprecatedUPGEntityType = never;
29
- /** All entity types — `DeprecatedUPGEntityType` is `never`, so this equals `UPGEntityType`. */
29
+ /** All entity types. `DeprecatedUPGEntityType` is `never`, so this equals `UPGEntityType`. */
30
30
  type AnyUPGEntityType = UPGEntityType | DeprecatedUPGEntityType;
31
31
 
32
32
  /**
@@ -50,7 +50,7 @@ type UPGMappingConfidence = 'high' | 'medium' | 'low' | 'manual';
50
50
  * Everything else is optional to keep the format lightweight.
51
51
  *
52
52
  * @example
53
- * // A minimal persona node — only required fields populated.
53
+ * // A minimal persona node, only required fields populated.
54
54
  * const persona: UPGBaseNode = {
55
55
  * id: 'n_persona_1',
56
56
  * type: 'persona',
@@ -79,7 +79,7 @@ type UPGMappingConfidence = 'high' | 'medium' | 'low' | 'manual';
79
79
  interface UPGBaseNode {
80
80
  /** Unique identifier within the graph */
81
81
  id: string;
82
- /** The UPG entity type — must be a value from UPGEntityType */
82
+ /** The UPG entity type (must be a value from UPGEntityType) */
83
83
  type: UPGEntityType;
84
84
  /** Human-readable title */
85
85
  title: string;
@@ -102,7 +102,7 @@ interface UPGBaseNode {
102
102
  description?: string;
103
103
  /** Freeform tags for filtering and grouping */
104
104
  tags?: string[];
105
- /** Current lifecycle phase — must be a phase ID from getLifecycleForType().
105
+ /** Current lifecycle phase (must be a phase ID from getLifecycleForType()).
106
106
  * E.g., for hypothesis: 'untested' | 'testing' | 'resolved'.
107
107
  * Entity types without a lifecycle definition should omit this field.
108
108
  * Validated at runtime against UPG_ALL_PHASES_SET. */
@@ -115,7 +115,7 @@ interface UPGBaseNode {
115
115
  mapping_confidence?: UPGMappingConfidence;
116
116
  /** External tool that holds the canonical artifact (e.g. "figma", "linear", "notion") */
117
117
  external_tool?: string;
118
- /** URI to the canonical artifact — https:// for cloud tools, file:// or relative path for local files */
118
+ /** URI to the canonical artifact: https:// for cloud tools, file:// or relative path for local files */
119
119
  external_ref?: string;
120
120
  /** Identifier in the external tool's system (for sync / round-trip) */
121
121
  external_id?: string;
@@ -565,6 +565,13 @@ declare const UPG_EDGE_CATALOG: {
565
565
  source_type: string;
566
566
  target_type: string;
567
567
  };
568
+ competitor_competes_in_territory: {
569
+ forward_verb: string;
570
+ reverse_verb: string;
571
+ classification: "cross-domain";
572
+ source_type: string;
573
+ target_type: string;
574
+ };
568
575
  competitor_yields_learning: {
569
576
  forward_verb: string;
570
577
  reverse_verb: string;
@@ -1776,6 +1783,13 @@ declare const UPG_EDGE_CATALOG: {
1776
1783
  source_type: string;
1777
1784
  target_type: string;
1778
1785
  };
1786
+ deployment_triggers_incident: {
1787
+ forward_verb: string;
1788
+ reverse_verb: string;
1789
+ classification: "causal";
1790
+ source_type: string;
1791
+ target_type: string;
1792
+ };
1779
1793
  service_serves_api_endpoint: {
1780
1794
  forward_verb: string;
1781
1795
  reverse_verb: string;
@@ -2238,6 +2252,13 @@ declare const UPG_EDGE_CATALOG: {
2238
2252
  source_type: string;
2239
2253
  target_type: string;
2240
2254
  };
2255
+ monitor_measures_service_level_indicator: {
2256
+ forward_verb: string;
2257
+ reverse_verb: string;
2258
+ classification: "semantic";
2259
+ source_type: string;
2260
+ target_type: string;
2261
+ };
2241
2262
  ci_pipeline_deploys_service: {
2242
2263
  forward_verb: string;
2243
2264
  reverse_verb: string;
@@ -2931,6 +2952,13 @@ declare const UPG_EDGE_CATALOG: {
2931
2952
  source_type: string;
2932
2953
  target_type: string;
2933
2954
  };
2955
+ attribution_model_credits_acquisition_channel: {
2956
+ forward_verb: string;
2957
+ reverse_verb: string;
2958
+ classification: "semantic";
2959
+ source_type: string;
2960
+ target_type: string;
2961
+ };
2934
2962
  product_guided_by_metric: {
2935
2963
  forward_verb: string;
2936
2964
  reverse_verb: string;
@@ -3050,6 +3078,13 @@ declare const UPG_EDGE_CATALOG: {
3050
3078
  source_type: string;
3051
3079
  target_type: string;
3052
3080
  };
3081
+ growth_loop_fuels_acquisition_channel: {
3082
+ forward_verb: string;
3083
+ reverse_verb: string;
3084
+ classification: "semantic";
3085
+ source_type: string;
3086
+ target_type: string;
3087
+ };
3053
3088
  variant_tests_hypothesis: {
3054
3089
  forward_verb: string;
3055
3090
  reverse_verb: string;
@@ -3855,6 +3890,13 @@ declare const UPG_EDGE_CATALOG: {
3855
3890
  source_type: string;
3856
3891
  target_type: string;
3857
3892
  };
3893
+ forecast_projects_metric: {
3894
+ forward_verb: string;
3895
+ reverse_verb: string;
3896
+ classification: "cross-domain";
3897
+ source_type: string;
3898
+ target_type: string;
3899
+ };
3858
3900
  product_markets_through_marketing_strategy: {
3859
3901
  forward_verb: string;
3860
3902
  reverse_verb: string;
@@ -4380,6 +4422,13 @@ declare const UPG_EDGE_CATALOG: {
4380
4422
  source_type: string;
4381
4423
  target_type: string;
4382
4424
  };
4425
+ content_theme_organizes_content_piece: {
4426
+ forward_verb: string;
4427
+ reverse_verb: string;
4428
+ classification: "semantic";
4429
+ source_type: string;
4430
+ target_type: string;
4431
+ };
4383
4432
  document_describes_feature: {
4384
4433
  forward_verb: string;
4385
4434
  reverse_verb: string;
@@ -6156,6 +6205,13 @@ declare const UPG_EDGE_CATALOG: {
6156
6205
  source_type: string;
6157
6206
  target_type: string;
6158
6207
  };
6208
+ participant_represents_persona: {
6209
+ forward_verb: string;
6210
+ reverse_verb: string;
6211
+ classification: "cross-domain";
6212
+ source_type: string;
6213
+ target_type: string;
6214
+ };
6159
6215
  research_question_addressed_by_insight: {
6160
6216
  forward_verb: string;
6161
6217
  reverse_verb: string;
@@ -6740,23 +6796,23 @@ type _UPGEdgeTypeLocal = keyof typeof UPG_EDGE_CATALOG;
6740
6796
  *
6741
6797
  * Three semantic families are sanctioned:
6742
6798
  *
6743
- * 1. **Universal semantic verbs** — any node can inform / constrain / inspire
6799
+ * 1. **Universal semantic verbs**: any node can inform / constrain / inspire
6744
6800
  * any other node. The meaning is deliberately abstract; consumers render
6745
6801
  * them as plain relational signals.
6746
- * 2. **Decision-to-anything** — a decision can influence, be constrained by,
6802
+ * 2. **Decision-to-anything**: a decision can influence, be constrained by,
6747
6803
  * or produce any kind of node. Decisions cut across domains; binding the
6748
6804
  * target would force a combinatorial explosion.
6749
- * 3. **Universal ownership** — any node can be owned by a team, role,
6805
+ * 3. **Universal ownership**: any node can be owned by a team, role,
6750
6806
  * stakeholder, department, or person. Ownership is not per-entity-type.
6751
6807
  *
6752
6808
  * Adding a new polymorphic edge requires extending this array AND the
6753
- * spec-integrity regression test — that forces a conscious decision and
6809
+ * spec-integrity regression test, which forces a conscious decision and
6754
6810
  * keeps consumers (MCP, Entopo, audit tools) able to enumerate the full set.
6755
6811
  */
6756
6812
  declare const UPG_POLYMORPHIC_EDGE_KEYS: readonly _UPGEdgeTypeLocal[];
6757
6813
  /**
6758
6814
  * True if the edge uses the `'node'` wildcard at either endpoint. Derived
6759
- * dynamically from `source_type`/`target_type` — not from the allow-list —
6815
+ * dynamically from `source_type`/`target_type`, not from the allow-list,
6760
6816
  * so an accidentally-added polymorphic edge still returns true and surfaces
6761
6817
  * via the invariant test rather than silently passing.
6762
6818
  *
@@ -6829,7 +6885,7 @@ interface UPGSource {
6829
6885
  * const product: UPGProduct = {
6830
6886
  * id: 'entopo',
6831
6887
  * title: 'Entopo',
6832
- * description: 'The product creation tool — canvas + AI + graph, built on UPG.',
6888
+ * description: 'The product creation tool: canvas + AI + graph, built on UPG.',
6833
6889
  * stage: 'beta',
6834
6890
  * }
6835
6891
  */
@@ -7054,7 +7110,7 @@ interface UPGPortfolioDocument {
7054
7110
  }
7055
7111
 
7056
7112
  /**
7057
- * Legacy product-stage aliases — UPG-509 Part 2.
7113
+ * Legacy product-stage aliases (UPG-509 Part 2).
7058
7114
  *
7059
7115
  * Existing graphs (`entopo.upg`, `sanity.upg`, `maximum-minimum.upg`,
7060
7116
  * `notion-saturated.upg`, etc.) carry `product.stage` values that pre-date
@@ -7071,7 +7127,7 @@ interface UPGPortfolioDocument {
7071
7127
  * already canonical and not a known legacy alias).
7072
7128
  *
7073
7129
  * Mapping rationale:
7074
- * - `idea → concept` — pre-canonical alias from early v0.1 product nodes;
7130
+ * - `idea → concept`: pre-canonical alias from early v0.1 product nodes;
7075
7131
  * matches the v0.2.13 `properties.stage` migration `value_map` and the
7076
7132
  * `UPG_PRODUCT_STAGE_COERCION_MAP` documented mapping.
7077
7133
  *
@@ -7096,7 +7152,7 @@ declare const LEGACY_PRODUCT_STAGES: Readonly<Record<string, UPGProductStage>>;
7096
7152
  *
7097
7153
  * - Returns the canonical stage when `stage` is a known legacy alias.
7098
7154
  * - Returns `stage` verbatim when it is not a known legacy alias (the input
7099
- * may itself already be canonical, or genuinely unknown — the strict
7155
+ * may itself already be canonical, or genuinely unknown. The strict
7100
7156
  * write path is responsible for rejecting genuinely-unknown values).
7101
7157
  * - Returns `undefined` for `undefined` / `null` inputs.
7102
7158
  *
@@ -7107,7 +7163,7 @@ declare const LEGACY_PRODUCT_STAGES: Readonly<Record<string, UPGProductStage>>;
7107
7163
  * migrateProductStage('IDEA') // → 'concept'
7108
7164
  * migrateProductStage('concept') // → 'concept' (already canonical, passthrough)
7109
7165
  * migrateProductStage('launch') // → 'launch' (already canonical, passthrough)
7110
- * migrateProductStage('xyz') // → 'xyz' (unknown, passthrough — callers decide)
7166
+ * migrateProductStage('xyz') // → 'xyz' (unknown, passthrough; callers decide)
7111
7167
  * migrateProductStage(undefined) // → undefined
7112
7168
  */
7113
7169
  declare function migrateProductStage<T extends string | undefined | null>(stage: T): T extends string ? UPGProductStage | string : undefined;
@@ -7158,7 +7214,7 @@ type UPGEntityTypeMaturity = 'draft' | 'proposed' | 'stable' | 'deprecated' | 'r
7158
7214
  * }
7159
7215
  *
7160
7216
  * @example
7161
- * // Deprecated type — readable in .upg files, migrates on write.
7217
+ * // Deprecated type: readable in .upg files, migrates on write.
7162
7218
  * const painPointMeta: EntityTypeMeta = {
7163
7219
  * name: 'pain_point',
7164
7220
  * type_id: 'ent_018',
@@ -7226,7 +7282,7 @@ declare function getTypeId(name: string): string | undefined;
7226
7282
  *
7227
7283
  * @example
7228
7284
  * getTypeName('ent_016') // → 'persona'
7229
- * getTypeName('ent_018') // → 'pain_point' (deprecated — see `getReplacementType`)
7285
+ * getTypeName('ent_018') // → 'pain_point' (deprecated; see `getReplacementType`)
7230
7286
  * getTypeName('ent_9999') // → undefined
7231
7287
  */
7232
7288
  declare function getTypeName(typeId: string): string | undefined;
@@ -7237,7 +7293,7 @@ declare function getTypeName(typeId: string): string | undefined;
7237
7293
  */
7238
7294
 
7239
7295
  /**
7240
- * A semantic domain — a flat grouping of related entity types.
7296
+ * A semantic domain: a flat grouping of related entity types.
7241
7297
  *
7242
7298
  * @example
7243
7299
  * const userDomain: UPGDomain = {
@@ -7375,7 +7431,7 @@ declare const UPG_DOMAINS: readonly [{
7375
7431
  }, {
7376
7432
  readonly id: "pricing";
7377
7433
  readonly label: "Pricing & Packaging";
7378
- readonly description: "How you package and price your product. Pricing strategies set the overall approach. Pricing tiers define what customers buy — bundling features, trials, gates, and discounts. Discount strategies manage promotions. Trial configs define free-to-paid conversion mechanics. Paywalls gate premium features. Connects Business Model (revenue streams) to Growth (conversion optimization) and Sales (deal structure).";
7434
+ readonly description: "How you package and price your product. Pricing strategies set the overall approach. Pricing tiers define what customers buy, bundling features, trials, gates, and discounts. Discount strategies manage promotions. Trial configs define free-to-paid conversion mechanics. Paywalls gate premium features. Connects Business Model (revenue streams) to Growth (conversion optimization) and Sales (deal structure).";
7379
7435
  readonly types: readonly ["pricing_strategy", "pricing_tier", "discount_strategy", "trial_config", "paywall"];
7380
7436
  }, {
7381
7437
  readonly id: "ai";
@@ -7441,13 +7497,13 @@ declare const UPG_DOMAINS: readonly [{
7441
7497
  /**
7442
7498
  * Union of every canonical domain identifier, derived from UPG_DOMAINS.
7443
7499
  *
7444
- * Adding, removing, or renaming a domain updates this type automatically —
7445
- * do NOT maintain a separate list here.
7500
+ * Adding, removing, or renaming a domain updates this type automatically.
7501
+ * Do NOT maintain a separate list here.
7446
7502
  */
7447
7503
  type UPGDomainId = typeof UPG_DOMAINS[number]['id'];
7448
7504
  /**
7449
7505
  * Canonical entity-type → domain-id lookup. O(1) access, derived from
7450
- * `UPG_DOMAINS` at module init — never maintained by hand.
7506
+ * `UPG_DOMAINS` at module init. Never maintained by hand.
7451
7507
  *
7452
7508
  * Prefer this over walking `UPG_DOMAINS` in downstream packages: the repeated
7453
7509
  * `UPG_DOMAINS.find(d => d.types.includes(t))?.id` pattern is a drift risk
@@ -7480,7 +7536,7 @@ declare function getDomainForType(entityType: string): UPGDomain | undefined;
7480
7536
  * Look up the canonical domain id for a typed entity type. O(1).
7481
7537
  *
7482
7538
  * Returns `undefined` only for the degenerate case where an entity type is
7483
- * absent from every domain — which spec-integrity tests guarantee never
7539
+ * absent from every domain, which spec-integrity tests guarantee never
7484
7540
  * happens for active types. Callers with a `UPGEntityType` can treat the
7485
7541
  * result as non-null, but the return type keeps the escape hatch for
7486
7542
  * defensive string-typed call sites.
@@ -7563,7 +7619,7 @@ declare function getValidChildren(entityType: string): readonly string[];
7563
7619
  */
7564
7620
  declare function canBeChildOf(childType: string, parentType: string): boolean;
7565
7621
  /**
7566
- * Containment-free entity types — types that exist in the graph but are
7622
+ * Containment-free entity types: types that exist in the graph but are
7567
7623
  * *referenced* by other nodes (via edges) rather than *contained* by
7568
7624
  * structural parents. They appear in no `UPG_VALID_CHILDREN` list and
7569
7625
  * have no hierarchy edges into them.
@@ -7571,12 +7627,12 @@ declare function canBeChildOf(childType: string, parentType: string): boolean;
7571
7627
  * This is parallel to `UPG_LIFECYCLE_FREE_TYPES` in `grammar/lifecycles.ts`:
7572
7628
  * both describe what a type *does not have*. Lifecycle-free types lack a
7573
7629
  * status progression; containment-free types lack a structural parent.
7574
- * A type may be one, both, or neither — `person` is both; `theme` is
7630
+ * A type may be one, both, or neither: `person` is both; `theme` is
7575
7631
  * lifecycle-free but structurally contained; `feature` is neither.
7576
7632
  *
7577
7633
  * The G2b hierarchy audit treats absence from `UPG_VALID_CHILDREN` as a
7578
7634
  * defect *unless* the type is in this set. Use this category for types
7579
- * that are orthogonal to product structure — identities, references,
7635
+ * that are orthogonal to product structure: identities, references,
7580
7636
  * cross-cutting concerns that any node might point at.
7581
7637
  *
7582
7638
  * `person` is the first explicit member of the set. Additional candidates
@@ -7591,7 +7647,7 @@ declare function canBeChildOf(childType: string, parentType: string): boolean;
7591
7647
  */
7592
7648
  declare const UPG_CONTAINMENT_FREE_TYPES: ReadonlySet<string>;
7593
7649
  /**
7594
- * Returns `true` if `entityType` is containment-free — i.e. it deliberately
7650
+ * Returns `true` if `entityType` is containment-free, i.e. it deliberately
7595
7651
  * has no structural parent in `UPG_VALID_CHILDREN`. See
7596
7652
  * `UPG_CONTAINMENT_FREE_TYPES` for the rationale and roster.
7597
7653
  */
@@ -7617,12 +7673,12 @@ interface UPGLifecycle {
7617
7673
  * group, label, and link templates without re-detecting them structurally.
7618
7674
  */
7619
7675
  template_id?: string;
7620
- /** The universal phases — fixed by the spec, understood by all tools. */
7676
+ /** The universal phases, fixed by the spec and understood by all tools. */
7621
7677
  phases: LifecyclePhase[];
7622
7678
  /** Which phase a new entity of this type starts in. */
7623
7679
  initial_phase: string;
7624
7680
  /**
7625
- * Phases representing completion — the end points of normal forward progression.
7681
+ * Phases representing completion: the end points of normal forward progression.
7626
7682
  *
7627
7683
  * A terminal phase MAY still declare `transitions_to` entries, which represent
7628
7684
  * late-state transitions (e.g., `archived → draft` for republishing, `approved
@@ -7641,17 +7697,17 @@ interface UPGLifecycle {
7641
7697
  }
7642
7698
  /** A phase is one broad stage in the entity's lifecycle. */
7643
7699
  interface LifecyclePhase {
7644
- /** Machine-readable phase ID — the universal vocabulary.
7700
+ /** Machine-readable phase ID: the universal vocabulary.
7645
7701
  * @example "in_progress" */
7646
7702
  id: string;
7647
7703
  /** Human-readable label.
7648
7704
  * @example "In Progress" */
7649
7705
  label: string;
7650
- /** What this phase means — guidance for agents and documentation.
7706
+ /** What this phase means: guidance for agents and documentation.
7651
7707
  * @example "The solution is actively being built or tested." */
7652
7708
  description: string;
7653
7709
  /**
7654
- * Which phases can follow this one — valid transitions at the phase level.
7710
+ * Which phases can follow this one: valid transitions at the phase level.
7655
7711
  *
7656
7712
  * On non-terminal phases: forward progression targets.
7657
7713
  * On terminal phases: late-state / reopen / revive paths (optional; often empty).
@@ -7659,7 +7715,7 @@ interface LifecyclePhase {
7659
7715
  * @example ["shipped", "deferred"]
7660
7716
  */
7661
7717
  transitions_to: string[];
7662
- /** Core states defined by the spec — always available in this phase.
7718
+ /** Core states defined by the spec, always available in this phase.
7663
7719
  * If omitted, the phase itself is the only state. No nesting needed. */
7664
7720
  core_states?: LifecycleState[];
7665
7721
  }
@@ -7697,26 +7753,26 @@ declare function getLifecycleForType(entityType: string): UPGLifecycle | undefin
7697
7753
  * Entity types that are deliberately lifecycle-free.
7698
7754
  *
7699
7755
  * Every active UPGEntityType must be either in UPG_LIFECYCLES or in this
7700
- * set — the `10-lifecycle-coverage` audit enforces it. The coverage check
7756
+ * set; the `10-lifecycle-coverage` audit enforces it. The coverage check
7701
7757
  * is the successor to the earlier ad-hoc "barren entity" info log.
7702
7758
  *
7703
7759
  * Categories represented here:
7704
7760
  *
7705
- * • **Reference / catalog data** — vocabulary definitions that don't
7761
+ * • **Reference / catalog data**: vocabulary definitions that don't
7706
7762
  * transition (persona, skill, competitor, glossary_term).
7707
- * • **Structural primitives** — atoms of a larger composite (journey_step,
7763
+ * • **Structural primitives**: atoms of a larger composite (journey_step,
7708
7764
  * funnel_step, aggregate, domain_entity, contract_clause).
7709
- * • **Data points / snapshots** — immutable observations (quote,
7765
+ * • **Data points / snapshots**: immutable observations (quote,
7710
7766
  * observation, evidence, survey_response, test_result).
7711
- * • **Configuration** — static settings (paywall, trial_config,
7767
+ * • **Configuration**: static settings (paywall, trial_config,
7712
7768
  * attribution_model, design_token).
7713
- * • **Historical records** — append-only ledger entries (changelog,
7769
+ * • **Historical records**: append-only ledger entries (changelog,
7714
7770
  * approval_record, workflow_artifact, ai_trace, ai_cost_tracker).
7715
- * • **Profile / directory entries** — people and orgs (contact,
7771
+ * • **Profile / directory entries**: people and orgs (contact,
7716
7772
  * stakeholder, organization).
7717
- * • **Computed / derived values** — not workflow-bearing (cohort,
7773
+ * • **Computed / derived values**: not workflow-bearing (cohort,
7718
7774
  * customer_health_score, forecast, error_budget).
7719
- * • **DDD modelling primitives** — aggregates / value objects / commands —
7775
+ * • **DDD modelling primitives**: aggregates / value objects / commands;
7720
7776
  * they describe the domain model, not processes within it.
7721
7777
  *
7722
7778
  * Some of these will gain lifecycles in v0.3 if Entopo usage surfaces real
@@ -7732,27 +7788,27 @@ declare const UPG_LIFECYCLE_FREE_TYPES: ReadonlySet<string>;
7732
7788
  * {@link UPG_LIFECYCLE_FREE_TYPES} for the full list and rationale).
7733
7789
  *
7734
7790
  * @example
7735
- * isLifecycleFreeType('tag') // true — tags are reference data, not stateful artefacts
7736
- * isLifecycleFreeType('feature') // false — features carry a development lifecycle
7791
+ * isLifecycleFreeType('tag') // true (tags are reference data, not stateful artefacts)
7792
+ * isLifecycleFreeType('feature') // false (features carry a development lifecycle)
7737
7793
  */
7738
7794
  declare function isLifecycleFreeType(entityType: string): boolean;
7739
7795
  /**
7740
- * Entity types that are **triaged but not yet implemented** — each has a
7796
+ * Entity types that are **triaged but not yet implemented**; each has a
7741
7797
  * lifecycle planned for a later phase of. This set exists so that
7742
7798
  * the coverage audit (`10-lifecycle-coverage`) distinguishes
7743
- * "actively deferred" from "untriaged" — moving a type here is a commitment
7799
+ * "actively deferred" from "untriaged"; moving a type here is a commitment
7744
7800
  * to enrich it, not a punt.
7745
7801
  *
7746
7802
  * Phase breakdown (committed 2026-04-17):
7747
7803
  *
7748
- * • **Phase B** — high-value hand-authored lifecycles (NL) + two new
7804
+ * • **Phase B**: high-value hand-authored lifecycles (NL) + two new
7749
7805
  * templates (SALES_DEAL, RISK_ITEM). ~30 types: outcome, feature, epic,
7750
7806
  * user_story, bug, deal, threat, risk, compliance_requirement, insight,
7751
7807
  * hypothesis-adjacent artefacts, workflow artefacts, etc.
7752
- * • **Phase C** — expand existing-template coverage to the PUBLISHING /
7808
+ * • **Phase C**: expand existing-template coverage to the PUBLISHING /
7753
7809
  * OPERATIONAL / APPROVAL / MATURITY / WORK_ITEM buckets via
7754
7810
  * `fromTemplate()`. ~60 types.
7755
- * • **Phase D** — residual new lifecycles for types that don't fit a
7811
+ * • **Phase D**: residual new lifecycles for types that don't fit a
7756
7812
  * template cleanly but didn't make Phase B's cut. ~10 types.
7757
7813
  *
7758
7814
  * As phases land, types migrate out of this set into UPG_LIFECYCLES.
@@ -7765,13 +7821,13 @@ declare const UPG_LIFECYCLE_PLANNED_TYPES: ReadonlySet<string>;
7765
7821
  * (see {@link UPG_LIFECYCLE_PLANNED_TYPES}).
7766
7822
  *
7767
7823
  * @example
7768
- * isLifecyclePlannedType('outcome') // true — planned for a later phase
7769
- * isLifecyclePlannedType('feature') // false — feature lifecycle is already implemented
7824
+ * isLifecyclePlannedType('outcome') // true (planned for a later phase)
7825
+ * isLifecyclePlannedType('feature') // false (feature lifecycle is already implemented)
7770
7826
  */
7771
7827
  declare function isLifecyclePlannedType(entityType: string): boolean;
7772
7828
  /** A render-ready lifecycle state (one phase of the underlying lifecycle). */
7773
7829
  interface LifecycleRenderState {
7774
- /** Phase id — e.g. `'draft'`, `'in_progress'`, `'archived'`. */
7830
+ /** Phase id (e.g. `'draft'`, `'in_progress'`, `'archived'`). */
7775
7831
  id: string;
7776
7832
  /** Human-readable label. */
7777
7833
  label: string;
@@ -7790,10 +7846,10 @@ interface LifecycleRenderTransition {
7790
7846
  * Classification derived from the lifecycle's terminal set and authoring
7791
7847
  * order:
7792
7848
  *
7793
- * - `'reopen'` — source is terminal, target is not (e.g. `archived → draft`).
7794
- * - `'terminal'` — target is terminal, source is not (forward to completion).
7795
- * - `'backward'` — target appears before source in `phases[]` and is not a reopen.
7796
- * - `'forward'` — everything else.
7849
+ * - `'reopen'`: source is terminal, target is not (e.g. `archived → draft`).
7850
+ * - `'terminal'`: target is terminal, source is not (forward to completion).
7851
+ * - `'backward'`: target appears before source in `phases[]` and is not a reopen.
7852
+ * - `'forward'`: everything else.
7797
7853
  *
7798
7854
  * The classification is a render hint, not a validation rule: any transition
7799
7855
  * declared in the source lifecycle is valid by definition.
@@ -7814,7 +7870,7 @@ interface LifecycleRenderShape {
7814
7870
  states: LifecycleRenderState[];
7815
7871
  /** Render transitions, classified by `kind`. */
7816
7872
  transitions: LifecycleRenderTransition[];
7817
- /** Initial state id — equals the source `initial_phase`. */
7873
+ /** Initial state id; equals the source `initial_phase`. */
7818
7874
  initial_state: string;
7819
7875
  }
7820
7876
  /**
@@ -7822,7 +7878,7 @@ interface LifecycleRenderShape {
7822
7878
  * lifecycle, or `null` if the type is intentionally lifecycle-free
7823
7879
  * (see {@link UPG_LIFECYCLE_FREE_TYPES}).
7824
7880
  *
7825
- * The shape is flattened to one level — each phase becomes one render state.
7881
+ * The shape is flattened to one level; each phase becomes one render state.
7826
7882
  * Optional finer-grained `core_states` are not surfaced here; consumers that
7827
7883
  * need them should read the source lifecycle directly via
7828
7884
  * {@link getLifecycleForType}.
@@ -7906,7 +7962,7 @@ declare const UPG_SCALES: Record<string, UPGScaleDefinition>;
7906
7962
  /**
7907
7963
  * Look up a scale definition by its ID.
7908
7964
  *
7909
- * Returns undefined for unknown IDs — callers should handle this case
7965
+ * Returns undefined for unknown IDs; callers should handle this case
7910
7966
  * gracefully (e.g. fall back to displaying raw value).
7911
7967
  *
7912
7968
  * @example
@@ -7921,8 +7977,8 @@ declare function getScale(scaleId: string): UPGScaleDefinition | undefined;
7921
7977
  * 1. Check `PROPERTY_SCALE_MAP` for a property-level override.
7922
7978
  * 2. Fall back to `'scale_5'` (generic 1–5 ordinal) for all other properties.
7923
7979
  *
7924
- * The `entityType` parameter is accepted for API stability — future versions
7925
- * may add per-entity overrides — but the initial implementation ignores it.
7980
+ * The `entityType` parameter is accepted for API stability; future versions
7981
+ * may add per-entity overrides, but the initial implementation ignores it.
7926
7982
  *
7927
7983
  * @param entityType - The UPG entity type string (e.g. `'problem_statement'`).
7928
7984
  * Currently unused; reserved for future per-entity overrides.
@@ -7958,7 +8014,7 @@ interface UPGEnumScaleValue {
7958
8014
  *
7959
8015
  * `values` is ordered semantically (e.g. low → high for ordinal scales;
7960
8016
  * strict → permissive for rule strength). Array index is the canonical
7961
- * position — no separate `position` field.
8017
+ * position (no separate `position` field).
7962
8018
  */
7963
8019
  interface UPGEnumScaleDefinition {
7964
8020
  /** Matches the TypeScript type name (e.g. `'HealthStatus'`) */
@@ -7970,12 +8026,12 @@ interface UPGEnumScaleDefinition {
7970
8026
  /** Per-value metadata in semantic order */
7971
8027
  values: UPGEnumScaleValue[];
7972
8028
  /**
7973
- * Optional rendering hint — which end of the scale is desirable.
8029
+ * Optional rendering hint: which end of the scale is desirable.
7974
8030
  * Parallel to `SCALE_TONE_DIRECTION` for numeric scales.
7975
8031
  *
7976
- * `'high-is-good'` — first value is best (e.g. on_track, high confidence)
7977
- * `'low-is-good'` — last value in natural order is worst (e.g. critical urgency is bad)
7978
- * `'neutral'` — no inherent good/bad direction (e.g. Cadence, Priority)
8032
+ * `'high-is-good'`: first value is best (e.g. on_track, high confidence)
8033
+ * `'low-is-good'`: last value in natural order is worst (e.g. critical urgency is bad)
8034
+ * `'neutral'`: no inherent good/bad direction (e.g. Cadence, Priority)
7979
8035
  */
7980
8036
  tone_direction?: 'high-is-good' | 'low-is-good' | 'neutral';
7981
8037
  }
@@ -8010,7 +8066,7 @@ declare const UPG_MIGRATIONS: Record<string, UPGTypeMigration[]>;
8010
8066
  *
8011
8067
  * Returns a negative number if `a < b`, zero if `a === b`, positive if `a > b`.
8012
8068
  * Components are compared numerically (e.g. `0.2.11` is greater than `0.2.8`,
8013
- * not less — naive string comparison gets this backwards because `'11' < '8'`
8069
+ * not less; naive string comparison gets this backwards because `'11' < '8'`
8014
8070
  * lexicographically).
8015
8071
  *
8016
8072
  * Used by every range-filtered migration helper below
@@ -8031,7 +8087,7 @@ declare function compareVersions(a: string, b: string): number;
8031
8087
  * Used by TYPE_ALIASES and .upg file readers.
8032
8088
  *
8033
8089
  * @example
8034
- * // Upgrading from v0 (pre-UPG) to v0.2.0 — collect every type rename.
8090
+ * // Upgrading from v0 (pre-UPG) to v0.2.0: collect every type rename.
8035
8091
  * const map = getMigrationMap('0.0.0', '0.2.0')
8036
8092
  * // map.pain_point === 'need'
8037
8093
  * // map.jtbd === 'job'
@@ -8042,7 +8098,7 @@ declare function getMigrationMap(fromVersion: string, toVersion: string): Record
8042
8098
  * Apply migrations to a single node, converting its type and
8043
8099
  * merging default properties.
8044
8100
  *
8045
- * `T` is the caller's node shape — typically `UPGBaseNode` or a narrower
8101
+ * `T` is the caller's node shape, typically `UPGBaseNode` or a narrower
8046
8102
  * app-specific node type. The constraint (`{ type: string; properties?: ... }`)
8047
8103
  * keeps the function node-library-agnostic so adapters, CLI tools, and test
8048
8104
  * fixtures can all reuse it without coupling to `UPGBaseNode` directly.
@@ -8056,7 +8112,7 @@ declare function getMigrationMap(fromVersion: string, toVersion: string): Record
8056
8112
  * // migrated.properties.description === 'Onboarding is slow' // original preserved
8057
8113
  *
8058
8114
  * @example
8059
- * // Non-deprecated type passes through — return shape preserves T.
8115
+ * // Non-deprecated type passes through; return shape preserves T.
8060
8116
  * const healthy = { id: 'n2', type: 'persona', properties: { is_primary: true } }
8061
8117
  * const same = migrateNode(healthy, '0.0.0', '0.1.0')
8062
8118
  * // same === healthy (referentially unchanged)
@@ -8081,9 +8137,9 @@ declare function getDeprecatedTypes(): Set<string>;
8081
8137
  *
8082
8138
  * Discriminated by `kind`:
8083
8139
  *
8084
- * - `'drop_props'` — remove keys from `node.properties`. The original
8140
+ * - `'drop_props'`: remove keys from `node.properties`. The original
8085
8141
  * shape; the existing v0.2.2 + v0.2.8 entries use this.
8086
- * - `'rename_top_level'` — rename a top-level `UPGBaseNode` field to a
8142
+ * - `'rename_top_level'`: rename a top-level `UPGBaseNode` field to a
8087
8143
  * different top-level field, optionally remapping its value. Used when a
8088
8144
  * pre-canonical custom field (e.g. `lifecycle_status`) shifts to its
8089
8145
  * canonical slot (`status`).
@@ -8091,7 +8147,7 @@ declare function getDeprecatedTypes(): Set<string>;
8091
8147
  * top-level field, optionally remapping. Used when a slot that was
8092
8148
  * pragmatically stuffed in `properties` graduates to a top-level
8093
8149
  * `UPGBaseNode` slot (e.g. `properties.stage` → top-level `status`).
8094
- * - `'drop_when_self_referential'` — drop top-level fields whose value
8150
+ * - `'drop_when_self_referential'`: drop top-level fields whose value
8095
8151
  * equals the node's own `id` or `type` (or another configured
8096
8152
  * self-reference). Used to clean up redundant round-trip metadata that's
8097
8153
  * only meaningful when pointing OUT of the node, not at itself.
@@ -8217,7 +8273,7 @@ declare function migrateNodeProperties<T extends {
8217
8273
  changes: UPGPropertyMigrationChange[];
8218
8274
  };
8219
8275
  /**
8220
- * Returns every property migration entry between two versions — useful for
8276
+ * Returns every property migration entry between two versions; useful for
8221
8277
  * load-time warning generation and audit reports.
8222
8278
  */
8223
8279
  declare function getPropertyMigrations(fromVersion: string, toVersion: string): UPGPropertyMigration[];
@@ -8232,7 +8288,7 @@ interface UPGSplitTarget {
8232
8288
  /** Defaults merged after keep_props (route-specific defaults win). */
8233
8289
  defaults?: Record<string, unknown>;
8234
8290
  }
8235
- /** Per-target route plan — what to spawn and what overrides apply. */
8291
+ /** Per-target route plan: what to spawn and what overrides apply. */
8236
8292
  interface UPGSplitRouteTarget {
8237
8293
  /** Route-specific defaults merged on top of UPGSplitTarget.defaults. */
8238
8294
  defaults?: Record<string, unknown>;
@@ -8258,9 +8314,9 @@ interface UPGSplitEdge {
8258
8314
  /**
8259
8315
  * When to emit the edge.
8260
8316
  *
8261
- * - `'both_spawned'` — only emit if both source_ref and target_ref were
8317
+ * - `'both_spawned'`: only emit if both source_ref and target_ref were
8262
8318
  * spawned by the routing rule.
8263
- * - `'always'` — emit unconditionally (rare; only valid if both refs
8319
+ * - `'always'`: emit unconditionally (rare; only valid if both refs
8264
8320
  * appear in every routing entry's `spawn`).
8265
8321
  */
8266
8322
  when: 'both_spawned' | 'always';
@@ -8275,7 +8331,7 @@ interface UPGSplitMigration {
8275
8331
  status_property: string;
8276
8332
  /** The N canonical types this rule produces. */
8277
8333
  produces: readonly UPGSplitTarget[];
8278
- /** Per-status routing — keys are values of source[status_property]. */
8334
+ /** Per-status routing: keys are values of source[status_property]. */
8279
8335
  routing: Record<string, UPGSplitRoute>;
8280
8336
  /** Edges to emit between spawned targets. */
8281
8337
  edges: readonly UPGSplitEdge[];
@@ -8303,7 +8359,7 @@ declare function getSplitMigrations(fromVersion: string, toVersion: string): UPG
8303
8359
  * `flip` is true) and may gate on endpoint identity via
8304
8360
  * `requires_source_type` / `requires_target_type`.
8305
8361
  *
8306
- * `drop` removes the edge entirely (no replacement key) — used when a
8362
+ * `drop` removes the edge entirely (no replacement key); used when a
8307
8363
  * legacy edge has been superseded by a structurally different canonical
8308
8364
  * edge whose endpoints don't match the legacy rule's `from`.
8309
8365
  */
@@ -8337,13 +8393,13 @@ declare const UPG_EDGE_MIGRATIONS: Record<string, UPGEdgeMigration[]>;
8337
8393
  * Get all edge migration rules between two versions, in version order.
8338
8394
  *
8339
8395
  * @example
8340
- * // v0.2.0 backfill — six jtbd→job edge renames.
8396
+ * // v0.2.0 backfill: six jtbd→job edge renames.
8341
8397
  * const rules = getUPGEdgeMigrations('0.0.0', '0.2.0')
8342
8398
  * rules.length // → 6
8343
8399
  * rules.every(r => r.kind === 'rename') // → true
8344
8400
  *
8345
8401
  * @example
8346
- * // Full v0.2.x range — every rule from v0.2.0 + v0.2.7 + v0.2.8.
8402
+ * // Full v0.2.x range: every rule from v0.2.0 + v0.2.7 + v0.2.8.
8347
8403
  * getUPGEdgeMigrations('0.0.0', '0.2.8').filter(r => r.kind === 'drop').length // → 4
8348
8404
  */
8349
8405
  declare function getUPGEdgeMigrations(fromVersion: string, toVersion: string): UPGEdgeMigration[];
@@ -8353,7 +8409,7 @@ declare function getUPGEdgeMigrations(fromVersion: string, toVersion: string): U
8353
8409
  * Both `sourceType` and `targetType` should be the *post-migration* node
8354
8410
  * types (i.e. after `migrateNode` / `applySplit` has run on the endpoints).
8355
8411
  * When omitted, rules with `requires_source_type` / `requires_target_type`
8356
- * guards are skipped (safer default — a guard that cannot be evaluated
8412
+ * guards are skipped (safer default; a guard that cannot be evaluated
8357
8413
  * does not fire).
8358
8414
  */
8359
8415
  interface UPGEdgeMigrationEndpoints {
@@ -8368,7 +8424,7 @@ interface UPGEdgeMigrationEndpoints {
8368
8424
  * dead-ends.
8369
8425
  *
8370
8426
  * **Why this exists.** `UPG_EDGE_MIGRATIONS` accumulates rules across the
8371
- * spec's history. A single edge can be renamed multiple times — and the
8427
+ * spec's history. A single edge can be renamed multiple times, and the
8372
8428
  * direction can reverse (e.g. v0.2.8 renamed `solution_proposes_hypothesis`
8373
8429
  * → `solution_proposes_hypothesis_claim`, then v0.4.0 renamed the latter
8374
8430
  * back to the former). Naively picking "the first rule whose `from` matches"
@@ -8384,19 +8440,19 @@ interface UPGEdgeMigrationEndpoints {
8384
8440
  * outcome rather than loop forever.
8385
8441
  *
8386
8442
  * **Return values.**
8387
- * - `{ kind: 'canonical', to }` — the walk landed on a key present in
8443
+ * - `{ kind: 'canonical', to }`: the walk landed on a key present in
8388
8444
  * `UPG_EDGE_CATALOG`. Callers should suggest `to` as the migration target.
8389
- * - `{ kind: 'drop' }` — the walk encountered a `drop` rule. The edge has
8445
+ * - `{ kind: 'drop' }`: the walk encountered a `drop` rule. The edge has
8390
8446
  * no canonical replacement.
8391
- * - `{ kind: 'dead_end', last }` — no rule matched and `last` is not in
8447
+ * - `{ kind: 'dead_end', last }`: no rule matched and `last` is not in
8392
8448
  * `UPG_EDGE_CATALOG`. The edge is non-canonical with no known migration
8393
8449
  * target.
8394
- * - `{ kind: 'cycle', visited }` — a cycle was detected. Returned so
8450
+ * - `{ kind: 'cycle', visited }`: a cycle was detected. Returned so
8395
8451
  * callers can degrade gracefully. Should not happen in practice given
8396
8452
  * the version-ordered structure of `UPG_EDGE_MIGRATIONS`.
8397
8453
  *
8398
8454
  * **Caller note.** Callers that already know `edge_type` is canonical
8399
- * (i.e. `edge_type in UPG_EDGE_CATALOG`) should NOT call this helper —
8455
+ * (i.e. `edge_type in UPG_EDGE_CATALOG`) should NOT call this helper;
8400
8456
  * there's nothing to suggest. The helper is for the case where the edge
8401
8457
  * type is deprecated and the caller needs to find its canonical successor.
8402
8458
  *
@@ -8411,7 +8467,7 @@ interface UPGEdgeMigrationEndpoints {
8411
8467
  * // → { kind: 'drop' }
8412
8468
  *
8413
8469
  * @example
8414
- * // Already-canonical edge type — returns dead_end because the helper is
8470
+ * // Already-canonical edge type: returns dead_end because the helper is
8415
8471
  * // intended for non-canonical callers. The 'canonical' branch fires only
8416
8472
  * // when the chain ENDS on a catalog entry, not when it STARTS on one.
8417
8473
  * // (In practice the validator skips this case before calling.)
@@ -8436,20 +8492,20 @@ declare function walkMigrationChainToCanonical(edge_type: string, catalog: Reado
8436
8492
  * - the original edge (un-shaped, referentially equal) if no rule matched;
8437
8493
  * - a new edge with retyped `type` (and possibly swapped `source`/`target`
8438
8494
  * when the rule sets `flip: true`) if a `rename` rule matched;
8439
- * - `null` if a `drop` rule matched — caller should remove the edge.
8495
+ * - `null` if a `drop` rule matched; caller should remove the edge.
8440
8496
  *
8441
8497
  * Endpoint guards (`requires_source_type` / `requires_target_type`) check
8442
8498
  * the *post-migration* endpoint types provided via `endpoints`. When
8443
- * `endpoints` is omitted, guarded rules are skipped — callers running edge
8499
+ * `endpoints` is omitted, guarded rules are skipped; callers running edge
8444
8500
  * migration in isolation (without endpoint type context) get only the
8445
8501
  * un-guarded rules.
8446
8502
  *
8447
- * `T` is the caller's edge shape — only `type` is required; `source` and
8503
+ * `T` is the caller's edge shape; only `type` is required. `source` and
8448
8504
  * `target` are touched only when `flip: true` and are otherwise preserved
8449
8505
  * verbatim.
8450
8506
  *
8451
8507
  * @example
8452
- * // No rule matches — edge passes through unchanged.
8508
+ * // No rule matches; edge passes through unchanged.
8453
8509
  * const edge = { id: 'e1', type: 'persona_pursues_job' }
8454
8510
  * migrateEdge(edge, '0.2.0', '0.2.8') === edge // → true
8455
8511
  *
@@ -8460,7 +8516,7 @@ declare function walkMigrationChainToCanonical(edge_type: string, catalog: Reado
8460
8516
  * migrated?.type // → 'persona_pursues_job'
8461
8517
  *
8462
8518
  * @example
8463
- * // Drop rule matches — null signals "remove this edge".
8519
+ * // Drop rule matches; null signals "remove this edge".
8464
8520
  * const dropped = { id: 'e3', type: 'experiment_tests_hypothesis' }
8465
8521
  * migrateEdge(dropped, '0.0.0', '0.2.7') // → null
8466
8522
  */
@@ -8497,7 +8553,7 @@ declare function migrateEdge<T extends {
8497
8553
  * Each top-level key is an entity type; each inner key is a legacy status
8498
8554
  * value observed in real graphs; the value is the canonical phase id from
8499
8555
  * that type's lifecycle. Entity types absent from this map have no
8500
- * registered status migration — `migrateStatusValue` returns `null` for
8556
+ * registered status migration; `migrateStatusValue` returns `null` for
8501
8557
  * them, signalling "no automated fix; surface to operator".
8502
8558
  *
8503
8559
  * **Population strategy.** Only mappings that are unambiguous from observed
@@ -8505,7 +8561,7 @@ declare function migrateEdge<T extends {
8505
8561
  * different canonical phases, the type is left empty rather than guessing.
8506
8562
  *
8507
8563
  * **Why this is a map of maps rather than a list of rules.** Status values
8508
- * are entity-type-scoped — `"active"` means different things on `service`,
8564
+ * are entity-type-scoped: `"active"` means different things on `service`,
8509
8565
  * `feature`, and `hypothesis`. A flat `[{ from, to, type }]` list would
8510
8566
  * force every lookup to filter; a map of maps gives O(1) `[type][value]`
8511
8567
  * lookup and makes the per-type registry obvious to readers.
@@ -8518,7 +8574,7 @@ declare const UPG_STATUS_MIGRATIONS: Partial<Record<UPGEntityType, Record<string
8518
8574
  * Caller contract: only invoke when the current status is known-invalid
8519
8575
  * for the entity's lifecycle. `null` signals "no automated fix is on
8520
8576
  * file; surface to the operator". The presence of a mapping does NOT
8521
- * imply the current status is invalid — checking validity is the caller's
8577
+ * imply the current status is invalid; checking validity is the caller's
8522
8578
  * job (typically via `getLifecycleForType(entityType).phases`).
8523
8579
  *
8524
8580
  * @example
@@ -8648,9 +8704,9 @@ interface UPGValidationError {
8648
8704
  interface UPGValidationResult {
8649
8705
  /** Whether the document passed all mandatory spec checks */
8650
8706
  valid: boolean;
8651
- /** Spec violations — any entry here means `valid` is false */
8707
+ /** Spec violations: any entry here means `valid` is false */
8652
8708
  errors: UPGValidationError[];
8653
- /** Best-practice notices — present even when `valid` is true */
8709
+ /** Best-practice notices: present even when `valid` is true */
8654
8710
  warnings: UPGValidationWarning[];
8655
8711
  }
8656
8712
  interface UPGValidationWarning {
@@ -8681,7 +8737,7 @@ interface UPGValidationWarning {
8681
8737
  */
8682
8738
  declare function validateUPGDocument(doc: unknown): UPGValidationResult;
8683
8739
  /**
8684
- * Type guard — returns true if the document is a valid UPGDocument.
8740
+ * Type guard: returns true if the document is a valid UPGDocument.
8685
8741
  * Use `validateUPGDocument` for detailed error reporting.
8686
8742
  *
8687
8743
  * @example
@@ -8709,10 +8765,10 @@ type ISODateTime = string;
8709
8765
  *
8710
8766
  * Format: `PnYnMnDTnHnMnS` (year/month/day prefix P, time prefix T).
8711
8767
  * Common examples:
8712
- * `P14D` — 14 days
8713
- * `P3M` — 3 months
8714
- * `PT2H30M` — 2 hours 30 minutes
8715
- * `P1Y6M` — 1 year 6 months
8768
+ * `P14D` : 14 days
8769
+ * `P3M` : 3 months
8770
+ * `PT2H30M` : 2 hours 30 minutes
8771
+ * `P1Y6M` : 1 year 6 months
8716
8772
  *
8717
8773
  * Used for retention periods, notice periods, agreement terms, lead times,
8718
8774
  * lookback windows, sprint durations, and any other measured time span.
@@ -8725,9 +8781,9 @@ type Duration = string;
8725
8781
  * Extended 6-field form: `second minute hour day-of-month month day-of-week`
8726
8782
  *
8727
8783
  * Examples:
8728
- * `'0 9 * * 1'` — every Monday at 09:00
8729
- * `'0 0 1 * *'` — first day of every month at midnight
8730
- * `'*\/15 * * * *'` — every 15 minutes
8784
+ * `'0 9 * * 1'` : every Monday at 09:00
8785
+ * `'0 0 1 * *'` : first day of every month at midnight
8786
+ * `'*\/15 * * * *'` : every 15 minutes
8731
8787
  *
8732
8788
  * Used for scheduled data pipelines, recurring jobs, and automation triggers.
8733
8789
  */
@@ -8735,12 +8791,12 @@ type Cron = string;
8735
8791
  /**
8736
8792
  * Flexible, human-readable timeframe label.
8737
8793
  *
8738
- * Accepted forms (not exhaustive — this is an open-shape string):
8739
- * `'Q1 2026'` — calendar quarter
8740
- * `'2026-H1'` — calendar half-year
8741
- * `'FY2027 Q2'` — fiscal quarter
8742
- * `'12-18 months'` — relative range
8743
- * `'now'` / `'ongoing'` — open-ended
8794
+ * Accepted forms (not exhaustive; this is an open-shape string):
8795
+ * `'Q1 2026'` : calendar quarter
8796
+ * `'2026-H1'` : calendar half-year
8797
+ * `'FY2027 Q2'` : fiscal quarter
8798
+ * `'12-18 months'` : relative range
8799
+ * `'now'` / `'ongoing'` : open-ended
8744
8800
  *
8745
8801
  * Used to unify `timeline`, `time_horizon`, `timeframe`, `period`, and
8746
8802
  * `report_period` properties that share the same human-calendar semantics
@@ -8753,7 +8809,7 @@ type Timeframe = string;
8753
8809
  * Examples: `'USD'`, `'EUR'`, `'GBP'`, `'JPY'`.
8754
8810
  * All characters must be ASCII uppercase letters (A–Z).
8755
8811
  *
8756
- * Used wherever a property JSDoc says "ISO 4217" — pricing tiers, contracts,
8812
+ * Used wherever a property JSDoc says "ISO 4217": pricing tiers, contracts,
8757
8813
  * sales quotes, growth campaigns, and localisation settings.
8758
8814
  */
8759
8815
  type ISO4217 = string;
@@ -8823,18 +8879,18 @@ type SignalSentiment = 'positive' | 'neutral' | 'negative' | 'mixed';
8823
8879
  * provides the canonical closed set for migration.
8824
8880
  *
8825
8881
  * Members:
8826
- * `'analytics_event'` — first-party product analytics event (PostHog, Amplitude, etc.)
8827
- * `'community'` — forum, Discord, Slack community, etc.
8828
- * `'email'` — direct email or newsletter reply
8829
- * `'in_app'` — in-product feedback widget, NPS prompt, or beta-feedback panel
8830
- * `'interview'` — user or sales interview
8831
- * `'other'` — catch-all for unlisted channels
8832
- * `'review'` — app store or G2/Capterra review
8833
- * `'sales_call'` — sales demo or discovery call
8834
- * `'social'` — social media mention or DM
8835
- * `'support_ticket'` — helpdesk or in-app support ticket
8836
- * `'survey'` — NPS, CSAT, or custom survey
8837
- * `'usage_session'` — observed product session (telemetry-derived friction signal)
8882
+ * `'analytics_event'` : first-party product analytics event (PostHog, Amplitude, etc.)
8883
+ * `'community'` : forum, Discord, Slack community, etc.
8884
+ * `'email'` : direct email or newsletter reply
8885
+ * `'in_app'` : in-product feedback widget, NPS prompt, or beta-feedback panel
8886
+ * `'interview'` : user or sales interview
8887
+ * `'other'` : catch-all for unlisted channels
8888
+ * `'review'` : app store or G2/Capterra review
8889
+ * `'sales_call'` : sales demo or discovery call
8890
+ * `'social'` : social media mention or DM
8891
+ * `'support_ticket'` : helpdesk or in-app support ticket
8892
+ * `'survey'` : NPS, CSAT, or custom survey
8893
+ * `'usage_session'` : observed product session (telemetry-derived friction signal)
8838
8894
  */
8839
8895
  type SignalChannel = 'analytics_event' | 'community' | 'email' | 'in_app' | 'interview' | 'other' | 'review' | 'sales_call' | 'social' | 'support_ticket' | 'survey' | 'usage_session';
8840
8896
  /**
@@ -8847,15 +8903,15 @@ type SignalChannel = 'analytics_event' | 'community' | 'email' | 'in_app' | 'int
8847
8903
  * rather than a labelled tier.
8848
8904
  *
8849
8905
  * Members (coarse → fine):
8850
- * `'continuous'` — always running / no discrete recurrence
8851
- * `'hourly'` — recurs every hour
8852
- * `'daily'` — recurs every day
8853
- * `'weekly'` — recurs every week
8854
- * `'monthly'` — recurs every month
8855
- * `'quarterly'` — recurs every calendar quarter
8856
- * `'yearly'` — recurs every year
8857
- * `'on_demand'` — triggered by event, not schedule
8858
- * `'other'` — recurs on a cadence not captured by the above tiers
8906
+ * `'continuous'` : always running, no discrete recurrence
8907
+ * `'hourly'` : recurs every hour
8908
+ * `'daily'` : recurs every day
8909
+ * `'weekly'` : recurs every week
8910
+ * `'monthly'` : recurs every month
8911
+ * `'quarterly'` : recurs every calendar quarter
8912
+ * `'yearly'` : recurs every year
8913
+ * `'on_demand'` : triggered by event, not schedule
8914
+ * `'other'` : recurs on a cadence not captured by the above tiers
8859
8915
  *
8860
8916
  * Introduced in v0.4.0 as the canonical replacement for ad-hoc
8861
8917
  * `frequency?: string` and `*cadence?: string` properties (Concern 2 axis
@@ -8875,17 +8931,17 @@ type Cadence = 'continuous' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'quart
8875
8931
  * will normalise casing in a follow-up pass.
8876
8932
  *
8877
8933
  * Members (alphabetical):
8878
- * `'asyncapi'` — AsyncAPI / event-driven API spec
8879
- * `'event'` — generic event/message bus
8880
- * `'file'` — file-based transfer (SFTP, S3, etc.)
8881
- * `'graphql'` — GraphQL over HTTP
8882
- * `'grpc'` — gRPC / Protocol Buffers
8883
- * `'mqtt'` — MQTT (IoT / lightweight pub-sub)
8884
- * `'other'` — unlisted protocol
8885
- * `'rest'` — REST over HTTP
8886
- * `'soap'` — SOAP / XML web services
8887
- * `'webhook'` — HTTP webhook (push callback)
8888
- * `'websocket'` — WebSocket bidirectional stream
8934
+ * `'asyncapi'` : AsyncAPI / event-driven API spec
8935
+ * `'event'` : generic event/message bus
8936
+ * `'file'` : file-based transfer (SFTP, S3, etc.)
8937
+ * `'graphql'` : GraphQL over HTTP
8938
+ * `'grpc'` : gRPC / Protocol Buffers
8939
+ * `'mqtt'` : MQTT (IoT / lightweight pub-sub)
8940
+ * `'other'` : unlisted protocol
8941
+ * `'rest'` : REST over HTTP
8942
+ * `'soap'` : SOAP / XML web services
8943
+ * `'webhook'` : HTTP webhook (push callback)
8944
+ * `'websocket'` : WebSocket bidirectional stream
8889
8945
  */
8890
8946
  type Protocol = 'asyncapi' | 'event' | 'file' | 'graphql' | 'grpc' | 'mqtt' | 'other' | 'rest' | 'soap' | 'webhook' | 'websocket';
8891
8947
  /**
@@ -8898,18 +8954,18 @@ type Protocol = 'asyncapi' | 'event' | 'file' | 'graphql' | 'grpc' | 'mqtt' | 'o
8898
8954
  * This primitive is the alphabetical superset of both.
8899
8955
  *
8900
8956
  * Members:
8901
- * `'discord'` — Discord community / server
8902
- * `'email'` — newsletter / email marketing platform
8903
- * `'google'` — Google Ads / Search / Display
8904
- * `'instagram'` — Instagram organic or paid
8905
- * `'linkedin'` — LinkedIn organic or paid
8906
- * `'meta'` — Meta Ads (Facebook/Instagram ad platform)
8907
- * `'other'` — unlisted platform
8908
- * `'podcast'` — podcast advertising or distribution
8909
- * `'reddit'` — Reddit organic or paid
8910
- * `'tiktok'` — TikTok organic or paid
8911
- * `'twitter'` — Twitter / X organic or paid
8912
- * `'youtube'` — YouTube organic or paid
8957
+ * `'discord'` : Discord community / server
8958
+ * `'email'` : newsletter / email marketing platform
8959
+ * `'google'` : Google Ads / Search / Display
8960
+ * `'instagram'` : Instagram organic or paid
8961
+ * `'linkedin'` : LinkedIn organic or paid
8962
+ * `'meta'` : Meta Ads (Facebook/Instagram ad platform)
8963
+ * `'other'` : unlisted platform
8964
+ * `'podcast'` : podcast advertising or distribution
8965
+ * `'reddit'` : Reddit organic or paid
8966
+ * `'tiktok'` : TikTok organic or paid
8967
+ * `'twitter'` : Twitter / X organic or paid
8968
+ * `'youtube'` : YouTube organic or paid
8913
8969
  */
8914
8970
  type MarketingPlatform = 'discord' | 'email' | 'google' | 'instagram' | 'linkedin' | 'meta' | 'other' | 'podcast' | 'reddit' | 'tiktok' | 'twitter' | 'youtube';
8915
8971
 
@@ -9035,7 +9091,7 @@ interface VisionProperties {
9035
9091
  * @example
9036
9092
  * const properties: MissionProperties = {
9037
9093
  * target_audience: 'Product managers and founders at 10–200-person B2B SaaS companies.',
9038
- * core_value: 'Clarity beats velocity — decisions you can justify compound faster than code.',
9094
+ * core_value: 'Clarity beats velocity: decisions you can justify compound faster than code.',
9039
9095
  * differentiation: 'Open interchange format + works where you already think.',
9040
9096
  * }
9041
9097
  */
@@ -9414,7 +9470,7 @@ interface JobStepProperties {
9414
9470
  * const properties: SwitchingCostProperties = {
9415
9471
  * cost_type: 'financial',
9416
9472
  * magnitude: 'high',
9417
- * barrier_description: 'Extensive Notion workspace with years of history — migration feels daunting.',
9473
+ * barrier_description: 'Extensive Notion workspace with years of history; migration feels daunting.',
9418
9474
  * }
9419
9475
  */
9420
9476
  interface SwitchingCostProperties {
@@ -10471,7 +10527,7 @@ interface JourneyStepProperties {
10471
10527
  * opportunity_score: 5,
10472
10528
  * evidence: 'Pasted transcript appears as a single text node',
10473
10529
  * system: 'canvas-paste-handler',
10474
- * notes: 'Most users hesitate before pasting — too much trust required.',
10530
+ * notes: 'Most users hesitate before pasting; too much trust required.',
10475
10531
  * }
10476
10532
  */
10477
10533
  interface JourneyActionProperties {
@@ -10545,7 +10601,7 @@ interface DesignQuestionProperties {
10545
10601
  * @example
10546
10602
  * const properties: DesignConceptProperties = {
10547
10603
  * sketch_url: 'https://figma.com/file/abc/sketch',
10548
- * rationale: 'Reduces support burden and lifts activation — both priorities this quarter.',
10604
+ * rationale: 'Reduces support burden and lifts activation, both priorities this quarter.',
10549
10605
  * concept_status: 'exploring',
10550
10606
  * }
10551
10607
  */
@@ -10797,7 +10853,7 @@ interface DesignPatternProperties {
10797
10853
  * const properties: DesignGuidelineProperties = {
10798
10854
  * guideline_category: 'spacing',
10799
10855
  * applies_to: 'All customer-facing surfaces',
10800
- * rationale: 'Reduces support burden and lifts activation — both priorities this quarter.',
10856
+ * rationale: 'Reduces support burden and lifts activation, both priorities this quarter.',
10801
10857
  * }
10802
10858
  */
10803
10859
  interface DesignGuidelineProperties {
@@ -11249,7 +11305,7 @@ interface EpicProperties {
11249
11305
  * persona will be able to do. Lifecycle-free: a statement either still
11250
11306
  * describes a real promise, or is superseded by a new one when the promise changes.
11251
11307
  *
11252
- * Pairs with `task` (UCS pattern P4 — story_task collapsed into task) via `task_implements_user_story`.
11308
+ * Pairs with `task` (UCS pattern P4, story_task collapsed into task) via `task_implements_user_story`.
11253
11309
  * One statement can have many tasks (re-implementation, per-platform variants);
11254
11310
  * each task carries its own lifecycle.
11255
11311
  *
@@ -13305,7 +13361,7 @@ interface A11yAuditProperties {
13305
13361
  * @example
13306
13362
  * const properties: A11yIssueProperties = {
13307
13363
  * severity: 'minor',
13308
- * wcag_criterion: '1.4.3 — Contrast (Minimum)',
13364
+ * wcag_criterion: '1.4.3: Contrast (Minimum)',
13309
13365
  * rule_id: 'dqr_nodes_no_null_title',
13310
13366
  * }
13311
13367
  */
@@ -13782,7 +13838,7 @@ interface KnowledgeBaseArticleProperties {
13782
13838
  * const properties: BrandAssetProperties = {
13783
13839
  * asset_type: 'logo',
13784
13840
  * url: 'https://example.com/doc',
13785
- * usage_rights: 'Internal use only — do not redistribute without written approval.',
13841
+ * usage_rights: 'Internal use only. Do not redistribute without written approval.',
13786
13842
  * }
13787
13843
  */
13788
13844
  interface BrandAssetProperties {
@@ -14221,7 +14277,7 @@ interface RoleProperties {
14221
14277
  *
14222
14278
  * Properties are minimal: identity, addressability, coordination. HR-shaped
14223
14279
  * fields (`seniority`, `employment_type`, `start_date`) are intentionally
14224
- * out of scope — they encode org-design opinions that vary wildly across
14280
+ * out of scope; they encode org-design opinions that vary wildly across
14225
14281
  * companies and have no bearing on product-graph reasoning. UPG is not
14226
14282
  * an HRIS.
14227
14283
  *
@@ -14475,7 +14531,7 @@ interface RiskRegisterProperties {
14475
14531
  * const properties: ChangeRequestProperties = {
14476
14532
  * change_type: 'scope',
14477
14533
  * priority: 'high',
14478
- * impact_assessment: 'Medium — affects onboarding success metric.',
14534
+ * impact_assessment: 'Medium: affects onboarding success metric.',
14479
14535
  * }
14480
14536
  */
14481
14537
  interface ChangeRequestProperties {
@@ -14877,6 +14933,8 @@ interface WorkflowTemplateProperties {
14877
14933
  checkpoint_enabled?: boolean;
14878
14934
  /** Whether a human approval step is required */
14879
14935
  human_in_loop?: boolean;
14936
+ /** Version label for this workflow template (e.g. "2.1") */
14937
+ version?: string;
14880
14938
  }
14881
14939
  /** Workflow run.
14882
14940
  *
@@ -14940,6 +14998,8 @@ interface AgentDefinitionProperties {
14940
14998
  multimodal?: boolean;
14941
14999
  /** Operational status of this agent definition */
14942
15000
  agent_status?: 'active' | 'disabled' | 'testing';
15001
+ /** Version label for this agent definition (e.g. "1.4.2") */
15002
+ version?: string;
14943
15003
  }
14944
15004
  /** Agent session.
14945
15005
  *
@@ -15251,6 +15311,8 @@ interface PartnershipProperties {
15251
15311
  risk_level?: UPGAssessment;
15252
15312
  /** Internal owner */
15253
15313
  owner?: string;
15314
+ /** Date the partnership became effective (ISO 8601) */
15315
+ start_date?: ISODate;
15254
15316
  }
15255
15317
  /** KeyResource.
15256
15318
  *
@@ -15558,7 +15620,7 @@ interface GrowthLoopProperties {
15558
15620
  *
15559
15621
  * @example
15560
15622
  * const properties: VariantProperties = {
15561
- * variant_name: 'B — simplified onboarding',
15623
+ * variant_name: 'B: simplified onboarding',
15562
15624
  * traffic_percentage: 42,
15563
15625
  * variant_status: 'active',
15564
15626
  * }
@@ -16641,7 +16703,7 @@ interface LocaleConfigProperties {
16641
16703
  * @example
16642
16704
  * const properties: CulturalAdaptationProperties = {
16643
16705
  * adaptation_type: 'content',
16644
- * rationale: 'Reduces support burden and lifts activation — both priorities this quarter.',
16706
+ * rationale: 'Reduces support burden and lifts activation, both priorities this quarter.',
16645
16707
  * }
16646
16708
  */
16647
16709
  interface CulturalAdaptationProperties {
@@ -16992,7 +17054,7 @@ interface WorkspaceProperties {
16992
17054
  /** Type-safe lookup from entity type string to its property interface.
16993
17055
  * Every active entity type has an entry. */
16994
17056
  interface UPGPropertyMap {
16995
- /** The product being built — root node of every product graph */
17057
+ /** The product being built: root node of every product graph */
16996
17058
  product: ProductProperties;
16997
17059
  /** A measurable outcome the product is working toward */
16998
17060
  outcome: OutcomeProperties;
@@ -17000,13 +17062,13 @@ interface UPGPropertyMap {
17000
17062
  objective: ObjectiveProperties;
17001
17063
  /** A quantifiable key result used to measure an objective */
17002
17064
  key_result: KeyResultProperties;
17003
- /** A tracked metric — present when a quantitative measure is defined */
17065
+ /** A tracked metric, present when a quantitative measure is defined */
17004
17066
  metric: MetricProperties;
17005
17067
  /** A point-in-time review of a metric's quality and fitness for purpose. */
17006
17068
  metric_quality_assessment: MetricQualityAssessmentProperties;
17007
17069
  /** The long-horizon vision statement for the product */
17008
17070
  vision: VisionProperties;
17009
- /** The mission statement — who is served and what core value is delivered */
17071
+ /** The mission statement: who is served and what core value is delivered */
17010
17072
  mission: MissionProperties;
17011
17073
  /** A strategic theme grouping related initiatives under a common direction */
17012
17074
  strategic_theme: StrategicThemeProperties;
@@ -17018,20 +17080,20 @@ interface UPGPropertyMap {
17018
17080
  value_stream: ValueStreamProperties;
17019
17081
  /** A durable strategic pillar spanning multi-year horizons */
17020
17082
  strategic_pillar: StrategicPillarProperties;
17021
- /** An assumption that underpins strategy or design — present when validation is being tracked */
17083
+ /** An assumption that underpins strategy or design, present when validation is being tracked */
17022
17084
  assumption: AssumptionProperties;
17023
- /** A decision record — strategic, product, engineering, or design */
17085
+ /** A decision record (strategic, product, engineering, or design) */
17024
17086
  decision: DecisionProperties;
17025
- /** A named limitation or boundary — resource, technical, regulatory,
17026
- * temporal, or compliance — that bounds product creation. Edge-defined. */
17087
+ /** A named limitation or boundary (resource, technical, regulatory,
17088
+ * temporal, or compliance) that bounds product creation. Edge-defined. */
17027
17089
  constraint: ConstraintProperties;
17028
17090
  /** A user persona representing a segment of people the product serves */
17029
17091
  persona: PersonaProperties;
17030
- /** A job-to-be-done — the progress a user is trying to make */
17092
+ /** A job-to-be-done: the progress a user is trying to make */
17031
17093
  job: JobProperties;
17032
17094
  /** A user need derived from research or synthesis */
17033
17095
  need: NeedProperties;
17034
- /** A desired outcome — the specific result a user wants from a job step */
17096
+ /** A desired outcome: the specific result a user wants from a job step */
17035
17097
  desired_outcome: DesiredOutcomeProperties;
17036
17098
  /** A discrete step within a job-to-be-done */
17037
17099
  job_step: JobStepProperties;
@@ -17039,21 +17101,21 @@ interface UPGPropertyMap {
17039
17101
  switching_cost: SwitchingCostProperties;
17040
17102
  /** A product opportunity identified from user needs or market gaps */
17041
17103
  opportunity: OpportunityProperties;
17042
- /** A proposed solution to an opportunity — present before commitment */
17104
+ /** A proposed solution to an opportunity, present before commitment */
17043
17105
  solution: SolutionProperties;
17044
17106
  /** A feasibility study assessing viability of a solution */
17045
17107
  feasibility_study: FeasibilityStudyProperties;
17046
17108
  /** A design sprint run to explore and test a solution space */
17047
17109
  design_sprint: DesignSprintProperties;
17048
- /** A testable belief — the canonical validation design artefact. */
17110
+ /** A testable belief: the canonical validation design artefact. */
17049
17111
  hypothesis: HypothesisProperties;
17050
- /** @deprecated since v0.4.0 — use `evidence` + `hypothesis_has_evidence` edge instead. */
17112
+ /** @deprecated since v0.4.0. Use `evidence` + `hypothesis_has_evidence` edge instead. */
17051
17113
  hypothesis_evidence: HypothesisEvidenceProperties;
17052
17114
  /** A general-purpose experiment entity (canonical-stable). Use `experiment_plan` + `experiment_run` for fine-grained plan/run separation. */
17053
17115
  experiment: ExperimentProperties;
17054
- /** Planning intent for a structured test of a hypothesis (UCS pattern P4 — work-unit). Pairs with `experiment_run`. */
17116
+ /** Planning intent for a structured test of a hypothesis (UCS pattern P4, work-unit). Pairs with `experiment_run`. */
17055
17117
  experiment_plan: ExperimentPlanProperties;
17056
- /** Execution evidence for a structured test of a hypothesis (UCS pattern P6 — event-occurrence). Pairs with `experiment_plan`. */
17118
+ /** Execution evidence for a structured test of a hypothesis (UCS pattern P6, event-occurrence). Pairs with `experiment_plan`. */
17057
17119
  experiment_run: ExperimentRunProperties;
17058
17120
  /** A learning captured from an experiment or research activity */
17059
17121
  learning: LearningProperties;
@@ -17063,7 +17125,7 @@ interface UPGPropertyMap {
17063
17125
  evidence: EvidenceProperties;
17064
17126
  /** A research plan outlining goals, methods, and participant criteria */
17065
17127
  research_plan: ResearchPlanProperties;
17066
- /** A competitor in the market — present when competitive tracking is active */
17128
+ /** A competitor in the market, present when competitive tracking is active */
17067
17129
  competitor: CompetitorProperties;
17068
17130
  /** A specific feature offered by a competitor */
17069
17131
  competitor_feature: CompetitorFeatureProperties;
@@ -17075,13 +17137,13 @@ interface UPGPropertyMap {
17075
17137
  competitive_analysis: CompetitiveAnalysisProperties;
17076
17138
  /** A dimension along which subjects are classified */
17077
17139
  classification_axis: ClassificationAxisProperties;
17078
- /** A value on a classification axis — one position in a taxonomy */
17140
+ /** A value on a classification axis: one position in a taxonomy */
17079
17141
  classification_value: ClassificationValueProperties;
17080
- /** A formal user research study — interview series, survey, usability test */
17142
+ /** A formal user research study (interview series, survey, usability test) */
17081
17143
  research_study: ResearchStudyProperties;
17082
- /** An insight synthesised from research — a meaningful pattern or finding */
17144
+ /** An insight synthesised from research: a meaningful pattern or finding */
17083
17145
  insight: InsightProperties;
17084
- /** A research participant — present when participant tracking is needed */
17146
+ /** A research participant, present when participant tracking is needed */
17085
17147
  participant: ParticipantProperties;
17086
17148
  /** A raw observation recorded during research */
17087
17149
  observation: ObservationProperties;
@@ -17113,7 +17175,7 @@ interface UPGPropertyMap {
17113
17175
  wireframe: WireframeProperties;
17114
17176
  /** A user flow showing task-level paths through the product */
17115
17177
  user_flow: UserFlowProperties;
17116
- /** A screen in the product UI — present when screen mapping is tracked */
17178
+ /** A screen in the product UI, present when screen mapping is tracked */
17117
17179
  screen: ScreenProperties;
17118
17180
  /** A specific UI state of a screen (empty, loading, error, etc.) */
17119
17181
  screen_state: ScreenStateProperties;
@@ -17123,33 +17185,33 @@ interface UPGPropertyMap {
17123
17185
  interaction_spec: InteractionSpecProperties;
17124
17186
  /** A reusable UI component in the design system */
17125
17187
  design_component: DesignComponentProperties;
17126
- /** A design token — a named value for colour, spacing, typography, etc. */
17188
+ /** A design token: a named value for colour, spacing, typography, etc. */
17127
17189
  design_token: DesignTokenProperties;
17128
- /** The design system itself — governance, tooling, and coverage metadata */
17190
+ /** The design system itself, covering governance, tooling, and coverage metadata */
17129
17191
  design_system: DesignSystemProperties;
17130
17192
  /** A recurring interaction or layout pattern documented in the design system */
17131
17193
  design_pattern: DesignPatternProperties;
17132
17194
  /** A design guideline stating how and when to apply a pattern or token */
17133
17195
  design_guideline: DesignGuidelineProperties;
17134
- /** The brand identity — values, personality, and positioning */
17196
+ /** The brand identity, covering values, personality, and positioning */
17135
17197
  brand_identity: BrandIdentityProperties;
17136
17198
  /** A specific brand colour with usage guidance */
17137
17199
  brand_colour: BrandColourProperties;
17138
- /** A brand typography pairing — typeface, scale, and usage rules */
17200
+ /** A brand typography pairing (typeface, scale, and usage rules) */
17139
17201
  brand_typography: BrandTypographyProperties;
17140
- /** The brand voice — tone, register, and writing principles */
17202
+ /** The brand voice: tone, register, and writing principles */
17141
17203
  brand_voice: BrandVoiceProperties;
17142
- /** A brand logo variant — full, icon, wordmark, etc. */
17204
+ /** A brand logo variant (full, icon, wordmark, etc.) */
17143
17205
  brand_logo: BrandLogoProperties;
17144
- /** Brand imagery guidelines — photography and illustration style */
17206
+ /** Brand imagery guidelines covering photography and illustration style */
17145
17207
  brand_imagery: BrandImageryProperties;
17146
17208
  /** A feature area grouping related features under a product section */
17147
17209
  feature_area: FeatureAreaProperties;
17148
- /** A product feature — a discrete unit of user-facing functionality */
17210
+ /** A product feature: a discrete unit of user-facing functionality */
17149
17211
  feature: FeatureProperties;
17150
17212
  /** An epic grouping related user stories under a deliverable theme */
17151
17213
  epic: EpicProperties;
17152
- /** The "As X, I want Y so Z" templated promise — a user story (UCS pattern P5 — templated-statement). Implemented by `task` via `task_implements_user_story`. */
17214
+ /** The "As X, I want Y so Z" templated promise: a user story (UCS pattern P5, templated-statement). Implemented by `task` via `task_implements_user_story`. */
17153
17215
  user_story: UserStoryProperties;
17154
17216
  /**
17155
17217
  * @deprecated since v0.4.0. story_task collapsed into task.
@@ -17158,15 +17220,15 @@ interface UPGPropertyMap {
17158
17220
  story_task: StoryTaskProperties;
17159
17221
  /** An acceptance criterion defining when a story or feature is complete */
17160
17222
  acceptance_criterion: AcceptanceCriterionProperties;
17161
- /** A product release — present when versioned delivery is tracked */
17223
+ /** A product release, present when versioned delivery is tracked */
17162
17224
  release: ReleaseProperties;
17163
17225
  /** A discrete task assigned to a person or team */
17164
17226
  task: TaskProperties;
17165
- /** A bug report — present when a defect is being tracked */
17227
+ /** A bug report, present when a defect is being tracked */
17166
17228
  bug: BugProperties;
17167
17229
  /** A product roadmap grouping features and themes over a planning horizon */
17168
17230
  roadmap: RoadmapProperties;
17169
- /** A single item on a roadmap — a feature, epic, or theme with timing */
17231
+ /** A single item on a roadmap: a feature, epic, or theme with timing */
17170
17232
  roadmap_item: RoadmapItemProperties;
17171
17233
  /** A thematic grouping used to cluster work on the roadmap */
17172
17234
  theme: ThemeProperties;
@@ -17180,31 +17242,31 @@ interface UPGPropertyMap {
17180
17242
  domain_event: DomainEventProperties;
17181
17243
  /** An API contract specifying the interface between services or clients */
17182
17244
  api_contract: ApiContractProperties;
17183
- /** A technical debt item — present when debt is being tracked for remediation */
17245
+ /** A technical debt item, present when debt is being tracked for remediation */
17184
17246
  technical_debt_item: TechnicalDebtItemProperties;
17185
17247
  /** A feature flag controlling runtime behaviour without deployment */
17186
17248
  feature_flag: FeatureFlagProperties;
17187
- /** A deployment record — present when a specific release was deployed */
17249
+ /** A deployment record, present when a specific release was deployed */
17188
17250
  deployment: DeploymentProperties;
17189
- /** A DDD aggregate — a cluster of domain objects with a consistency boundary */
17251
+ /** A DDD aggregate: a cluster of domain objects with a consistency boundary */
17190
17252
  aggregate: AggregateProperties;
17191
- /** A domain entity — an object with identity that changes over time */
17253
+ /** A domain entity: an object with identity that changes over time */
17192
17254
  domain_entity: DomainEntityProperties;
17193
- /** A value object — an immutable domain concept identified by its attributes */
17255
+ /** A value object: an immutable domain concept identified by its attributes */
17194
17256
  value_object: ValueObjectProperties;
17195
17257
  /** A command representing an intent to change system state */
17196
17258
  command: CommandProperties;
17197
- /** A read model — a query-optimised projection of domain state */
17259
+ /** A read model: a query-optimised projection of domain state */
17198
17260
  read_model: ReadModelProperties;
17199
- /** A specific API endpoint — present when endpoint-level tracking is needed */
17261
+ /** A specific API endpoint, present when endpoint-level tracking is needed */
17200
17262
  api_endpoint: ApiEndpointProperties;
17201
- /** A database schema — table structure, constraints, and migration status */
17263
+ /** A database schema (table structure, constraints, and migration status) */
17202
17264
  database_schema: DatabaseSchemaProperties;
17203
17265
  /** A message queue topic or channel */
17204
17266
  queue_topic: QueueTopicProperties;
17205
17267
  /** A build artifact produced by the CI pipeline */
17206
17268
  build_artifact: BuildArtifactProperties;
17207
- /** A code repository — present when repo-level tracking is needed */
17269
+ /** A code repository, present when repo-level tracking is needed */
17208
17270
  code_repository: CodeRepositoryProperties;
17209
17271
  /** A library dependency tracked for version and licence compliance */
17210
17272
  library_dependency: LibraryDependencyProperties;
@@ -17218,7 +17280,7 @@ interface UPGPropertyMap {
17218
17280
  investigation: InvestigationProperties;
17219
17281
  /** The root cause identified during an incident investigation */
17220
17282
  root_cause: RootCauseProperties;
17221
- /** A symptom observed during an incident — present before root cause is known */
17283
+ /** A symptom observed during an incident, present before root cause is known */
17222
17284
  symptom: SymptomProperties;
17223
17285
  /** A fix applied to resolve a bug or incident */
17224
17286
  fix: FixProperties;
@@ -17234,47 +17296,47 @@ interface UPGPropertyMap {
17234
17296
  cohort: CohortProperties;
17235
17297
  /** A behavioural segment defined by in-product actions */
17236
17298
  behavioral_segment: BehavioralSegmentProperties;
17237
- /** A growth loop — a self-reinforcing cycle that compounds user or revenue growth */
17299
+ /** A growth loop: a self-reinforcing cycle that compounds user or revenue growth */
17238
17300
  growth_loop: GrowthLoopProperties;
17239
17301
  /** A variant in an A/B or multivariate experiment */
17240
17302
  variant: VariantProperties;
17241
17303
  /** An attribution model defining how credit is assigned to acquisition channels */
17242
17304
  attribution_model: AttributionModelProperties;
17243
- /** The overall business model — present when BMC-level structure is tracked */
17305
+ /** The overall business model, present when BMC-level structure is tracked */
17244
17306
  business_model: BusinessModelProperties;
17245
- /** A value proposition — the core promise made to a customer segment */
17307
+ /** A value proposition: the core promise made to a customer segment */
17246
17308
  value_proposition: ValuePropositionProperties;
17247
- /** A revenue stream — a mechanism through which the product earns money */
17309
+ /** A revenue stream: a mechanism through which the product earns money */
17248
17310
  revenue_stream: RevenueStreamProperties;
17249
17311
  /** A pricing tier defining what a customer gets at a given price point */
17250
17312
  pricing_tier: PricingTierProperties;
17251
- /** The cost structure — fixed and variable costs underpinning the business model */
17313
+ /** The cost structure (fixed and variable costs underpinning the business model) */
17252
17314
  cost_structure: CostStructureProperties;
17253
- /** Unit economics — per-unit revenue, cost, and margin metrics */
17315
+ /** Unit economics: per-unit revenue, cost, and margin metrics */
17254
17316
  unit_economics: UnitEconomicsProperties;
17255
- /** A partnership — a strategic relationship with an external organisation */
17317
+ /** A partnership: a strategic relationship with an external organisation */
17256
17318
  partnership: PartnershipProperties;
17257
17319
  /** A key resource required to deliver value (people, IP, infrastructure) */
17258
17320
  key_resource: KeyResourceProperties;
17259
17321
  /** A key activity the business must perform to deliver its value proposition */
17260
17322
  key_activity: KeyActivityProperties;
17261
- /** A customer relationship type — how the business interacts with a segment */
17323
+ /** A customer relationship type: how the business interacts with a segment */
17262
17324
  customer_relationship: CustomerRelationshipProperties;
17263
17325
  /** A distribution channel through which value reaches the customer */
17264
17326
  distribution_channel: DistributionChannelProperties;
17265
- /** The GTM strategy — present when go-to-market planning is formalised */
17327
+ /** The GTM strategy, present when go-to-market planning is formalised */
17266
17328
  gtm_strategy: GtmStrategyProperties;
17267
17329
  /** An ideal customer profile defining the best-fit buyer */
17268
17330
  ideal_customer_profile: IdealCustomerProfileProperties;
17269
17331
  /** A positioning statement defining where the product sits in the market */
17270
17332
  positioning: PositioningProperties;
17271
- /** A messaging framework — headlines, value pillars, and proof points */
17333
+ /** A messaging framework (headlines, value pillars, and proof points) */
17272
17334
  messaging: MessagingProperties;
17273
- /** A product launch — present when a coordinated launch is being planned */
17335
+ /** A product launch, present when a coordinated launch is being planned */
17274
17336
  launch: LaunchProperties;
17275
17337
  /** A content strategy defining themes, formats, and channels */
17276
17338
  content_strategy: ContentStrategyProperties;
17277
- /** A sales motion — the repeatable process used to close deals */
17339
+ /** A sales motion: the repeatable process used to close deals */
17278
17340
  sales_motion: SalesMotionProperties;
17279
17341
  /** A competitive battle card for use by the sales team */
17280
17342
  competitive_battle_card: CompetitiveBattleCardProperties;
@@ -17288,17 +17350,17 @@ interface UPGPropertyMap {
17288
17350
  rebuttal: RebuttalProperties;
17289
17351
  /** A proof point substantiating a claim in messaging or sales */
17290
17352
  proof_point: ProofPointProperties;
17291
- /** A team — a group of people working on a shared scope */
17353
+ /** A team: a group of people working on a shared scope */
17292
17354
  team: TeamProperties;
17293
- /** A role — a function or responsibility within the team or organisation */
17355
+ /** A role: a function or responsibility within the team or organisation */
17294
17356
  role: RoleProperties;
17295
17357
  /** A stakeholder with interest in or influence over the product */
17296
17358
  stakeholder: StakeholderProperties;
17297
- /** A named, accountable individual — distinct from `stakeholder` (interested party) and `role` (responsibility slot) */
17359
+ /** A named, accountable individual, distinct from `stakeholder` (interested party) and `role` (responsibility slot) */
17298
17360
  person: PersonProperties;
17299
17361
  /** An OKR set at the team level */
17300
17362
  team_okr: TeamOkrProperties;
17301
- /** A retrospective — present when team reflections are being tracked */
17363
+ /** A retrospective, present when team reflections are being tracked */
17302
17364
  retrospective: RetrospectiveProperties;
17303
17365
  /** A cross-team dependency that may block delivery */
17304
17366
  dependency: DependencyProperties;
@@ -17314,13 +17376,13 @@ interface UPGPropertyMap {
17314
17376
  data_source: DataSourceProperties;
17315
17377
  /** An event schema defining the structure of a tracked event */
17316
17378
  event_schema: EventSchemaProperties;
17317
- /** A dashboard — present when a reporting surface is being tracked */
17379
+ /** A dashboard, present when a reporting surface is being tracked */
17318
17380
  dashboard: DashboardProperties;
17319
- /** A data model — entity relationships and schema structure */
17381
+ /** A data model covering entity relationships and schema structure */
17320
17382
  data_model: DataModelProperties;
17321
17383
  /** A data quality rule defining expectations on a dataset or field */
17322
17384
  data_quality_rule: DataQualityRuleProperties;
17323
- /** A data product — a curated, discoverable dataset made available to consumers */
17385
+ /** A data product: a curated, discoverable dataset made available to consumers */
17324
17386
  data_product: DataProductProperties;
17325
17387
  /** A data pipeline moving or transforming data between systems */
17326
17388
  data_pipeline: DataPipelineProperties;
@@ -17330,13 +17392,13 @@ interface UPGPropertyMap {
17330
17392
  glossary_term: GlossaryTermProperties;
17331
17393
  /** A data domain grouping related data assets under a common owner */
17332
17394
  data_domain: DataDomainProperties;
17333
- /** A report — a scheduled or on-demand analytical output */
17395
+ /** A report: a scheduled or on-demand analytical output */
17334
17396
  report: ReportProperties;
17335
- /** A content piece — blog post, video, podcast, whitepaper, or case study */
17397
+ /** A content piece (blog post, video, podcast, whitepaper, or case study) */
17336
17398
  content_piece: ContentPieceProperties;
17337
17399
  /** A knowledge base article for customers, developers, or internal teams */
17338
17400
  knowledge_base_article: KnowledgeBaseArticleProperties;
17339
- /** A brand asset — logo, illustration, photo, or video */
17401
+ /** A brand asset (logo, illustration, photo, or video) */
17340
17402
  brand_asset: BrandAssetProperties;
17341
17403
  /** A prompt template used for AI-assisted workflows */
17342
17404
  prompt_template: PromptTemplateProperties;
@@ -17346,21 +17408,21 @@ interface UPGPropertyMap {
17346
17408
  content_theme: ContentThemeProperties;
17347
17409
  /** A documentation template defining structure for a class of documents */
17348
17410
  documentation_template: DocumentationTemplateProperties;
17349
- /** A document entity — provenance container linking to a source file */
17411
+ /** A document entity: provenance container linking to a source file */
17350
17412
  document: DocumentProperties;
17351
- /** A legal entity — company, subsidiary, or contracting party */
17413
+ /** A legal entity (company, subsidiary, or contracting party) */
17352
17414
  legal_entity: LegalEntityProperties;
17353
- /** An intellectual property asset — patent, trademark, copyright, or trade secret */
17415
+ /** An intellectual property asset (patent, trademark, copyright, or trade secret) */
17354
17416
  ip_asset: IpAssetProperties;
17355
17417
  /** A contract between the company and an external party */
17356
17418
  contract: ContractProperties;
17357
- /** A specific clause within a contract — present when clause-level tracking is needed */
17419
+ /** A specific clause within a contract, present when clause-level tracking is needed */
17358
17420
  contract_clause: ContractClauseProperties;
17359
- /** A privacy policy document — present when policy tracking is active */
17421
+ /** A privacy policy document, present when policy tracking is active */
17360
17422
  privacy_policy: PrivacyPolicyProperties;
17361
17423
  /** A compliance requirement from a regulation, standard, or customer contract */
17362
17424
  compliance_requirement: ComplianceRequirementProperties;
17363
- /** A risk — a potential event with negative impact on the product or business */
17425
+ /** A risk: a potential event with negative impact on the product or business */
17364
17426
  risk: RiskProperties;
17365
17427
  /** A data contract defining agreed schema and SLAs between producer and consumer */
17366
17428
  data_contract: DataContractProperties;
@@ -17368,15 +17430,15 @@ interface UPGPropertyMap {
17368
17430
  audit_log_policy: AuditLogPolicyProperties;
17369
17431
  /** A compliance framework being adhered to (SOC 2, ISO 27001, GDPR, etc.) */
17370
17432
  compliance_framework: ComplianceFrameworkProperties;
17371
- /** A security audit — present when a formal review has been conducted */
17433
+ /** A security audit, present when a formal review has been conducted */
17372
17434
  security_audit: SecurityAuditProperties;
17373
- /** A service level indicator — a specific measurement of service behaviour */
17435
+ /** A service level indicator: a specific measurement of service behaviour */
17374
17436
  service_level_indicator: ServiceLevelIndicatorProperties;
17375
- /** A service level objective — a target range for an SLI */
17437
+ /** A service level objective: a target range for an SLI */
17376
17438
  service_level_objective: ServiceLevelObjectiveProperties;
17377
- /** An error budget derived from an SLO — present when reliability is tracked */
17439
+ /** An error budget derived from an SLO, present when reliability is tracked */
17378
17440
  error_budget: ErrorBudgetProperties;
17379
- /** An incident — a production event requiring response */
17441
+ /** An incident: a production event requiring response */
17380
17442
  incident: IncidentProperties;
17381
17443
  /** A postmortem written after an incident is resolved */
17382
17444
  postmortem: PostmortemProperties;
@@ -17386,25 +17448,25 @@ interface UPGPropertyMap {
17386
17448
  monitor: MonitorProperties;
17387
17449
  /** An alert rule defining when a monitor fires a notification */
17388
17450
  alert_rule: AlertRuleProperties;
17389
- /** A CI pipeline configuration — build, test, and deploy stages */
17451
+ /** A CI pipeline configuration (build, test, and deploy stages) */
17390
17452
  ci_pipeline: CiPipelineProperties;
17391
17453
  /** A release strategy defining how changes are deployed (blue-green, canary, etc.) */
17392
17454
  release_strategy: ReleaseStrategyProperties;
17393
17455
  /** An on-call rotation assigning responders to incidents by schedule */
17394
17456
  on_call_rotation: OnCallRotationProperties;
17395
- /** An infrastructure component — server, container, network resource, etc. */
17457
+ /** An infrastructure component (server, container, network resource, etc.) */
17396
17458
  infrastructure_component: InfrastructureComponentProperties;
17397
17459
  /** A threat model documenting attack surfaces and adversary assumptions */
17398
17460
  threat_model: ThreatModelProperties;
17399
17461
  /** A specific threat identified within a threat model */
17400
17462
  threat: ThreatProperties;
17401
- /** A vulnerability — a known weakness that could be exploited */
17463
+ /** A vulnerability: a known weakness that could be exploited */
17402
17464
  vulnerability: VulnerabilityProperties;
17403
17465
  /** A security control mitigating one or more threats */
17404
17466
  security_control: SecurityControlProperties;
17405
17467
  /** A security policy governing how the system or team handles a security domain */
17406
17468
  security_policy: SecurityPolicyProperties;
17407
- /** A penetration test — present when external security testing is tracked */
17469
+ /** A penetration test, present when external security testing is tracked */
17408
17470
  penetration_test: PenetrationTestProperties;
17409
17471
  /** A security review of a feature, service, or architecture change */
17410
17472
  security_review: SecurityReviewProperties;
@@ -17416,7 +17478,7 @@ interface UPGPropertyMap {
17416
17478
  a11y_standard: A11yStandardProperties;
17417
17479
  /** A specific accessibility guideline derived from a standard */
17418
17480
  a11y_guideline: A11yGuidelineProperties;
17419
- /** An accessibility audit — present when a formal review has been run */
17481
+ /** An accessibility audit, present when a formal review has been run */
17420
17482
  a11y_audit: A11yAuditProperties;
17421
17483
  /** An accessibility issue found during audit or user research */
17422
17484
  a11y_issue: A11yIssueProperties;
@@ -17424,9 +17486,9 @@ interface UPGPropertyMap {
17424
17486
  a11y_annotation: A11yAnnotationProperties;
17425
17487
  /** A test suite grouping related test cases */
17426
17488
  test_suite: TestSuiteProperties;
17427
- /** A test case — a single scenario with expected inputs and outputs */
17489
+ /** A test case: a single scenario with expected inputs and outputs */
17428
17490
  test_case: TestCaseProperties;
17429
- /** A QA session — present when exploratory testing is being tracked */
17491
+ /** A QA session, present when exploratory testing is being tracked */
17430
17492
  qa_session: QaSessionProperties;
17431
17493
  /** A regression test ensuring previously fixed behaviour does not break */
17432
17494
  regression_test: RegressionTestProperties;
@@ -17434,33 +17496,33 @@ interface UPGPropertyMap {
17434
17496
  test_coverage_report: TestCoverageReportProperties;
17435
17497
  /** A test environment configuration used to run a test suite */
17436
17498
  test_environment: TestEnvironmentProperties;
17437
- /** The result of a test run — pass, fail, or flaky */
17499
+ /** The result of a test run (pass, fail, or flaky) */
17438
17500
  test_result: TestResultProperties;
17439
- /** A feedback programme — present when structured customer feedback is collected */
17501
+ /** A feedback programme, present when structured customer feedback is collected */
17440
17502
  feedback_program: FeedbackProgramProperties;
17441
17503
  /** A feature request submitted by a customer or prospect */
17442
17504
  feature_request: FeatureRequestProperties;
17443
- /** A vote on a feature request — present when voting is tracked */
17505
+ /** A vote on a feature request, present when voting is tracked */
17444
17506
  feedback_vote: FeedbackVoteProperties;
17445
- /** An NPS campaign — present when Net Promoter Score is being measured */
17507
+ /** An NPS campaign, present when Net Promoter Score is being measured */
17446
17508
  nps_campaign: NpsCampaignProperties;
17447
- /** A user advisory board — a formal group of customers shaping product direction */
17509
+ /** A user advisory board: a formal group of customers shaping product direction */
17448
17510
  user_advisory_board: UserAdvisoryBoardProperties;
17449
- /** A beta programme — present when pre-release access is being managed */
17511
+ /** A beta programme, present when pre-release access is being managed */
17450
17512
  beta_program: BetaProgramProperties;
17451
17513
  /** A feedback theme clustering related requests or complaints */
17452
17514
  feedback_theme: FeedbackThemeProperties;
17453
- /** The pricing strategy — present when pricing approach is formalised */
17515
+ /** The pricing strategy, present when pricing approach is formalised */
17454
17516
  pricing_strategy: PricingStrategyProperties;
17455
17517
  /** A discount strategy defining when and how discounts are applied */
17456
17518
  discount_strategy: DiscountStrategyProperties;
17457
- /** A trial configuration — present when a free trial or pilot is offered */
17519
+ /** A trial configuration, present when a free trial or pilot is offered */
17458
17520
  trial_config: TrialConfigProperties;
17459
- /** A paywall — the gate between free and paid access */
17521
+ /** A paywall: the gate between free and paid access */
17460
17522
  paywall: PaywallProperties;
17461
17523
  /** An AI model used by or integrated into the product */
17462
17524
  ai_model: AiModelProperties;
17463
- /** A versioned prompt — present when prompt engineering is tracked */
17525
+ /** A versioned prompt, present when prompt engineering is tracked */
17464
17526
  prompt_version: PromptVersionProperties;
17465
17527
  /** An evaluation benchmark defining pass/fail criteria for a model */
17466
17528
  eval_benchmark: EvalBenchmarkProperties;
@@ -17468,9 +17530,9 @@ interface UPGPropertyMap {
17468
17530
  eval_run: EvalRunProperties;
17469
17531
  /** An AI cost tracker monitoring token usage and spend */
17470
17532
  ai_cost_tracker: AiCostTrackerProperties;
17471
- /** A hallucination report — present when model output accuracy is audited */
17533
+ /** A hallucination report, present when model output accuracy is audited */
17472
17534
  hallucination_report: HallucinationReportProperties;
17473
- /** An AI guardrail — a safety or quality constraint applied to model output */
17535
+ /** An AI guardrail: a safety or quality constraint applied to model output */
17474
17536
  ai_guardrail: AiGuardrailProperties;
17475
17537
  /** A model comparison evaluating two or more models on the same benchmark */
17476
17538
  model_comparison: ModelComparisonProperties;
@@ -17482,17 +17544,17 @@ interface UPGPropertyMap {
17482
17544
  ai_trace: AiTraceProperties;
17483
17545
  /** A workflow template defining a reusable multi-step process */
17484
17546
  workflow_template: WorkflowTemplateProperties;
17485
- /** A workflow run — a live execution of a workflow template */
17547
+ /** A workflow run: a live execution of a workflow template */
17486
17548
  workflow_run: WorkflowRunProperties;
17487
- /** An agent definition — the configuration and capabilities of an AI agent */
17549
+ /** An agent definition: the configuration and capabilities of an AI agent */
17488
17550
  agent_definition: AgentDefinitionProperties;
17489
- /** An agent session — a single interaction run by an agent */
17551
+ /** An agent session: a single interaction run by an agent */
17490
17552
  agent_session: AgentSessionProperties;
17491
17553
  /** A review gate requiring human approval before a workflow continues */
17492
17554
  review_gate: ReviewGateProperties;
17493
- /** An approval record — the decision made at a review gate */
17555
+ /** An approval record: the decision made at a review gate */
17494
17556
  approval_record: ApprovalRecordProperties;
17495
- /** A skill available to an agent — a named, callable capability */
17557
+ /** A skill available to an agent: a named, callable capability */
17496
17558
  agent_skill: AgentSkillProperties;
17497
17559
  /** A hook executed before or after a workflow step */
17498
17560
  agent_hook: AgentHookProperties;
@@ -17500,67 +17562,67 @@ interface UPGPropertyMap {
17500
17562
  workflow_artifact: WorkflowArtifactProperties;
17501
17563
  /** A task assigned to an agent within a workflow run */
17502
17564
  agent_task: AgentTaskProperties;
17503
- /** An organisation — the company or entity that owns a portfolio of products */
17565
+ /** An organisation: the company or entity that owns a portfolio of products */
17504
17566
  organization: OrganizationProperties;
17505
17567
  /** A portfolio grouping multiple products under a common strategy */
17506
17568
  portfolio: PortfolioProperties;
17507
- /** A product area — a named section of the product with its own ownership */
17569
+ /** A product area: a named section of the product with its own ownership */
17508
17570
  product_area: ProductAreaProperties;
17509
- /** A workspace — the collaboration boundary for a team or organisation */
17571
+ /** A workspace: the collaboration boundary for a team or organisation */
17510
17572
  workspace: WorkspaceProperties;
17511
- /** An account — a company or organisation in the CRM */
17573
+ /** An account: a company or organisation in the CRM */
17512
17574
  account: AccountProperties;
17513
- /** A contact — an individual person at an account */
17575
+ /** A contact: an individual person at an account */
17514
17576
  contact: ContactProperties;
17515
- /** A lead — an unqualified prospect entering the sales funnel */
17577
+ /** A lead: an unqualified prospect entering the sales funnel */
17516
17578
  lead: LeadProperties;
17517
- /** A deal — a qualified sales opportunity being pursued */
17579
+ /** A deal: a qualified sales opportunity being pursued */
17518
17580
  deal: DealProperties;
17519
- /** The sales pipeline — present when pipeline-level metadata is tracked */
17581
+ /** The sales pipeline, present when pipeline-level metadata is tracked */
17520
17582
  pipeline_sales: PipelineSalesProperties;
17521
17583
  /** A stage within the sales pipeline */
17522
17584
  pipeline_stage: PipelineStageProperties;
17523
17585
  /** A quote document sent to a prospect */
17524
17586
  quote_document: QuoteDocumentProperties;
17525
- /** A subscription — a recurring revenue relationship with a customer */
17587
+ /** A subscription: a recurring revenue relationship with a customer */
17526
17588
  subscription: SubscriptionProperties;
17527
17589
  /** An invoice issued to a customer */
17528
17590
  invoice: InvoiceProperties;
17529
- /** A sales forecast — present when revenue prediction is tracked */
17591
+ /** A sales forecast, present when revenue prediction is tracked */
17530
17592
  forecast: ForecastProperties;
17531
17593
  /** A programme grouping related projects under a strategic objective */
17532
17594
  program: ProgramProperties;
17533
- /** A project — a time-boxed initiative with a defined scope */
17595
+ /** A project: a time-boxed initiative with a defined scope */
17534
17596
  project: ProjectProperties;
17535
17597
  /** A milestone marking a significant point in a project or release */
17536
17598
  milestone: MilestoneProperties;
17537
17599
  /** A risk register capturing identified risks and mitigations */
17538
17600
  risk_register: RiskRegisterProperties;
17539
- /** A change request — present when a formal change process is followed */
17601
+ /** A change request, present when a formal change process is followed */
17540
17602
  change_request: ChangeRequestProperties;
17541
- /** A deliverable — a tangible output committed to a stakeholder */
17603
+ /** A deliverable: a tangible output committed to a stakeholder */
17542
17604
  deliverable: DeliverableProperties;
17543
17605
  /** A resource allocation mapping team capacity to projects */
17544
17606
  resource_allocation: ResourceAllocationProperties;
17545
17607
  /** A status report summarising progress against plan */
17546
17608
  status_report: StatusReportProperties;
17547
- /** The marketing strategy — present when marketing is formalised at the programme level */
17609
+ /** The marketing strategy, present when marketing is formalised at the programme level */
17548
17610
  marketing_strategy: MarketingStrategyProperties;
17549
- /** A marketing channel — a medium used to reach the target audience */
17611
+ /** A marketing channel: a medium used to reach the target audience */
17550
17612
  marketing_channel: MarketingChannelProperties;
17551
- /** A marketing campaign plan — present when a campaign is being planned */
17613
+ /** A marketing campaign plan, present when a campaign is being planned */
17552
17614
  marketing_campaign_plan: MarketingCampaignPlanProperties;
17553
- /** An email sequence — a series of automated emails sent to a segment */
17615
+ /** An email sequence: a series of automated emails sent to a segment */
17554
17616
  email_sequence: EmailSequenceProperties;
17555
- /** A social post — present when social content is being planned or tracked */
17617
+ /** A social post, present when social content is being planned or tracked */
17556
17618
  social_post: SocialPostProperties;
17557
17619
  /** An SEO keyword being targeted in content or paid search */
17558
17620
  seo_keyword: SeoKeywordProperties;
17559
- /** An ad creative — copy and visual used in a paid media placement */
17621
+ /** An ad creative: copy and visual used in a paid media placement */
17560
17622
  ad_creative: AdCreativeProperties;
17561
- /** A press release — present when media outreach is being tracked */
17623
+ /** A press release, present when media outreach is being tracked */
17562
17624
  press_release: PressReleaseProperties;
17563
- /** An event — physical or virtual — being planned or tracked */
17625
+ /** An event (physical or virtual) being planned or tracked */
17564
17626
  event: EventProperties;
17565
17627
  /** A community initiative building engagement with users or prospects */
17566
17628
  community_initiative: CommunityInitiativeProperties;
@@ -17570,9 +17632,9 @@ interface UPGPropertyMap {
17570
17632
  customer_feedback: CustomerFeedbackProperties;
17571
17633
  /** A churn reason explaining why a customer cancelled */
17572
17634
  churn_reason: ChurnReasonProperties;
17573
- /** A customer health score — present when account health is tracked */
17635
+ /** A customer health score, present when account health is tracked */
17574
17636
  customer_health_score: CustomerHealthScoreProperties;
17575
- /** A playbook — a documented response to a customer scenario */
17637
+ /** A playbook: a documented response to a customer scenario */
17576
17638
  playbook: PlaybookProperties;
17577
17639
  /** A service level agreement defining commitments to a customer */
17578
17640
  service_level_agreement: ServiceLevelAgreementProperties;
@@ -17584,39 +17646,39 @@ interface UPGPropertyMap {
17584
17646
  success_milestone: SuccessMilestoneProperties;
17585
17647
  /** A service blueprint mapping frontstage and backstage activities */
17586
17648
  service_blueprint: ServiceBlueprintProperties;
17587
- /** A locale — a language and region combination supported by the product */
17649
+ /** A locale: a language and region combination supported by the product */
17588
17650
  locale: LocaleProperties;
17589
17651
  /** A translation key mapping a string identifier to localised text */
17590
17652
  translation_key: TranslationKeyProperties;
17591
- /** A translation bundle — a collection of keys for a single locale */
17653
+ /** A translation bundle: a collection of keys for a single locale */
17592
17654
  translation_bundle: TranslationBundleProperties;
17593
17655
  /** A locale configuration defining date, number, and currency formatting */
17594
17656
  locale_config: LocaleConfigProperties;
17595
- /** A cultural adaptation — a locale-specific change beyond string translation */
17657
+ /** A cultural adaptation: a locale-specific change beyond string translation */
17596
17658
  cultural_adaptation: CulturalAdaptationProperties;
17597
17659
  /** A regional pricing configuration adjusting price for a locale */
17598
17660
  regional_pricing: RegionalPricingProperties;
17599
- /** An education programme — a structured curriculum for customer learning */
17661
+ /** An education programme: a structured curriculum for customer learning */
17600
17662
  education_program: EducationProgramProperties;
17601
17663
  /** A tutorial walking a user through a feature or workflow */
17602
17664
  tutorial: TutorialProperties;
17603
- /** A walkthrough — an in-product guided tour */
17665
+ /** A walkthrough: an in-product guided tour */
17604
17666
  walkthrough: WalkthroughProperties;
17605
- /** A webinar — a live or recorded educational session */
17667
+ /** A webinar: a live or recorded educational session */
17606
17668
  webinar: WebinarProperties;
17607
17669
  /** A certification awarded upon completing a learning path */
17608
17670
  certification: CertificationProperties;
17609
- /** A help video — a short screencast explaining a feature */
17671
+ /** A help video: a short screencast explaining a feature */
17610
17672
  help_video: HelpVideoProperties;
17611
- /** A learning path — a sequenced collection of tutorials, videos, and assessments */
17673
+ /** A learning path: a sequenced collection of tutorials, videos, and assessments */
17612
17674
  learning_path: LearningPathProperties;
17613
17675
  /** A partner programme defining tiers, benefits, and requirements */
17614
17676
  partner_program: PartnerProgramProperties;
17615
- /** A partner tier within a programme — Bronze, Silver, Gold, etc. */
17677
+ /** A partner tier within a programme (Bronze, Silver, Gold, etc.) */
17616
17678
  partner_tier: PartnerTierProperties;
17617
- /** The API ecosystem — developer community and integration surface */
17679
+ /** The API ecosystem: developer community and integration surface */
17618
17680
  api_ecosystem: ApiEcosystemProperties;
17619
- /** A marketplace listing — present when the product is listed on a platform */
17681
+ /** A marketplace listing, present when the product is listed on a platform */
17620
17682
  marketplace_listing: MarketplaceListingProperties;
17621
17683
  /** A developer portal providing documentation and sandbox access */
17622
17684
  developer_portal: DeveloperPortalProperties;
@@ -17625,16 +17687,16 @@ interface UPGPropertyMap {
17625
17687
  /** A partner revenue share arrangement defining commercial terms */
17626
17688
  partner_revenue_share: PartnerRevenueShareProperties;
17627
17689
  }
17628
- /** A fully typed UPG node — `UPGBaseNode` narrowed to a specific entity type.
17690
+ /** A fully typed UPG node. `UPGBaseNode` narrowed to a specific entity type.
17629
17691
  *
17630
17692
  * `T` is an entity-type literal from `UPGPropertyMap`. When supplied, it
17631
17693
  * constrains `type` to that literal and narrows `properties` to the matching
17632
- * `*Properties` interface. When omitted, `T` defaults to the full union — the
17694
+ * `*Properties` interface. When omitted, `T` defaults to the full union: the
17633
17695
  * node accepts any entity type and `properties` widens to the union of all
17634
17696
  * domain property shapes.
17635
17697
  *
17636
17698
  * @example
17637
- * // Narrowed by T — `type` is locked to 'feature' and `properties` to
17699
+ * // Narrowed by T: `type` is locked to 'feature' and `properties` to
17638
17700
  * // FeatureProperties.
17639
17701
  * const featureNode: UPGNode<'feature'> = {
17640
17702
  * id: 'feat-1',
@@ -17644,7 +17706,7 @@ interface UPGPropertyMap {
17644
17706
  * }
17645
17707
  *
17646
17708
  * @example
17647
- * // A different instantiation of T — the generic lets a single helper
17709
+ * // A different instantiation of T: the generic lets a single helper
17648
17710
  * // signature return the correctly typed node for any entity type.
17649
17711
  * const personaNode: UPGNode<'persona'> = {
17650
17712
  * id: 'p-1',
@@ -17659,7 +17721,7 @@ type UPGNode<T extends keyof UPGPropertyMap = keyof UPGPropertyMap> = UPGBaseNod
17659
17721
  };
17660
17722
 
17661
17723
  /**
17662
- * UPG Property Registry — Runtime schema for entity types
17724
+ * UPG Property Registry: Runtime schema for entity types
17663
17725
  *
17664
17726
  * AUTO-GENERATED by scripts/generate-property-registry.ts
17665
17727
  * Do not edit manually. Run: npx tsx scripts/generate-property-registry.ts
@@ -17671,9 +17733,9 @@ interface PropertyDefinition {
17671
17733
  type: 'string' | 'number' | 'boolean' | 'string[]' | 'object';
17672
17734
  description?: string;
17673
17735
  enum?: string[];
17674
- /** For object-typed fields — nested property shapes. */
17736
+ /** For object-typed fields: nested property shapes. */
17675
17737
  properties?: Record<string, PropertyDefinition>;
17676
- /** For object-typed fields — required keys within `properties`. */
17738
+ /** For object-typed fields: required keys within `properties`. */
17677
17739
  required?: string[];
17678
17740
  }
17679
17741
  type PropertySchema = Record<string, PropertyDefinition>;
@@ -17689,7 +17751,7 @@ declare const UPG_PROPERTY_SCHEMA: Record<string, PropertySchema>;
17689
17751
  declare function getPropertySchema(entityType: string): PropertySchema | undefined;
17690
17752
 
17691
17753
  /**
17692
- * UPG Labels — framework-vocabulary Rosetta Stone. Each entity type maps to a
17754
+ * UPG Labels: framework-vocabulary Rosetta Stone. Each entity type maps to a
17693
17755
  * canonical label, alt labels, and framework-specific labels. Answers "what
17694
17756
  * does framework X call this concept?"
17695
17757
  *
@@ -17708,7 +17770,7 @@ interface UPGTypeLabel {
17708
17770
  designations?: Record<string, string>;
17709
17771
  }
17710
17772
  /**
17711
- * The complete Rosetta Stone — one UPGTypeLabel for every active type.
17773
+ * The complete Rosetta Stone: one UPGTypeLabel for every active type.
17712
17774
  *
17713
17775
  * Assembly logic:
17714
17776
  * 1. If a type has a PRIORITY_LABELS entry → use it (richest framework_labels)
@@ -17751,11 +17813,11 @@ declare function resolveLabel(entityType: string, frameworkId?: string, designat
17751
17813
  * aliases['problem'] // → 'need' (Lean Canvas label → canonical)
17752
17814
  */
17753
17815
  declare function buildTypeAliases(): Record<string, string>;
17754
- /** Pre-built alias map — import this instead of calling buildTypeAliases() repeatedly */
17816
+ /** Pre-built alias map. Import this instead of calling buildTypeAliases() repeatedly. */
17755
17817
  declare const UPG_TYPE_ALIASES: Record<string, string>;
17756
17818
 
17757
17819
  /**
17758
- * UPG Intelligence Conditions — structured, machine-evaluable graph predicates.
17820
+ * UPG Intelligence Conditions: structured, machine-evaluable graph predicates.
17759
17821
  *
17760
17822
  * Three check types: `EntityCheck` (count by criteria), `RelationshipCheck`
17761
17823
  * (edge existence/count), `BenchmarkCheck` (compare against stage benchmark).
@@ -17902,7 +17964,7 @@ interface StepBase {
17902
17964
  phase: string;
17903
17965
  /** Human-readable label for this step */
17904
17966
  name?: string;
17905
- /** Optional prompt shown to the user at this step. Structure only — no UI hints. */
17967
+ /** Optional prompt shown to the user at this step. Structure only, no UI hints. */
17906
17968
  prompt_hint?: string;
17907
17969
  /** Machine-evaluable condition that must hold before advancing to the next step */
17908
17970
  transition_condition?: IntelligenceCondition;
@@ -17918,7 +17980,7 @@ interface DomainGuideStep extends StepBase {
17918
17980
  /** Step that applies a named framework. */
17919
17981
  interface FrameworkInvocationStep extends StepBase {
17920
17982
  kind: 'framework';
17921
- /** ID of the framework to apply — matches an entry in UPG_FRAMEWORKS */
17983
+ /** ID of the framework to apply (matches an entry in UPG_FRAMEWORKS) */
17922
17984
  framework_id: string;
17923
17985
  }
17924
17986
  /** Step that creates entities of an explicit, fixed list of types. */
@@ -17930,7 +17992,7 @@ interface EntitySequenceStep extends StepBase {
17930
17992
  /** Step that chains into a nested playbook or technique. */
17931
17993
  interface SubSequenceStep extends StepBase {
17932
17994
  kind: 'sub_sequence';
17933
- /** ID of the nested sequence — `playbook:*` or `technique:*` */
17995
+ /** ID of the nested sequence: `playbook:*` or `technique:*` */
17934
17996
  sub_sequence_id: string;
17935
17997
  }
17936
17998
  /**
@@ -18016,7 +18078,7 @@ type UPGRegionShape =
18016
18078
  /**
18017
18079
  * The graph role an entity plays *within* its super-domain.
18018
18080
  *
18019
- * Purely structural — independent of any rendering concept.
18081
+ * Purely structural, independent of any rendering concept.
18020
18082
  */
18021
18083
  type UPGRegionEntityRole = 'anchor' | 'root' | 'hub' | 'container' | 'leaf';
18022
18084
  /** A single entity's membership in a super-domain. */
@@ -18052,20 +18114,20 @@ interface UPGAnchorEntity {
18052
18114
  inbound_cross_edge_count: number;
18053
18115
  }
18054
18116
  /**
18055
- * A super-domain region — a coherent rollup of 1–N atomic domains.
18117
+ * A super-domain region: a coherent rollup of 1-N atomic domains.
18056
18118
  *
18057
18119
  * Topology only: regions describe what is connected to what, not how it
18058
18120
  * renders. Rendering concerns live in Entopo (`apps/entopo/src/regions/`).
18059
18121
  *
18060
- * @see {@link UPG_REGIONS} — the canonical catalog
18061
- * @see MENTAL-MODEL.md — regions as the static "place" primitive
18122
+ * @see {@link UPG_REGIONS} for the canonical catalog
18123
+ * @see MENTAL-MODEL.md for regions as the static "place" primitive
18062
18124
  */
18063
18125
  interface UPGRegion {
18064
18126
  /** Machine-readable region id (snake_case) */
18065
18127
  id: string;
18066
18128
  /** Human-readable name */
18067
18129
  label: string;
18068
- /** Numeric order — matches prose file prefix (01–10) */
18130
+ /** Numeric order, matches prose file prefix (01-10) */
18069
18131
  order: number;
18070
18132
  /** Shape archetype */
18071
18133
  shape: UPGRegionShape;
@@ -18108,7 +18170,7 @@ interface UPGPlaybook {
18108
18170
  version: string;
18109
18171
  /** One-sentence description */
18110
18172
  description: string;
18111
- /** REQUIRED — the region this playbook anchors */
18173
+ /** REQUIRED: the region this playbook anchors */
18112
18174
  region: UPGRegionId;
18113
18175
  /**
18114
18176
  * Marks the canonical playbook for this region. Exactly one canonical per
@@ -18116,7 +18178,7 @@ interface UPGPlaybook {
18116
18178
  */
18117
18179
  is_canonical?: boolean;
18118
18180
  /**
18119
- * Optional — the framework this playbook is anchored on. References
18181
+ * Optional: the framework this playbook is anchored on. References
18120
18182
  * `UPGFramework.id`. Specialised playbooks are typically framework-anchored;
18121
18183
  * the canonical playbook usually is not.
18122
18184
  */
@@ -18127,7 +18189,7 @@ interface UPGPlaybook {
18127
18189
  */
18128
18190
  target_anchor_entity?: string;
18129
18191
  /**
18130
- * Ordered creation sequence — typically one `DomainGuideStep` per atomic
18192
+ * Ordered creation sequence, typically one `DomainGuideStep` per atomic
18131
18193
  * domain composed by the region, OR a framework-driven sequence when
18132
18194
  * `framework_id` is set.
18133
18195
  */
@@ -18142,15 +18204,15 @@ interface PlaybookBinding {
18142
18204
  surface: SurfaceId;
18143
18205
  /** Identifier the runtime maps to a component or handler */
18144
18206
  renderer: string;
18145
- /** Per-step renderer overrides — keyed by `Step.order` */
18207
+ /** Per-step renderer overrides, keyed by `Step.order` */
18146
18208
  step_renderers?: Record<number, string>;
18147
18209
  /** Surface-specific step kinds the runtime handles beyond the canonical ones */
18148
18210
  custom_step_kinds?: readonly string[];
18149
- /** Lifecycle hook id — runtime-resolved, fires when a run starts */
18211
+ /** Lifecycle hook id: runtime-resolved, fires when a run starts */
18150
18212
  on_start?: string;
18151
- /** Lifecycle hook id — runtime-resolved, fires after each step */
18213
+ /** Lifecycle hook id: runtime-resolved, fires after each step */
18152
18214
  on_step_complete?: string;
18153
- /** Lifecycle hook id — runtime-resolved, fires when a run completes */
18215
+ /** Lifecycle hook id: runtime-resolved, fires when a run completes */
18154
18216
  on_run_complete?: string;
18155
18217
  }
18156
18218
  /**
@@ -18205,7 +18267,7 @@ interface PlaybookRuntime {
18205
18267
  }
18206
18268
 
18207
18269
  /**
18208
- * UPG Lenses — role-specific projections combining vocabulary, visibility,
18270
+ * UPG Lenses: role-specific projections combining vocabulary, visibility,
18209
18271
  * workflow, and intelligence. Applied on read.
18210
18272
  * https://unifiedproductgraph.org/spec | MIT
18211
18273
  */
@@ -18215,24 +18277,24 @@ interface PlaybookRuntime {
18215
18277
  * layer. Surfaces a message when a trigger condition evaluates to `true`
18216
18278
  * over the current product graph.
18217
18279
  *
18218
- * Runtimes evaluate `structured_condition` — the machine-readable form.
18280
+ * Runtimes evaluate `structured_condition`, the machine-readable form.
18219
18281
  * `condition` is a human-readable shadow kept for documentation, prompt
18220
18282
  * engineering, debug output, and grep-ability. The two should describe
18221
18283
  * the same intent; when they diverge (rare), `structured_condition` is
18222
18284
  * the source of truth.
18223
18285
  *
18224
18286
  * @example
18225
- * // A simple "missing thing" nudge — fires when the product has no outcomes.
18287
+ * // A simple "missing thing" nudge that fires when the product has no outcomes.
18226
18288
  * const noOutcomes: UPGLensIntelligencePrompt = {
18227
18289
  * condition: 'outcomes.length === 0',
18228
18290
  * structured_condition: {
18229
18291
  * check: { type: 'entity_count', entity_type: 'outcome', comparison: 'zero' },
18230
18292
  * },
18231
- * message: 'No outcomes defined yet. Start with what success looks like — what measurable result should this product drive?',
18293
+ * message: 'No outcomes defined yet. Start with what success looks like: what measurable result should this product drive?',
18232
18294
  * }
18233
18295
  *
18234
18296
  * @example
18235
- * // A compound nudge — features exist but no hypotheses validate them.
18297
+ * // A compound nudge: features exist but no hypotheses validate them.
18236
18298
  * const featuresWithoutHypotheses: UPGLensIntelligencePrompt = {
18237
18299
  * condition: 'features.length > 0 && hypotheses.length === 0',
18238
18300
  * structured_condition: {
@@ -18247,12 +18309,12 @@ interface PlaybookRuntime {
18247
18309
  */
18248
18310
  interface UPGLensIntelligencePrompt {
18249
18311
  /**
18250
- * Human-readable shadow of `structured_condition`. Kept as documentary —
18312
+ * Human-readable shadow of `structured_condition`. Kept as documentary reference,
18251
18313
  * useful for prompt engineering, debug output, and search. Not evaluated
18252
18314
  * at runtime; if the two ever diverge, `structured_condition` wins.
18253
18315
  */
18254
18316
  condition: string;
18255
- /** Machine-evaluable condition — when to surface this prompt. */
18317
+ /** Machine-evaluable condition: when to surface this prompt. */
18256
18318
  structured_condition: IntelligenceCondition;
18257
18319
  /** The message to show, in the lens's voice */
18258
18320
  message: string;
@@ -18264,7 +18326,7 @@ interface UPGLensIntelligencePrompt {
18264
18326
  * A lens combines four orthogonal layers: vocabulary (which labels to
18265
18327
  * use), visibility (which domains to show), workflow (which guided
18266
18328
  * sequence to follow), and intelligence (which nudges to surface). The
18267
- * `.upg` file format is lens-unaware — lenses apply on read only.
18329
+ * `.upg` file format is lens-unaware; lenses apply on read only.
18268
18330
  *
18269
18331
  * @example
18270
18332
  * const productLens: UPGLens = {
@@ -18313,7 +18375,7 @@ interface UPGLens {
18313
18375
  * mental model. Structure lives in the playbook registry; the lens owns
18314
18376
  * only presentation (labels, visibility, intelligence).
18315
18377
  *
18316
- * Lenses without a 1:1 region playbook (e.g. `product`, `full` — both
18378
+ * Lenses without a 1:1 region playbook (e.g. `product`, `full`, both
18317
18379
  * cross-region) leave this field unset. Resolved via `getLensPlaybook`.
18318
18380
  *
18319
18381
  * Renamed from `workflow_id` (workflows → playbooks + techniques).
@@ -18392,13 +18454,13 @@ declare function getLensIds(): string[];
18392
18454
  * @example
18393
18455
  * const lens = getLens('design')!
18394
18456
  * const playbook = getLensPlaybook(lens)
18395
- * // playbook?.id matches lens.playbook_id — the bootstrap path for the
18457
+ * // playbook?.id matches lens.playbook_id, the bootstrap path for the
18396
18458
  * // experience_design_brand region.
18397
18459
  */
18398
18460
  declare function getLensPlaybook(lens: UPGLens): UPGPlaybook | undefined;
18399
18461
 
18400
18462
  /**
18401
- * UPG Domain Rings — 7 concentric groupings of the 36 UPG domains.
18463
+ * UPG Domain Rings: 7 concentric groupings of the 36 UPG domains.
18402
18464
  *
18403
18465
  * Defines the ring assignment for every domain and the canonical ring metadata.
18404
18466
  *
@@ -18442,7 +18504,7 @@ declare function getRingForDomain(domainId: string): UPGDomainRing | undefined;
18442
18504
  declare function getDomainsInRing(ringId: string): string[];
18443
18505
 
18444
18506
  /**
18445
- * UPG Domain Usage Guides — operational knowledge for MCP agents.
18507
+ * UPG Domain Usage Guides: operational knowledge for MCP agents.
18446
18508
  *
18447
18509
  * Each guide gives a domain's anchor entity, creation sequence, named
18448
18510
  * patterns (entity + edge chains), required cross-domain bridges, and
@@ -18450,7 +18512,7 @@ declare function getDomainsInRing(ringId: string): string[];
18450
18512
  */
18451
18513
 
18452
18514
  interface UPGDomainPattern {
18453
- /** Human-readable pattern name — no jargon, spell out acronyms */
18515
+ /** Human-readable pattern name (no jargon, spell out acronyms) */
18454
18516
  name: string;
18455
18517
  /** What this pattern accomplishes */
18456
18518
  description: string;
@@ -18469,16 +18531,16 @@ interface UPGDomainBridge {
18469
18531
  }
18470
18532
  /**
18471
18533
  * A common mistake agents make in a domain. Structured so MCP
18472
- * consumers can proactively surface violations — "you created a feature
18473
- * without a persona, that's an anti-pattern" — instead of only rendering
18534
+ * consumers can proactively surface violations (e.g. "you created a feature
18535
+ * without a persona, that's an anti-pattern") instead of only rendering
18474
18536
  * prose. Migrated from `anti_patterns: string[]`; existing copy lives in
18475
18537
  * `description`, and `name` / `affected_entity` / `remediation` are
18476
18538
  * optional for backward migration but preferred for new entries.
18477
18539
  */
18478
18540
  interface UPGAntiPattern {
18479
- /** Short title — enables compact display and cross-guide search. */
18541
+ /** Short title. Enables compact display and cross-guide search. */
18480
18542
  name?: string;
18481
- /** The anti-pattern itself — prose explanation of the mistake. */
18543
+ /** The anti-pattern itself: prose explanation of the mistake. */
18482
18544
  description: string;
18483
18545
  /** Which entity type is typically involved in this anti-pattern. */
18484
18546
  affected_entity?: UPGEntityType;
@@ -18488,7 +18550,7 @@ interface UPGAntiPattern {
18488
18550
  interface UPGDomainUsageGuide {
18489
18551
  /** Domain ID this guide covers */
18490
18552
  domain_id: UPGDomainId;
18491
- /** The entity you create first — everything else hangs from it */
18553
+ /** The entity you create first. Everything else hangs from it. */
18492
18554
  anchor_entity: UPGEntityType;
18493
18555
  /** Recommended creation sequence */
18494
18556
  creation_sequence: UPGEntityType[];
@@ -18513,7 +18575,7 @@ declare const UPG_DOMAIN_GUIDES: readonly UPGDomainUsageGuide[];
18513
18575
  */
18514
18576
  declare function getGuideForDomain(domainId: UPGDomainId | string): UPGDomainUsageGuide | undefined;
18515
18577
  /**
18516
- * Get the anchor entity for a domain — the entity you create first.
18578
+ * Get the anchor entity for a domain (the entity you create first).
18517
18579
  *
18518
18580
  * @example
18519
18581
  * getAnchorEntity('user') // → 'persona'
@@ -18528,7 +18590,7 @@ declare function getAnchorEntity(domainId: UPGDomainId | string): UPGEntityType
18528
18590
  * const all = getAntiPatterns()
18529
18591
  * // all[0].domain === 'user'
18530
18592
  * // all[0].anti_pattern.name === 'persona_without_jobs' (example)
18531
- * // all.length — one entry per anti-pattern across all guides
18593
+ * // all.length // one entry per anti-pattern across all guides
18532
18594
  */
18533
18595
  declare function getAntiPatterns(): Array<{
18534
18596
  domain: UPGDomainId;
@@ -18547,8 +18609,8 @@ declare function getAntiPatterns(): Array<{
18547
18609
  * against free-form strings. Each variant carries enough metadata to render
18548
18610
  * the citation inline without further lookup.
18549
18611
  *
18550
- * @example { kind: 'book', citation: 'The Lean Startup — Eric Ries (2011), ch. 7' }
18551
- * @example { kind: 'practitioner', attribution: 'Teresa Torres — Continuous Discovery Habits' }
18612
+ * @example { kind: 'book', citation: 'The Lean Startup, Eric Ries (2011), ch. 7' }
18613
+ * @example { kind: 'practitioner', attribution: 'Teresa Torres, Continuous Discovery Habits' }
18552
18614
  * @example { kind: 'industry_practice', category: 'devops' }
18553
18615
  * @example { kind: 'fundamental' }
18554
18616
  */
@@ -18572,7 +18634,7 @@ type UPGBenchmarkSource =
18572
18634
  kind: 'industry_practice';
18573
18635
  category: string;
18574
18636
  }
18575
- /** Definitional — true by the spec's own construction, not externally sourced. */
18637
+ /** Definitional: true by the spec's own construction, not externally sourced. */
18576
18638
  | {
18577
18639
  kind: 'fundamental';
18578
18640
  };
@@ -18632,7 +18694,7 @@ interface RatioBenchmark {
18632
18694
  numerator_type: UPGEntityType | UPGEntityType[];
18633
18695
  /** Entity type(s) forming the denominator of the ratio */
18634
18696
  denominator_type: UPGEntityType | UPGEntityType[];
18635
- /** Minimum acceptable ratio value — below this signals an imbalance */
18697
+ /** Minimum acceptable ratio value. Below this signals an imbalance. */
18636
18698
  expected_min: number;
18637
18699
  /** Stages where this ratio is meaningful and should be evaluated */
18638
18700
  stages: UPGProductStage[];
@@ -18669,8 +18731,8 @@ interface DomainActivation {
18669
18731
  *
18670
18732
  * Benchmark shape: see `CountBenchmark` in `./types.ts`.
18671
18733
  *
18672
- * @see ./types.ts — `CountBenchmark`, `StageRange`, `UPG_PRODUCT_STAGES`
18673
- * @see ../intelligence.ts — health scoring consumer
18734
+ * @see ./types.ts `CountBenchmark`, `StageRange`, `UPG_PRODUCT_STAGES`
18735
+ * @see ../intelligence.ts health scoring consumer
18674
18736
  * https://unifiedproductgraph.org/spec | MIT
18675
18737
  */
18676
18738
 
@@ -18682,7 +18744,7 @@ declare const UPG_COUNT_BENCHMARKS: CountBenchmark[];
18682
18744
  *
18683
18745
  * Encodes wisdom like "each persona should have at least 2 jobs" (JTBD) or
18684
18746
  * "each hypothesis should produce at least one learning" (Lean Startup).
18685
- * Relationship benchmarks are stage-scoped — a persona doesn't need 2 jobs
18747
+ * Relationship benchmarks are stage-scoped: a persona doesn't need 2 jobs
18686
18748
  * at `concept`, but does by `build`.
18687
18749
  *
18688
18750
  * Consumers:
@@ -18691,8 +18753,8 @@ declare const UPG_COUNT_BENCHMARKS: CountBenchmark[];
18691
18753
  *
18692
18754
  * Benchmark shape: see `RelationshipBenchmark` in `./types.ts`.
18693
18755
  *
18694
- * @see ./types.ts — `RelationshipBenchmark`
18695
- * @see ../intelligence.ts — audit consumer
18756
+ * @see ./types.ts `RelationshipBenchmark`
18757
+ * @see ../intelligence.ts audit consumer
18696
18758
  * https://unifiedproductgraph.org/spec | MIT
18697
18759
  */
18698
18760
 
@@ -18716,8 +18778,8 @@ declare const UPG_RELATIONSHIP_BENCHMARKS: RelationshipBenchmark[];
18716
18778
  *
18717
18779
  * Benchmark shape: see `RatioBenchmark` in `./types.ts`.
18718
18780
  *
18719
- * @see ./types.ts — `RatioBenchmark`
18720
- * @see ../intelligence.ts — ratio audit consumer
18781
+ * @see ./types.ts `RatioBenchmark`
18782
+ * @see ../intelligence.ts ratio audit consumer
18721
18783
  * https://unifiedproductgraph.org/spec | MIT
18722
18784
  */
18723
18785
 
@@ -18737,16 +18799,16 @@ declare const UPG_RATIO_BENCHMARKS: RatioBenchmark[];
18737
18799
  *
18738
18800
  * Benchmark shape: see `DomainActivation` in `./types.ts`.
18739
18801
  *
18740
- * @see ./types.ts — `DomainActivation`
18741
- * @see ../../registry/domains.ts — canonical domain registry
18742
- * @see ../intelligence.ts — domain-activation audit consumer
18802
+ * @see ./types.ts `DomainActivation`
18803
+ * @see ../../registry/domains.ts canonical domain registry
18804
+ * @see ../intelligence.ts domain-activation audit consumer
18743
18805
  * https://unifiedproductgraph.org/spec | MIT
18744
18806
  */
18745
18807
 
18746
18808
  declare const UPG_DOMAIN_ACTIVATION: DomainActivation[];
18747
18809
 
18748
18810
  /**
18749
- * benchmarks/ — Product management wisdom as structured data.
18811
+ * benchmarks/ Product management wisdom as structured data.
18750
18812
  *
18751
18813
  * Encodes expected entity counts, relationships, ratios, and domain activation
18752
18814
  * thresholds per product stage. All 9 stages populated.
@@ -18775,15 +18837,15 @@ declare function getBenchmark(entityType: UPGEntityType | string, stage: UPGProd
18775
18837
  declare function getBenchmarksByDomain(domain: UPGDomainId | string): CountBenchmark[];
18776
18838
 
18777
18839
  /**
18778
- * UPG Curated Anti-Patterns — cross-domain reference set.
18840
+ * UPG Curated Anti-Patterns: cross-domain reference set.
18779
18841
  *
18780
18842
  * Each entry pairs a memorable name with a machine-evaluable
18781
18843
  * `IntelligenceCondition`, the stages it fires in, a "why it matters" line,
18782
18844
  * and a remediation hint.
18783
18845
  *
18784
18846
  * Distinct from `UPGAntiPattern` in `domain-guides.ts`:
18785
- * - `UPGAntiPattern` (per-domain) — guidance for MCP agents working *inside* a domain.
18786
- * - `UPGCuratedAntiPattern` (this file) — cross-cutting patterns evaluated against the *whole* graph.
18847
+ * - `UPGAntiPattern` (per-domain): guidance for MCP agents working *inside* a domain.
18848
+ * - `UPGCuratedAntiPattern` (this file): cross-cutting patterns evaluated against the *whole* graph.
18787
18849
  *
18788
18850
  * Adding one: append to `UPG_ANTI_PATTERNS`. Integrity tests validate id
18789
18851
  * uniqueness, condition well-formedness, and stage/severity vocab. Cite
@@ -18809,7 +18871,7 @@ type UPGAntiPatternSeverity = 'high' | 'medium' | 'low';
18809
18871
  * {
18810
18872
  * id: 'features-without-hypotheses',
18811
18873
  * name: 'Features without hypotheses',
18812
- * description: 'The graph has features but no hypotheses — work is being scoped without a stated belief about why it should work.',
18874
+ * description: 'The graph has features but no hypotheses. Work is being scoped without a stated belief about why it should work.',
18813
18875
  * structured_condition: { operator: 'and', checks: [
18814
18876
  * { check: { type: 'entity_count', entity_type: 'feature', comparison: 'nonzero' } },
18815
18877
  * { check: { type: 'entity_count', entity_type: 'hypothesis', comparison: 'zero' } },
@@ -18822,7 +18884,7 @@ type UPGAntiPatternSeverity = 'high' | 'medium' | 'low';
18822
18884
  */
18823
18885
  interface UPGCuratedAntiPattern {
18824
18886
  /**
18825
- * Stable slug — kebab-case, unique within `UPG_ANTI_PATTERNS`.
18887
+ * Stable slug: kebab-case, unique within `UPG_ANTI_PATTERNS`.
18826
18888
  * Surfaced as URL fragment on the `/intelligence` site page; never rename
18827
18889
  * once published (rename = breaking link surface).
18828
18890
  */
@@ -18853,7 +18915,7 @@ interface UPGCuratedAntiPattern {
18853
18915
  * "competitors-missing" warnings during `concept`).
18854
18916
  */
18855
18917
  stages: readonly UPGProductStage[];
18856
- /** Severity tier — see `UPGAntiPatternSeverity`. */
18918
+ /** Severity tier. See `UPGAntiPatternSeverity`. */
18857
18919
  severity: UPGAntiPatternSeverity;
18858
18920
  /**
18859
18921
  * Optional citation for the pattern's origin (a book, practitioner,
@@ -18940,9 +19002,9 @@ interface AntiPatternInputs {
18940
19002
  /** Nodes with zero in-edges AND zero out-edges. */
18941
19003
  orphanCount: number;
18942
19004
  /**
18943
- * Active product stage — used to filter `UPG_ANTI_PATTERNS[i].stages[]`.
19005
+ * Active product stage. Used to filter `UPG_ANTI_PATTERNS[i].stages[]`.
18944
19006
  * If undefined, the evaluator runs all patterns regardless of stage gating
18945
- * (safer default — surface everything when stage is unknown).
19007
+ * (safer default: surface everything when stage is unknown).
18946
19008
  */
18947
19009
  productStage?: UPGProductStage;
18948
19010
  }
@@ -18957,7 +19019,7 @@ interface AntiPatternViolation {
18957
19019
  anti_pattern_id: string;
18958
19020
  name: string;
18959
19021
  severity: UPGAntiPatternSeverity;
18960
- /** Entity-type strings the catalog references. Phase 1 — types, not ids. */
19022
+ /** Entity-type strings the catalog references. Phase 1: types, not ids. */
18961
19023
  target_entities: string[];
18962
19024
  description: string;
18963
19025
  why_it_matters: string;
@@ -18974,7 +19036,7 @@ interface EvaluateAntiPatternsOptions {
18974
19036
  * Evaluate the curated anti-pattern catalog against a graph's pre-computed
18975
19037
  * stats. Returns the violations, sorted high → medium → low, then by id asc.
18976
19038
  *
18977
- * @param inputs The pre-computed graph stats — see `AntiPatternInputs`.
19039
+ * @param inputs The pre-computed graph stats (see `AntiPatternInputs`).
18978
19040
  * @param options Optional filters: `severity`, `anti_pattern_ids` subset.
18979
19041
  *
18980
19042
  * @example
@@ -19027,15 +19089,15 @@ declare function isCanonicalProductStage(value: unknown): value is UPGProductSta
19027
19089
  /**
19028
19090
  * Result of a soft-coercion attempt on a product `stage` value.
19029
19091
  *
19030
- * - `canonical` — the canonical UPGProductStage to use, or `undefined` when
19092
+ * - `canonical`: the canonical UPGProductStage to use, or `undefined` when
19031
19093
  * the input was unrecognised (no entry in the coercion map AND not already
19032
19094
  * canonical). Callers can choose to fall back to a default (typically
19033
19095
  * `'concept'`) or surface the unknown value.
19034
- * - `originalValue` — the raw input, for warning messages and audit trails.
19035
- * - `wasCoerced` — `true` if the input was a known legacy value that was
19096
+ * - `originalValue`: the raw input, for warning messages and audit trails.
19097
+ * - `wasCoerced`: `true` if the input was a known legacy value that was
19036
19098
  * mapped to a canonical equivalent. `false` if the input was already
19037
19099
  * canonical or unrecognised.
19038
- * - `wasUnknown` — `true` if the input was non-canonical AND not in the
19100
+ * - `wasUnknown`: `true` if the input was non-canonical AND not in the
19039
19101
  * coercion map. Callers should fall back to a default and log loudly.
19040
19102
  */
19041
19103
  interface ProductStageCoercion {
@@ -19089,13 +19151,13 @@ declare function validateProductStageStrict(value: unknown): string | null;
19089
19151
  * discovery-validation-hypothesis-cycle → build-measure-learn
19090
19152
  *
19091
19153
  * Every existing v0.2.x workflow maps here; cross-region lens workflows
19092
- * (`product-journey`, `full-product-journey`) were dropped — their content
19154
+ * (`product-journey`, `full-product-journey`) were dropped; their content
19093
19155
  * is already covered by the 10 canonical region playbooks.
19094
19156
  */
19095
19157
 
19096
19158
  declare const STRATEGY_OUTCOMES_PLAYBOOK: UPGPlaybook;
19097
19159
  /**
19098
- * Canonical users_needs playbook — net-new authored content per Q.C of the
19160
+ * Canonical users_needs playbook: net-new authored content per Q.C of the
19099
19161
  * decision doc. Persona has 25 inbound cross-edges; the spec's gravitational
19100
19162
  * centre. Skeleton-only is not acceptable here.
19101
19163
  */
@@ -19133,7 +19195,7 @@ declare const OPERATIONS_TEAM_RITUALS_PLAYBOOK: UPGPlaybook;
19133
19195
  declare const UPG_PLAYBOOKS: readonly UPGPlaybook[];
19134
19196
 
19135
19197
  /**
19136
- * playbooks/ — UPG Playbook public API.
19198
+ * playbooks/: UPG Playbook public API.
19137
19199
  *
19138
19200
  * Exports: `UPGPlaybook`, `PlaybookRuntime`, `PlaybookFilter`, `PlaybookRun`,
19139
19201
  * `PlaybookBinding`, `UPG_PLAYBOOKS`, and the lookup helpers
@@ -19148,12 +19210,12 @@ declare function getPlaybookById(id: string): UPGPlaybook | undefined;
19148
19210
  /**
19149
19211
  * Return the single canonical playbook for a region (the "start here" path).
19150
19212
  * Returns `null` when the region has no canonical playbook (W1 invariant
19151
- * violation — caught by `audit-playbook-coverage.ts`).
19213
+ * violation, caught by `audit-playbook-coverage.ts`).
19152
19214
  */
19153
19215
  declare function getCanonicalPlaybookForRegion(region: UPGRegionId): UPGPlaybook | null;
19154
19216
  /**
19155
19217
  * Return every playbook (canonical + specialised) anchored at a region.
19156
- * Order is the canonical `UPG_PLAYBOOKS` order — canonical entry first by
19218
+ * Order is the canonical `UPG_PLAYBOOKS` order, canonical entry first by
19157
19219
  * convention (catalog authoring discipline).
19158
19220
  */
19159
19221
  declare function getPlaybooksForRegion(region: UPGRegionId): readonly UPGPlaybook[];
@@ -19191,13 +19253,13 @@ interface FrameworkSlot {
19191
19253
  /** Explanation of what this slot represents in the framework */
19192
19254
  description?: string;
19193
19255
  }
19194
- /** Where the framework came from — attribution and licensing */
19256
+ /** Where the framework came from: attribution and licensing */
19195
19257
  interface FrameworkOrigin {
19196
19258
  /** Whether the framework is from academia, a practitioner, the community, or original to UPG */
19197
19259
  type: 'academic' | 'practitioner' | 'community' | 'custom';
19198
19260
  /** Human-readable attribution (e.g. "Sean Ellis", "Marty Cagan", "Teresa Torres") */
19199
19261
  attribution?: string;
19200
- /** Provenance narrative — how the framework came about (e.g. "Published in Business Model Generation") */
19262
+ /** Provenance narrative: how the framework came about (e.g. "Published in Business Model Generation") */
19201
19263
  description?: string;
19202
19264
  /** URL to the original source or publication */
19203
19265
  url?: string;
@@ -19259,12 +19321,12 @@ interface FrameworkConstant {
19259
19321
  properties: Record<string, unknown>;
19260
19322
  }
19261
19323
  /**
19262
- * Everything the framework needs from the graph's data layer — which entity
19324
+ * Everything the framework needs from the graph's data layer: which entity
19263
19325
  * types play which roles, which properties each type must carry under the
19264
19326
  * lens, and any computed or scaffolded constants.
19265
19327
  *
19266
19328
  * @example
19267
- * // RICE — scores a feature on reach, impact, confidence, effort.
19329
+ * // RICE: scores a feature on reach, impact, confidence, effort.
19268
19330
  * const riceData: FrameworkDataSpec = {
19269
19331
  * entity_types: [
19270
19332
  * { type: 'feature', role: 'item', min_count: 1 },
@@ -19300,12 +19362,12 @@ interface FrameworkDataSpec {
19300
19362
  * domain-specific fields on top of canonical entities (RICE adds
19301
19363
  * `reach`/`impact`/`confidence`/`effort` to a feature; Kano adds
19302
19364
  * `functional_response`/`dysfunctional_response`). These fields are NOT
19303
- * universal to the entity — they live inside the framework context.
19365
+ * universal to the entity; they live inside the framework context.
19304
19366
  *
19305
19367
  * Consumers must read framework-introduced properties from this spec, not
19306
19368
  * from `UPG_PROPERTY_SCHEMA`. Renderers merge both when displaying an
19307
- * entity under a framework. See `src/ARCHITECTURE.md` —
19308
- * "Framework Properties — Lens-Scoped Fields".
19369
+ * entity under a framework. See `src/ARCHITECTURE.md`,
19370
+ * "Framework Properties: Lens-Scoped Fields".
19309
19371
  */
19310
19372
  required_properties: Record<string, FrameworkPropertyRequirement[]>;
19311
19373
  /** Properties that are derived from other properties via expressions */
@@ -19374,15 +19436,15 @@ interface NamedGroup {
19374
19436
  interface FrameworkStructureSpec {
19375
19437
  /** The visual / topological pattern (tree, table, matrix, etc.) */
19376
19438
  pattern: StructurePattern;
19377
- /** Tree levels — only used when pattern is 'tree' */
19439
+ /** Tree levels (only used when pattern is 'tree') */
19378
19440
  levels?: FrameworkLevel[];
19379
19441
  /** Edge types used to connect entities in this framework */
19380
19442
  edge_types?: string[];
19381
- /** Matrix slots — only used when pattern is 'matrix' */
19443
+ /** Matrix slots (only used when pattern is 'matrix') */
19382
19444
  slots?: MatrixSlot[];
19383
- /** Funnel stages — only used when pattern is 'funnel' */
19445
+ /** Funnel stages (only used when pattern is 'funnel') */
19384
19446
  stages?: FunnelStage[];
19385
- /** Named groups — only used when pattern is 'collection' */
19447
+ /** Named groups (only used when pattern is 'collection') */
19386
19448
  groups?: NamedGroup[];
19387
19449
  }
19388
19450
  /** A column definition for table-layout frameworks */
@@ -19457,7 +19519,7 @@ interface FrameworkPresentationSpec {
19457
19519
  card_fields?: string[];
19458
19520
  /** Whether tree branches can be collapsed */
19459
19521
  collapsible?: boolean;
19460
- /** Custom colour map — keys are values of the colour_by dimension, values are CSS colours */
19522
+ /** Custom colour map: keys are values of the colour_by dimension, values are CSS colours */
19461
19523
  colour_map?: Record<string, string>;
19462
19524
  }
19463
19525
  /** One step in a guided walkthrough of how to use a framework */
@@ -19490,11 +19552,11 @@ interface FrameworkEducation {
19490
19552
  * A UPG Framework is a declarative, config-driven lens that structures
19491
19553
  * UPG graph data into a well-known product management pattern.
19492
19554
  *
19493
- * Frameworks are pure data — no code. The rendering engine reads the
19555
+ * Frameworks are pure data; no code. The rendering engine reads the
19494
19556
  * framework definition and produces the appropriate UI.
19495
19557
  *
19496
19558
  * @example
19497
- * // Abbreviated RICE definition — shows the layer split (data / structure
19559
+ * // Abbreviated RICE definition, showing the layer split (data / structure
19498
19560
  * // / presentation / education). Real definitions live in
19499
19561
  * // `src/frameworks/definitions/`.
19500
19562
  * const riceFramework: UPGFramework = {
@@ -19570,19 +19632,19 @@ interface UPGFramework {
19570
19632
  /** ID of a parent framework this one extends */
19571
19633
  extends?: string;
19572
19634
  /**
19573
- * The approaches this framework serves — many-to-many. Each value is a
19635
+ * The approaches this framework serves (many-to-many). Each value is a
19574
19636
  * `UPGApproachId` (`'plan' | 'inspect' | 'prioritise' | 'trace' | 'reflect'`).
19575
- * Optional — partial coverage is by design; adding tags later is additive.
19637
+ * Optional: partial coverage is by design; adding tags later is additive.
19576
19638
  *
19577
19639
  * Type-erased to `string[]` to avoid a circular import with
19578
19640
  * `approaches/types.ts`. Conceptually `readonly UPGApproachId[]`.
19579
19641
  *
19580
- * @see MENTAL-MODEL.md — approach × framework relationship
19642
+ * @see MENTAL-MODEL.md, approach × framework relationship
19581
19643
  */
19582
19644
  approach_ids?: readonly string[];
19583
19645
  }
19584
19646
  /**
19585
- * Lightweight framework metadata — the identity + origin subset of UPGFramework.
19647
+ * Lightweight framework metadata: the identity + origin subset of UPGFramework.
19586
19648
  *
19587
19649
  * Use this type for catalogue listings, site data, and anywhere that needs
19588
19650
  * framework identity without the full data/structure/presentation/education layers.
@@ -19610,7 +19672,7 @@ interface UPGFrameworkMeta {
19610
19672
  }
19611
19673
 
19612
19674
  /**
19613
- * UPG Approach primitive — the cognitive *path of arrival* to a region.
19675
+ * UPG Approach primitive: the cognitive *path of arrival* to a region.
19614
19676
  *
19615
19677
  * Five canonical approaches: Plan, Inspect, Prioritise, Trace, Reflect.
19616
19678
  * The catalog is closed. New techniques land as frameworks under existing
@@ -19621,7 +19683,7 @@ interface UPGFrameworkMeta {
19621
19683
  */
19622
19684
 
19623
19685
  /**
19624
- * The five canonical approach ids. Closed catalog — adding a sixth is a
19686
+ * The five canonical approach ids. Closed catalog: adding a sixth is a
19625
19687
  * coordinated breaking-shape change.
19626
19688
  *
19627
19689
  * Source of truth for `UPGFramework.approach_ids` and the MCP tool dispatch
@@ -19632,17 +19694,17 @@ type UPGApproachId = 'plan' | 'inspect' | 'prioritise' | 'trace' | 'reflect';
19632
19694
  * A definition record describing a cognitive engagement category exposed as
19633
19695
  * a verb-led MCP tool (`plan` / `inspect` / `prioritise` / `trace` / `reflect`).
19634
19696
  *
19635
- * Today these ship as definition lookups — the MCP handler returns the
19697
+ * Today these ship as definition lookups: the MCP handler returns the
19636
19698
  * approach record + invocation parameters; the LLM is the executor.
19637
19699
  * Structured execution is forward-declared (see `ApproachRuntime`) and is
19638
19700
  * a forthcoming follow-up.
19639
19701
  *
19640
19702
  * @example
19641
- * // The Prioritise approach — "what's most important?"
19703
+ * // The Prioritise approach: "what's most important?"
19642
19704
  * const prioritise: UPGApproach = {
19643
19705
  * id: 'prioritise',
19644
19706
  * label: 'Prioritise',
19645
- * description: 'Rank a candidate set by an explicit framework — RICE, ICE, Kano, Cost of Delay.',
19707
+ * description: 'Rank a candidate set by an explicit framework: RICE, ICE, Kano, Cost of Delay.',
19646
19708
  * question_answered: "what's most important?",
19647
19709
  * signature_hint: '({ candidates: entity_ids[], framework_id }) → { ranked, framework_used }',
19648
19710
  * framework_id_examples: ['rice-scoring', 'ice-scoring', 'kano-model', 'cost-of-delay'],
@@ -19650,11 +19712,11 @@ type UPGApproachId = 'plan' | 'inspect' | 'prioritise' | 'trace' | 'reflect';
19650
19712
  */
19651
19713
  interface UPGApproach {
19652
19714
  /**
19653
- * Unique identifier — bare verb, matches the MCP tool name. One of
19715
+ * Unique identifier: bare verb, matches the MCP tool name. One of
19654
19716
  * `'plan' | 'inspect' | 'prioritise' | 'trace' | 'reflect'`.
19655
19717
  */
19656
19718
  id: UPGApproachId;
19657
- /** Human-readable label (Title Case) — `'Plan'`, `'Inspect'`, etc. */
19719
+ /** Human-readable label (Title Case): `'Plan'`, `'Inspect'`, etc. */
19658
19720
  label: string;
19659
19721
  /** One-paragraph description of the cognitive engagement category. */
19660
19722
  description: string;
@@ -19664,44 +19726,44 @@ interface UPGApproach {
19664
19726
  */
19665
19727
  question_answered: string;
19666
19728
  /**
19667
- * Compact signature reminder — `(args) → return-shape`. Documents the
19729
+ * Compact signature reminder: `(args) → return-shape`. Documents the
19668
19730
  * structured-execution shape; today the MCP handler returns the approach
19669
19731
  * record + invocation parameters (definition lookup).
19670
19732
  */
19671
19733
  signature_hint: string;
19672
19734
  /**
19673
- * 3-5 canonical framework ids inside this approach (`UPGFramework.id`) —
19735
+ * 3-5 canonical framework ids inside this approach (`UPGFramework.id`),
19674
19736
  * a discoverability surface, not exhaustive coverage. Full reverse-lookup
19675
19737
  * is via `UPGFramework.approach_ids`.
19676
19738
  */
19677
19739
  framework_id_examples?: readonly string[];
19678
19740
  }
19679
19741
  /**
19680
- * Canonical reflect modes — the 4 nouns the `reflect` approach accepts as an
19742
+ * Canonical reflect modes: the 4 nouns the `reflect` approach accepts as an
19681
19743
  * optional `mode` parameter. Absence of `mode` is open reflection.
19682
19744
  *
19683
19745
  * Locked vocabulary; agent-facing. Users speak natural language; the LLM
19684
19746
  * translates `"what assumptions are we making?"` → `mode: 'assumptions'`.
19685
19747
  */
19686
19748
  type ReflectMode = 'assumptions' | 'alternatives' | 'blind-spots' | 'load-bearing';
19687
- /** Closed list — useful for tool input-schema enums. */
19749
+ /** Closed list, useful for tool input-schema enums. */
19688
19750
  declare const REFLECT_MODES: readonly ReflectMode[];
19689
19751
  /**
19690
19752
  * Shared envelope every approach handler returns. The handler-specific
19691
- * payload spreads into `...payload` — see each approach's `signature_hint`
19753
+ * payload spreads into `...payload`; see each approach's `signature_hint`
19692
19754
  * for the per-id shape.
19693
19755
  */
19694
19756
  interface UPGApproachEnvelope {
19695
19757
  /** The approach id this envelope is wrapping. */
19696
19758
  approach_id: UPGApproachId;
19697
19759
  /**
19698
- * Approach-specific scope — a region id (Plan, Inspect, Reflect), an
19760
+ * Approach-specific scope: a region id (Plan, Inspect, Reflect), an
19699
19761
  * anchor entity id (Trace), an entity id array (Prioritise candidates),
19700
19762
  * or `null` (open invocation). Typed `unknown` because the shape varies
19701
19763
  * by approach.
19702
19764
  */
19703
19765
  scope: unknown;
19704
- /** ISO-8601 datetime — when the handler produced the envelope. */
19766
+ /** ISO-8601 datetime when the handler produced the envelope. */
19705
19767
  generated_at: string;
19706
19768
  }
19707
19769
  /** Per-surface experience binding for a `UPGApproach`. Forward-declared. */
@@ -19712,28 +19774,28 @@ interface ApproachBinding {
19712
19774
  surface: SurfaceId;
19713
19775
  /** Identifier the runtime maps to a component or handler */
19714
19776
  renderer: string;
19715
- /** Per-step renderer overrides — keyed by `Step.order` */
19777
+ /** Per-step renderer overrides, keyed by `Step.order` */
19716
19778
  step_renderers?: Record<number, string>;
19717
19779
  /** Surface-specific step kinds the runtime handles */
19718
19780
  custom_step_kinds?: readonly string[];
19719
- /** Lifecycle hook id — runtime-resolved, fires when an invocation starts */
19781
+ /** Lifecycle hook id: runtime-resolved, fires when an invocation starts */
19720
19782
  on_start?: string;
19721
- /** Lifecycle hook id — runtime-resolved, fires after each step */
19783
+ /** Lifecycle hook id: runtime-resolved, fires after each step */
19722
19784
  on_step_complete?: string;
19723
- /** Lifecycle hook id — runtime-resolved, fires when an invocation completes */
19785
+ /** Lifecycle hook id: runtime-resolved, fires when an invocation completes */
19724
19786
  on_run_complete?: string;
19725
19787
  }
19726
19788
  /** Narrowing filter for `listApproaches`. All fields AND together. */
19727
19789
  interface ApproachFilter {
19728
19790
  /** Filter to approaches whose framework_id_examples include this id */
19729
19791
  framework_id?: string;
19730
- /** Filter to approaches relevant to a specific region (forward-compat — all five are cross-region today) */
19792
+ /** Filter to approaches relevant to a specific region (forward-compat; all five are cross-region today) */
19731
19793
  region?: UPGRegionId;
19732
19794
  /** Filter to approaches reachable via a specific entry mode (forward-compat) */
19733
19795
  entry_mode?: EntryMode;
19734
19796
  }
19735
19797
  /**
19736
- * A concrete invocation of a `UPGApproach`. Forward-declared — the MCP
19798
+ * A concrete invocation of a `UPGApproach`. Forward-declared: the MCP
19737
19799
  * handlers are stateless definition lookups today; structured execution
19738
19800
  * with run tracking is a forthcoming follow-up.
19739
19801
  */
@@ -19753,7 +19815,7 @@ interface ApproachRun {
19753
19815
  }
19754
19816
  /**
19755
19817
  * Forward-declared interface for a future structured-execution runtime. No
19756
- * current surface implements it — the MCP tools ship as definition lookups.
19818
+ * current surface implements it; the MCP tools ship as definition lookups.
19757
19819
  */
19758
19820
  interface ApproachRuntime {
19759
19821
  /** Return all approaches matching an optional filter */
@@ -19767,15 +19829,15 @@ interface ApproachRuntime {
19767
19829
  }
19768
19830
 
19769
19831
  /**
19770
- * approaches/definitions/ — the five canonical UPGApproach records.
19832
+ * approaches/definitions/: the five canonical UPGApproach records.
19771
19833
  *
19772
- * Each record is a definition lookup — id, label, description (cartographic
19834
+ * Each record is a definition lookup: id, label, description (cartographic
19773
19835
  * framing), question_answered, signature_hint, framework_id_examples.
19774
19836
  * Structured execution semantics are a forthcoming follow-up; the LLM is the
19775
19837
  * executor today.
19776
19838
  *
19777
19839
  * Order is stable: Plan / Inspect / Prioritise / Trace / Reflect. Matches the
19778
- * cognitive flow — decide what to build, check what's broken, rank what's
19840
+ * cognitive flow: decide what to build, check what's broken, rank what's
19779
19841
  * most important, walk a path through what exists, question what you're
19780
19842
  * assuming.
19781
19843
  *
@@ -19806,7 +19868,7 @@ declare function getRegionForEntityType(entityType: string): UPGRegion | undefin
19806
19868
  declare const UPG_REGION_COUNT: number;
19807
19869
 
19808
19870
  /**
19809
- * Framework validation — validates UPGFramework objects against the spec.
19871
+ * Framework validation: validates UPGFramework objects against the spec.
19810
19872
  */
19811
19873
  /** Result of validating a UPGFramework object */
19812
19874
  interface FrameworkValidationResult {
@@ -19852,7 +19914,7 @@ interface FrameworkValidationResult {
19852
19914
  declare function validateUPGFramework(framework: unknown): FrameworkValidationResult;
19853
19915
 
19854
19916
  /**
19855
- * Canonical Framework Library — v1 public surface.
19917
+ * Canonical Framework Library: v1 public surface.
19856
19918
  *
19857
19919
  * The 34 famous, battle-tested product frameworks that anchor the public
19858
19920
  * Unified Product Graph framework catalog. Curated for editorial confidence
@@ -19864,7 +19926,7 @@ declare function validateUPGFramework(framework: unknown): FrameworkValidationRe
19864
19926
  * promoted into this canonical set incrementally as each framework is
19865
19927
  * reviewed and validated.
19866
19928
  *
19867
- * THIS FILE IS GENERATED — see scripts/regen-canonical-frameworks.mjs.
19929
+ * THIS FILE IS GENERATED. See scripts/regen-canonical-frameworks.mjs.
19868
19930
  */
19869
19931
 
19870
19932
  declare const UPG_FRAMEWORKS: UPGFramework[];
@@ -19883,7 +19945,7 @@ declare const UPG_FRAMEWORKS_BY_CATEGORY: Record<string, UPGFramework[]>;
19883
19945
  */
19884
19946
 
19885
19947
  /** The current spec version implemented by this package */
19886
- declare const UPG_VERSION: "0.7.0";
19948
+ declare const UPG_VERSION: "0.7.3";
19887
19949
  /**
19888
19950
  * The `.upg` JSON document format version. Written to the `upg_version` field.
19889
19951
  * Evolves independently from `UPG_VERSION` (the catalogue version).
@@ -19906,7 +19968,7 @@ declare const UPG_EDGE_TYPES: readonly UPGEdgeType[];
19906
19968
  * Lookup map: `"source_type:target_type"` → ordered list of canonical edge keys.
19907
19969
  *
19908
19970
  * Computed from the edge catalog. Multiple edges may share a `(source, target)`
19909
- * pair — e.g. `learning_updates_hypothesis` (causal) and `learning_refines_hypothesis`
19971
+ * pair, e.g. `learning_updates_hypothesis` (causal) and `learning_refines_hypothesis`
19910
19972
  * (cross-domain) both connect `learning → hypothesis`. Prior to v0.4.1 this map
19911
19973
  * was a `Record<string, UPGEdgeType>` populated by `Object.fromEntries`, which
19912
19974
  * silently dropped every collision but the last (35 pairs).
@@ -19939,14 +20001,14 @@ declare function resolveAllEdges(sourceType: string, targetType: string): UPGEdg
19939
20001
  * **Policy:**
19940
20002
  * 1. If `hint` is provided and an edge with that `classification` exists for
19941
20003
  * the pair, return it (first declared wins for sub-collisions inside a
19942
- * single classification — declaration order is the canonical tiebreaker).
20004
+ * single classification, declaration order is the canonical tiebreaker).
19943
20005
  * 2. Otherwise, return the highest-ranked classification edge available,
19944
20006
  * using `CLASSIFICATION_RANK` (hierarchy ≻ causal ≻ semantic ≻ cross-domain).
19945
20007
  * 3. If the pair has no catalogued edges, return `null`.
19946
20008
  *
19947
20009
  * **Determinism:** for any `(source, target)` the picked edge is stable across
19948
- * runs and never changes unless the catalog is edited. This is the v0.4.1 fix
19949
- * — pair collisions are no longer last-wins.
20010
+ * runs and never changes unless the catalog is edited. This is the v0.4.1 fix:
20011
+ * pair collisions are no longer last-wins.
19950
20012
  *
19951
20013
  * @example
19952
20014
  * pickCanonicalEdge('product', 'decision', 'hierarchy')
@@ -19960,8 +20022,8 @@ declare function pickCanonicalEdge(sourceType: string, targetType: string, hint?
19960
20022
  * Resolve the canonical `UPGEdgeType` for a containment relationship.
19961
20023
  *
19962
20024
  * Import adapters need to emit edges like "epic contains user_story" but
19963
- * cannot safely construct raw `${parent}_contains_${child}` template strings —
19964
- * that union is closed and most pairs are not registered. This function looks
20025
+ * cannot safely construct raw `${parent}_contains_${child}` template strings,
20026
+ * because that union is closed and most pairs are not registered. This function looks
19965
20027
  * up the canonical edge for the given parent→child pair using
19966
20028
  * `pickCanonicalEdge` with the `'hierarchy'` hint, falling back through the
19967
20029
  * standard precedence when no hierarchy-class edge exists for the pair.
@@ -19975,7 +20037,7 @@ declare function pickCanonicalEdge(sourceType: string, targetType: string, hint?
19975
20037
  * caller can fall back to `node_informs_node` or skip the edge entirely.
19976
20038
  *
19977
20039
  * **Design note:** the `hint` argument is omitted from this function for
19978
- * back-compat — all in-tree callers (Markdown, Notion, Linear, GitHub
20040
+ * back-compat. All in-tree callers (Markdown, Notion, Linear, GitHub
19979
20041
  * adapters) are containment-only. Callers that need a different classification
19980
20042
  * should call `pickCanonicalEdge(source, target, hint)` directly.
19981
20043
  *