@unified-product-graph/core 0.22.2 → 0.23.1

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.cts CHANGED
@@ -1470,6 +1470,20 @@ declare const UPG_EDGE_CATALOG: {
1470
1470
  source_type: string;
1471
1471
  target_type: string;
1472
1472
  };
1473
+ epic_decomposes_into_task: {
1474
+ forward_verb: string;
1475
+ reverse_verb: string;
1476
+ classification: "hierarchy";
1477
+ source_type: string;
1478
+ target_type: string;
1479
+ };
1480
+ epic_affected_by_bug: {
1481
+ forward_verb: string;
1482
+ reverse_verb: string;
1483
+ classification: "hierarchy";
1484
+ source_type: string;
1485
+ target_type: string;
1486
+ };
1473
1487
  task_has_subtask: {
1474
1488
  forward_verb: string;
1475
1489
  reverse_verb: string;
@@ -7583,6 +7597,14 @@ declare const UPG_EDGE_CATALOG: {
7583
7597
  target_type: string;
7584
7598
  cross_product_eligible: true;
7585
7599
  };
7600
+ dependency_resolved_by_objective: {
7601
+ forward_verb: string;
7602
+ reverse_verb: string;
7603
+ classification: "cross-domain";
7604
+ source_type: string;
7605
+ target_type: string;
7606
+ cross_product_eligible: true;
7607
+ };
7586
7608
  objective_raises_strategic_question: {
7587
7609
  forward_verb: string;
7588
7610
  reverse_verb: string;
@@ -8188,7 +8210,7 @@ interface UPGPortfolioDocument {
8188
8210
  /**
8189
8211
  * Legacy product-stage aliases (UPG-509 Part 2).
8190
8212
  *
8191
- * Existing graphs (`entopo.upg`, `sanity.upg`, `maximum-minimum.upg`,
8213
+ * Existing graphs (`entopo.upg`, `nimbus.upg`, `maximum-minimum.upg`,
8192
8214
  * `notion-saturated.upg`, etc.) carry `product.stage` values that pre-date
8193
8215
  * the canonical `UPGProductStage` enum
8194
8216
  * (`concept | validation | build | beta | launch | growth | mature |
@@ -8631,7 +8653,7 @@ declare const UPG_DOMAINS: readonly [{
8631
8653
  }, {
8632
8654
  readonly id: "foundations";
8633
8655
  readonly label: "Foundations";
8634
- readonly description: "The shared specifications and foundational primitives a product organisation stewards or implements everywhere. Specifications are governed specs (query languages, protocols, data formats, encodings) like GROQ or Portable Text; primitives are the compositional units those specs define (a block, a reference, a query value). Both are registry-hostable canonicals that products implement, expose, or conform to. Distinct from a product feature: a specification has no single owner, no P&L, and no buyer; it is the rulebook many products point at.";
8656
+ readonly description: "The shared specifications and foundational primitives a product organisation stewards or implements everywhere. Specifications are governed specs (query languages, protocols, data formats, encodings) like NQL or Structured Text; primitives are the compositional units those specs define (a block, a reference, a query value). Both are registry-hostable canonicals that products implement, expose, or conform to. Distinct from a product feature: a specification has no single owner, no P&L, and no buyer; it is the rulebook many products point at.";
8635
8657
  readonly types: readonly ["specification", "primitive", "operating_lifecycle", "operating_stage"];
8636
8658
  }];
8637
8659
  /**
@@ -9825,7 +9847,7 @@ declare function migrateEdge<T extends {
9825
9847
  * type's lifecycle exists but the graph carries pre-canonical status values
9826
9848
  * the lifecycle never had.
9827
9849
  *
9828
- * Source: live drift in `.upg/entopo.upg`, `.upg/sanity.upg`, and
9850
+ * Source: live drift in `.upg/entopo.upg`, `.upg/nimbus.upg`, and
9829
9851
  * `.upg/inkling.upg` surveyed during the v0.5 launch train (UPG-527).
9830
9852
  * Highest single drift class: 173 `service` nodes with `status: "active"`
9831
9853
  * against the canonical `[development, staging, production, deprecated]`
@@ -11452,7 +11474,7 @@ interface CompetitorProperties {
11452
11474
  /**
11453
11475
  * Provenance: where this was observed. A changelog, pricing, or docs URL,
11454
11476
  * an analyst report, or a research note.
11455
- * @example "https://www.contentful.com/pricing/"
11477
+ * @example "https://docs.larch.example/pricing/"
11456
11478
  */
11457
11479
  source?: string;
11458
11480
  /**
@@ -11504,7 +11526,7 @@ interface CompetitorFeatureProperties {
11504
11526
  /**
11505
11527
  * Provenance: where this was observed. A changelog, pricing, or docs URL,
11506
11528
  * an analyst report, or a research note.
11507
- * @example "https://www.contentful.com/changelog/"
11529
+ * @example "https://docs.larch.example/changelog/"
11508
11530
  */
11509
11531
  source?: string;
11510
11532
  /**
@@ -11626,7 +11648,7 @@ interface CompetitiveAnalysisProperties {
11626
11648
  *
11627
11649
  * @example
11628
11650
  * [
11629
- * { axis_a_value_ref: 'val-git-based', axis_b_value_ref: 'val-portable-text',
11651
+ * { axis_a_value_ref: 'val-git-based', axis_b_value_ref: 'val-structured-text',
11630
11652
  * rationale_kind: 'opportunity',
11631
11653
  * rationale_md: 'No technical reason; only adoption inertia. Watching brief.' },
11632
11654
  * { axis_a_value_ref: 'val-composable', axis_b_value_ref: 'val-wysiwyg',
@@ -11644,7 +11666,7 @@ interface CompetitiveAnalysisProperties {
11644
11666
  /**
11645
11667
  * Provenance: where this was observed. A changelog, pricing, or docs URL,
11646
11668
  * an analyst report, or a research note.
11647
- * @example "https://www.contentful.com/changelog/"
11669
+ * @example "https://docs.larch.example/changelog/"
11648
11670
  */
11649
11671
  source?: string;
11650
11672
  /**
@@ -11723,7 +11745,7 @@ interface CompetitorSignalProperties {
11723
11745
  /**
11724
11746
  * Provenance: where this was observed. A changelog, pricing, or docs URL,
11725
11747
  * an analyst report, or a research note.
11726
- * @example "https://www.contentful.com/changelog/"
11748
+ * @example "https://docs.larch.example/changelog/"
11727
11749
  */
11728
11750
  source?: string;
11729
11751
  /**
@@ -11851,14 +11873,14 @@ interface ClassificationAxisProperties {
11851
11873
  * @example
11852
11874
  * const properties: ClassificationValueProperties = {
11853
11875
  * rationale: 'Composable extends headless with three load-bearing commitments.',
11854
- * exemplars: ['Sanity', 'Contentful', 'Hygraph'],
11876
+ * exemplars: ['Nimbus', 'Larch', 'Prism'],
11855
11877
  * commitments: [
11856
11878
  * { name: 'Typed content graph', description: 'Schemas in code; references as edges.' },
11857
11879
  * { name: 'Real-time backend', description: 'Live queries, CRDT collaboration.' },
11858
11880
  * { name: 'Embeddable studio', description: 'Editor is a library hosted inside the team app.' },
11859
11881
  * ],
11860
11882
  * capabilities: [
11861
- * { surface: 'delivery', bullets: ['GROQ', 'GraphQL', 'REST', 'Live Content API'] },
11883
+ * { surface: 'delivery', bullets: ['NQL', 'GraphQL', 'REST', 'Live Sync API'] },
11862
11884
  * ],
11863
11885
  * }
11864
11886
  */
@@ -11871,7 +11893,7 @@ interface ClassificationValueProperties {
11871
11893
  /**
11872
11894
  * Free-text examples of products occupying this value.
11873
11895
  * For queryable occupancy, prefer `competitor` nodes with `classified_as` edges.
11874
- * @example ['Sanity', 'Contentful', 'Hygraph']
11896
+ * @example ['Nimbus', 'Larch', 'Prism']
11875
11897
  */
11876
11898
  exemplars?: string[];
11877
11899
  /**
@@ -11898,8 +11920,8 @@ interface ClassificationValueProperties {
11898
11920
  *
11899
11921
  * @example
11900
11922
  * [
11901
- * { surface: 'delivery', bullets: ['GROQ', 'GraphQL', 'REST', 'Live Content API', 'Asset CDN'] },
11902
- * { surface: 'extensibility', bullets: ['Custom input components', 'Studio plugins'] },
11923
+ * { surface: 'delivery', bullets: ['NQL', 'GraphQL', 'REST', 'Live Sync API', 'Asset CDN'] },
11924
+ * { surface: 'extensibility', bullets: ['Custom input components', 'editor plugins'] },
11903
11925
  * ]
11904
11926
  */
11905
11927
  capabilities?: Array<ClassificationCapability>;
@@ -15405,7 +15427,7 @@ interface EventSchemaProperties {
15405
15427
  */
15406
15428
  interface DashboardProperties {
15407
15429
  /** Analytics tool hosting this dashboard */
15408
- tool?: 'looker' | 'amplitude' | 'mixpanel' | 'posthog' | 'custom';
15430
+ tool?: 'looker' | 'amplitude' | 'mixpanel' | 'posthog' | 'omni' | 'custom';
15409
15431
  /** URL to the live dashboard */
15410
15432
  url?: string;
15411
15433
  /** Intended audience for this dashboard */
@@ -18843,9 +18865,9 @@ interface FrameworkExerciseProperties {
18843
18865
  * kind: 'language',
18844
18866
  * language_flavor: 'query',
18845
18867
  * governance: 'open_spec_stewarded',
18846
- * steward: 'Sanity',
18868
+ * steward: 'Nimbus',
18847
18869
  * openness: 'open',
18848
- * spec_url: 'https://sanity.io/docs/groq',
18870
+ * spec_url: 'https://nimbus.example/docs/nql',
18849
18871
  * current_version: '1.0',
18850
18872
  * since: '2019',
18851
18873
  * }
@@ -18875,13 +18897,13 @@ interface SpecificationProperties {
18875
18897
  conformance?: string;
18876
18898
  }
18877
18899
  /** A foundational compositional unit a specification defines: the noun products
18878
- * pass around and compose with (a Portable Text block, a Sanity reference, a
18900
+ * pass around and compose with (a Structured Text block, a typed reference, a
18879
18901
  * Git commit, a Stripe PaymentIntent). Lifecycle-free, like `metric`.
18880
18902
  *
18881
18903
  * @example
18882
18904
  * const properties: PrimitiveProperties = {
18883
18905
  * primitive_kind: 'block',
18884
- * defined_by: 'specification/portable_text',
18906
+ * defined_by: 'specification/structured_text',
18885
18907
  * since: '2018',
18886
18908
  * }
18887
18909
  */
@@ -18894,7 +18916,7 @@ interface PrimitiveProperties {
18894
18916
  since?: string;
18895
18917
  }
18896
18918
  /** An operating_lifecycle: a canonical, ordered (often cyclic) operating process
18897
- * that many products' journey phases map onto — e.g. Sanity's content-operations
18919
+ * that many products' journey phases map onto — e.g. Nimbus's content-operations
18898
18920
  * lifecycle. Registry-hostable like a `specification`; the cross-product join key
18899
18921
  * that turns per-surface journeys into one operation. Distinct from the per-entity
18900
18922
  * status `lifecycle` grammar concept (this is an entity, not a state machine).
@@ -18902,13 +18924,13 @@ interface PrimitiveProperties {
18902
18924
  * @example
18903
18925
  * const properties: OperatingLifecycleProperties = {
18904
18926
  * cyclic: true,
18905
- * source: 'Sanity official 5-stage content-ops lifecycle',
18927
+ * source: 'a canonical 5-stage content-ops lifecycle',
18906
18928
  * }
18907
18929
  */
18908
18930
  interface OperatingLifecycleProperties {
18909
18931
  /** True if the process loops (e.g. Analyze → Extend → Plan). The sequence is fully expressed by the stages' `stage_order`; `cyclic` adds the wrap from the last stage back to the first. */
18910
18932
  cyclic?: boolean;
18911
- /** Origin of the canonical model (e.g. "Sanity official content-ops lifecycle"). Optional provenance; promote to an edge if it names a real `specification`/`document`. */
18933
+ /** Origin of the canonical model (e.g. "a published content-ops lifecycle"). Optional provenance; promote to an edge if it names a real `specification`/`document`. */
18912
18934
  source?: string;
18913
18935
  }
18914
18936
  /** An operating_stage: one ordered stage of an `operating_lifecycle`. A product's
@@ -22518,7 +22540,7 @@ declare function isCanonical(text: string): boolean;
22518
22540
  * it stamps the `upg_version` field of every `.upg` file written by the SDK.
22519
22541
  * The `check:version-lockstep` gate enforces this at release time.
22520
22542
  */
22521
- declare const UPG_VERSION: "0.22.2";
22543
+ declare const UPG_VERSION: "0.23.1";
22522
22544
  /**
22523
22545
  * The `.upg` JSON document format version. Written to the `upg_version` field.
22524
22546
  * Evolves independently from `UPG_VERSION` (the catalogue version).
package/dist/index.d.ts CHANGED
@@ -1470,6 +1470,20 @@ declare const UPG_EDGE_CATALOG: {
1470
1470
  source_type: string;
1471
1471
  target_type: string;
1472
1472
  };
1473
+ epic_decomposes_into_task: {
1474
+ forward_verb: string;
1475
+ reverse_verb: string;
1476
+ classification: "hierarchy";
1477
+ source_type: string;
1478
+ target_type: string;
1479
+ };
1480
+ epic_affected_by_bug: {
1481
+ forward_verb: string;
1482
+ reverse_verb: string;
1483
+ classification: "hierarchy";
1484
+ source_type: string;
1485
+ target_type: string;
1486
+ };
1473
1487
  task_has_subtask: {
1474
1488
  forward_verb: string;
1475
1489
  reverse_verb: string;
@@ -7583,6 +7597,14 @@ declare const UPG_EDGE_CATALOG: {
7583
7597
  target_type: string;
7584
7598
  cross_product_eligible: true;
7585
7599
  };
7600
+ dependency_resolved_by_objective: {
7601
+ forward_verb: string;
7602
+ reverse_verb: string;
7603
+ classification: "cross-domain";
7604
+ source_type: string;
7605
+ target_type: string;
7606
+ cross_product_eligible: true;
7607
+ };
7586
7608
  objective_raises_strategic_question: {
7587
7609
  forward_verb: string;
7588
7610
  reverse_verb: string;
@@ -8188,7 +8210,7 @@ interface UPGPortfolioDocument {
8188
8210
  /**
8189
8211
  * Legacy product-stage aliases (UPG-509 Part 2).
8190
8212
  *
8191
- * Existing graphs (`entopo.upg`, `sanity.upg`, `maximum-minimum.upg`,
8213
+ * Existing graphs (`entopo.upg`, `nimbus.upg`, `maximum-minimum.upg`,
8192
8214
  * `notion-saturated.upg`, etc.) carry `product.stage` values that pre-date
8193
8215
  * the canonical `UPGProductStage` enum
8194
8216
  * (`concept | validation | build | beta | launch | growth | mature |
@@ -8631,7 +8653,7 @@ declare const UPG_DOMAINS: readonly [{
8631
8653
  }, {
8632
8654
  readonly id: "foundations";
8633
8655
  readonly label: "Foundations";
8634
- readonly description: "The shared specifications and foundational primitives a product organisation stewards or implements everywhere. Specifications are governed specs (query languages, protocols, data formats, encodings) like GROQ or Portable Text; primitives are the compositional units those specs define (a block, a reference, a query value). Both are registry-hostable canonicals that products implement, expose, or conform to. Distinct from a product feature: a specification has no single owner, no P&L, and no buyer; it is the rulebook many products point at.";
8656
+ readonly description: "The shared specifications and foundational primitives a product organisation stewards or implements everywhere. Specifications are governed specs (query languages, protocols, data formats, encodings) like NQL or Structured Text; primitives are the compositional units those specs define (a block, a reference, a query value). Both are registry-hostable canonicals that products implement, expose, or conform to. Distinct from a product feature: a specification has no single owner, no P&L, and no buyer; it is the rulebook many products point at.";
8635
8657
  readonly types: readonly ["specification", "primitive", "operating_lifecycle", "operating_stage"];
8636
8658
  }];
8637
8659
  /**
@@ -9825,7 +9847,7 @@ declare function migrateEdge<T extends {
9825
9847
  * type's lifecycle exists but the graph carries pre-canonical status values
9826
9848
  * the lifecycle never had.
9827
9849
  *
9828
- * Source: live drift in `.upg/entopo.upg`, `.upg/sanity.upg`, and
9850
+ * Source: live drift in `.upg/entopo.upg`, `.upg/nimbus.upg`, and
9829
9851
  * `.upg/inkling.upg` surveyed during the v0.5 launch train (UPG-527).
9830
9852
  * Highest single drift class: 173 `service` nodes with `status: "active"`
9831
9853
  * against the canonical `[development, staging, production, deprecated]`
@@ -11452,7 +11474,7 @@ interface CompetitorProperties {
11452
11474
  /**
11453
11475
  * Provenance: where this was observed. A changelog, pricing, or docs URL,
11454
11476
  * an analyst report, or a research note.
11455
- * @example "https://www.contentful.com/pricing/"
11477
+ * @example "https://docs.larch.example/pricing/"
11456
11478
  */
11457
11479
  source?: string;
11458
11480
  /**
@@ -11504,7 +11526,7 @@ interface CompetitorFeatureProperties {
11504
11526
  /**
11505
11527
  * Provenance: where this was observed. A changelog, pricing, or docs URL,
11506
11528
  * an analyst report, or a research note.
11507
- * @example "https://www.contentful.com/changelog/"
11529
+ * @example "https://docs.larch.example/changelog/"
11508
11530
  */
11509
11531
  source?: string;
11510
11532
  /**
@@ -11626,7 +11648,7 @@ interface CompetitiveAnalysisProperties {
11626
11648
  *
11627
11649
  * @example
11628
11650
  * [
11629
- * { axis_a_value_ref: 'val-git-based', axis_b_value_ref: 'val-portable-text',
11651
+ * { axis_a_value_ref: 'val-git-based', axis_b_value_ref: 'val-structured-text',
11630
11652
  * rationale_kind: 'opportunity',
11631
11653
  * rationale_md: 'No technical reason; only adoption inertia. Watching brief.' },
11632
11654
  * { axis_a_value_ref: 'val-composable', axis_b_value_ref: 'val-wysiwyg',
@@ -11644,7 +11666,7 @@ interface CompetitiveAnalysisProperties {
11644
11666
  /**
11645
11667
  * Provenance: where this was observed. A changelog, pricing, or docs URL,
11646
11668
  * an analyst report, or a research note.
11647
- * @example "https://www.contentful.com/changelog/"
11669
+ * @example "https://docs.larch.example/changelog/"
11648
11670
  */
11649
11671
  source?: string;
11650
11672
  /**
@@ -11723,7 +11745,7 @@ interface CompetitorSignalProperties {
11723
11745
  /**
11724
11746
  * Provenance: where this was observed. A changelog, pricing, or docs URL,
11725
11747
  * an analyst report, or a research note.
11726
- * @example "https://www.contentful.com/changelog/"
11748
+ * @example "https://docs.larch.example/changelog/"
11727
11749
  */
11728
11750
  source?: string;
11729
11751
  /**
@@ -11851,14 +11873,14 @@ interface ClassificationAxisProperties {
11851
11873
  * @example
11852
11874
  * const properties: ClassificationValueProperties = {
11853
11875
  * rationale: 'Composable extends headless with three load-bearing commitments.',
11854
- * exemplars: ['Sanity', 'Contentful', 'Hygraph'],
11876
+ * exemplars: ['Nimbus', 'Larch', 'Prism'],
11855
11877
  * commitments: [
11856
11878
  * { name: 'Typed content graph', description: 'Schemas in code; references as edges.' },
11857
11879
  * { name: 'Real-time backend', description: 'Live queries, CRDT collaboration.' },
11858
11880
  * { name: 'Embeddable studio', description: 'Editor is a library hosted inside the team app.' },
11859
11881
  * ],
11860
11882
  * capabilities: [
11861
- * { surface: 'delivery', bullets: ['GROQ', 'GraphQL', 'REST', 'Live Content API'] },
11883
+ * { surface: 'delivery', bullets: ['NQL', 'GraphQL', 'REST', 'Live Sync API'] },
11862
11884
  * ],
11863
11885
  * }
11864
11886
  */
@@ -11871,7 +11893,7 @@ interface ClassificationValueProperties {
11871
11893
  /**
11872
11894
  * Free-text examples of products occupying this value.
11873
11895
  * For queryable occupancy, prefer `competitor` nodes with `classified_as` edges.
11874
- * @example ['Sanity', 'Contentful', 'Hygraph']
11896
+ * @example ['Nimbus', 'Larch', 'Prism']
11875
11897
  */
11876
11898
  exemplars?: string[];
11877
11899
  /**
@@ -11898,8 +11920,8 @@ interface ClassificationValueProperties {
11898
11920
  *
11899
11921
  * @example
11900
11922
  * [
11901
- * { surface: 'delivery', bullets: ['GROQ', 'GraphQL', 'REST', 'Live Content API', 'Asset CDN'] },
11902
- * { surface: 'extensibility', bullets: ['Custom input components', 'Studio plugins'] },
11923
+ * { surface: 'delivery', bullets: ['NQL', 'GraphQL', 'REST', 'Live Sync API', 'Asset CDN'] },
11924
+ * { surface: 'extensibility', bullets: ['Custom input components', 'editor plugins'] },
11903
11925
  * ]
11904
11926
  */
11905
11927
  capabilities?: Array<ClassificationCapability>;
@@ -15405,7 +15427,7 @@ interface EventSchemaProperties {
15405
15427
  */
15406
15428
  interface DashboardProperties {
15407
15429
  /** Analytics tool hosting this dashboard */
15408
- tool?: 'looker' | 'amplitude' | 'mixpanel' | 'posthog' | 'custom';
15430
+ tool?: 'looker' | 'amplitude' | 'mixpanel' | 'posthog' | 'omni' | 'custom';
15409
15431
  /** URL to the live dashboard */
15410
15432
  url?: string;
15411
15433
  /** Intended audience for this dashboard */
@@ -18843,9 +18865,9 @@ interface FrameworkExerciseProperties {
18843
18865
  * kind: 'language',
18844
18866
  * language_flavor: 'query',
18845
18867
  * governance: 'open_spec_stewarded',
18846
- * steward: 'Sanity',
18868
+ * steward: 'Nimbus',
18847
18869
  * openness: 'open',
18848
- * spec_url: 'https://sanity.io/docs/groq',
18870
+ * spec_url: 'https://nimbus.example/docs/nql',
18849
18871
  * current_version: '1.0',
18850
18872
  * since: '2019',
18851
18873
  * }
@@ -18875,13 +18897,13 @@ interface SpecificationProperties {
18875
18897
  conformance?: string;
18876
18898
  }
18877
18899
  /** A foundational compositional unit a specification defines: the noun products
18878
- * pass around and compose with (a Portable Text block, a Sanity reference, a
18900
+ * pass around and compose with (a Structured Text block, a typed reference, a
18879
18901
  * Git commit, a Stripe PaymentIntent). Lifecycle-free, like `metric`.
18880
18902
  *
18881
18903
  * @example
18882
18904
  * const properties: PrimitiveProperties = {
18883
18905
  * primitive_kind: 'block',
18884
- * defined_by: 'specification/portable_text',
18906
+ * defined_by: 'specification/structured_text',
18885
18907
  * since: '2018',
18886
18908
  * }
18887
18909
  */
@@ -18894,7 +18916,7 @@ interface PrimitiveProperties {
18894
18916
  since?: string;
18895
18917
  }
18896
18918
  /** An operating_lifecycle: a canonical, ordered (often cyclic) operating process
18897
- * that many products' journey phases map onto — e.g. Sanity's content-operations
18919
+ * that many products' journey phases map onto — e.g. Nimbus's content-operations
18898
18920
  * lifecycle. Registry-hostable like a `specification`; the cross-product join key
18899
18921
  * that turns per-surface journeys into one operation. Distinct from the per-entity
18900
18922
  * status `lifecycle` grammar concept (this is an entity, not a state machine).
@@ -18902,13 +18924,13 @@ interface PrimitiveProperties {
18902
18924
  * @example
18903
18925
  * const properties: OperatingLifecycleProperties = {
18904
18926
  * cyclic: true,
18905
- * source: 'Sanity official 5-stage content-ops lifecycle',
18927
+ * source: 'a canonical 5-stage content-ops lifecycle',
18906
18928
  * }
18907
18929
  */
18908
18930
  interface OperatingLifecycleProperties {
18909
18931
  /** True if the process loops (e.g. Analyze → Extend → Plan). The sequence is fully expressed by the stages' `stage_order`; `cyclic` adds the wrap from the last stage back to the first. */
18910
18932
  cyclic?: boolean;
18911
- /** Origin of the canonical model (e.g. "Sanity official content-ops lifecycle"). Optional provenance; promote to an edge if it names a real `specification`/`document`. */
18933
+ /** Origin of the canonical model (e.g. "a published content-ops lifecycle"). Optional provenance; promote to an edge if it names a real `specification`/`document`. */
18912
18934
  source?: string;
18913
18935
  }
18914
18936
  /** An operating_stage: one ordered stage of an `operating_lifecycle`. A product's
@@ -22518,7 +22540,7 @@ declare function isCanonical(text: string): boolean;
22518
22540
  * it stamps the `upg_version` field of every `.upg` file written by the SDK.
22519
22541
  * The `check:version-lockstep` gate enforces this at release time.
22520
22542
  */
22521
- declare const UPG_VERSION: "0.22.2";
22543
+ declare const UPG_VERSION: "0.23.1";
22522
22544
  /**
22523
22545
  * The `.upg` JSON document format version. Written to the `upg_version` field.
22524
22546
  * Evolves independently from `UPG_VERSION` (the catalogue version).
package/dist/index.js CHANGED
@@ -495,7 +495,7 @@ var UPG_DOMAINS = [
495
495
  {
496
496
  id: "foundations",
497
497
  label: "Foundations",
498
- description: "The shared specifications and foundational primitives a product organisation stewards or implements everywhere. Specifications are governed specs (query languages, protocols, data formats, encodings) like GROQ or Portable Text; primitives are the compositional units those specs define (a block, a reference, a query value). Both are registry-hostable canonicals that products implement, expose, or conform to. Distinct from a product feature: a specification has no single owner, no P&L, and no buyer; it is the rulebook many products point at.",
498
+ description: "The shared specifications and foundational primitives a product organisation stewards or implements everywhere. Specifications are governed specs (query languages, protocols, data formats, encodings) like NQL or Structured Text; primitives are the compositional units those specs define (a block, a reference, a query value). Both are registry-hostable canonicals that products implement, expose, or conform to. Distinct from a product feature: a specification has no single owner, no P&L, and no buyer; it is the rulebook many products point at.",
499
499
  types: ["specification", "primitive", "operating_lifecycle", "operating_stage"]
500
500
  }
501
501
  ];
@@ -1429,6 +1429,17 @@ var UPG_EDGE_CATALOG = {
1429
1429
  bug_affects_feature: { forward_verb: "affects", reverse_verb: "affected_by", classification: "cross-domain", source_type: "bug", target_type: "feature" },
1430
1430
  roadmap_item_references_feature: { forward_verb: "references", reverse_verb: "referenced_by", classification: "cross-domain", source_type: "roadmap_item", target_type: "feature" },
1431
1431
  feature_decomposes_into_task: { forward_verb: "decomposes_into", reverse_verb: "implements", classification: "hierarchy", source_type: "feature", target_type: "task" },
1432
+ // Epic-level mirrors of the feature→task / feature→bug hierarchy (feedback
1433
+ // df99026a). A `feature` is the flat planning root, but an `epic` is a body of
1434
+ // work under it, and real imported ticket sets (Linear/Jira) carry bugs and
1435
+ // pure engineering tasks that belong to ONE epic, not the feature as a whole.
1436
+ // Without these, such tickets had to be mislabelled `user_story` (the only
1437
+ // epic child) to keep the epic grouping. These are additive twins of the
1438
+ // feature-level edges (same verbs/classification), so `pickCanonicalEdge` /
1439
+ // `resolveContainmentEdge('epic', 'task'|'bug')` and the adapter import path
1440
+ // resolve them with no further wiring.
1441
+ epic_decomposes_into_task: { forward_verb: "decomposes_into", reverse_verb: "implements", classification: "hierarchy", source_type: "epic", target_type: "task" },
1442
+ epic_affected_by_bug: { forward_verb: "affected_by", reverse_verb: "affects", classification: "hierarchy", source_type: "epic", target_type: "bug" },
1432
1443
  task_has_subtask: { forward_verb: "has_subtask", reverse_verb: "is_subtask_of", classification: "hierarchy", source_type: "task", target_type: "task" },
1433
1444
  // ── Planning cadence (0.20.0) ────────────────────────────────────────────────
1434
1445
  // The cadence axis. E1 self-nests the interval (a program-increment contains
@@ -3205,6 +3216,15 @@ var UPG_EDGE_CATALOG = {
3205
3216
  // by another team's graph within the portfolio (0.17.3 locked predicate).
3206
3217
  objective_depends_on_dependency: { forward_verb: "depends_on", reverse_verb: "dependency_of", classification: "cross-domain", source_type: "objective", target_type: "dependency", cross_product_eligible: true },
3207
3218
  dependency_blocks_objective: { forward_verb: "blocks", reverse_verb: "blocked_by", classification: "cross-domain", source_type: "dependency", target_type: "objective", cross_product_eligible: true },
3219
+ // The RESOLVING side, distinct from the two blocking edges above.
3220
+ // `dependency_blocks_objective` names an objective the dependency holds up (the
3221
+ // waiting side); this names the objective whose completion CLEARS the
3222
+ // dependency (the providing side). In a portfolio, a dependency in one
3223
+ // product's graph points at the objective in another product's graph that
3224
+ // delivers the awaited work, instead of recording it only in the free-text
3225
+ // `resolution` property. cross_product_eligible — the resolving objective
3226
+ // lives in another product's graph.
3227
+ dependency_resolved_by_objective: { forward_verb: "resolved_by", reverse_verb: "resolves", classification: "cross-domain", source_type: "dependency", target_type: "objective", cross_product_eligible: true },
3208
3228
  // objective / initiative → strategic_question. A planning doc's "Risks & Open
3209
3229
  // Questions" section names unresolved coordination questions the plan is
3210
3230
  // exposed to (who owns a capability across teams after a reorg). The
@@ -3732,7 +3752,10 @@ var UPG_VALID_CHILDREN = {
3732
3752
  // task_implements_user_story edge.
3733
3753
  feature: ["epic", "bug", "task"],
3734
3754
  feature_area: ["feature", "feature_area"],
3735
- epic: ["user_story"],
3755
+ // epic owns user_story (the templated promise) and, mirroring feature, may
3756
+ // also directly contain bug/task — heterogeneous imported tickets that belong
3757
+ // to one epic rather than the feature as a whole (feedback df99026a).
3758
+ epic: ["user_story", "bug", "task"],
3736
3759
  user_story: ["acceptance_criterion"],
3737
3760
  task: ["task"],
3738
3761
  // planning_cycle (0.20.0): the cadence axis self-nests (a program-increment
@@ -10462,9 +10485,9 @@ var UPG_PROPERTY_SCHEMA = {
10462
10485
  // ClassificationValueProperties: ClassificationValue: a value on a classification axis.
10463
10486
  classification_value: {
10464
10487
  rationale: { type: "string", description: "Short paragraph: why this value earns its own row/column. Longer narrative belongs in `summary_md` or attached `content_piece` nodes." },
10465
- exemplars: { type: "string[]", description: "Free-text examples of products occupying this value. For queryable occupancy, prefer `competitor` nodes with `classified_as` edges. @example ['Sanity', 'Contentful', 'Hygraph']" },
10488
+ exemplars: { type: "string[]", description: "Free-text examples of products occupying this value. For queryable occupancy, prefer `competitor` nodes with `classified_as` edges. @example ['Nimbus', 'Larch', 'Prism']" },
10466
10489
  commitments: { type: "object[]", description: "The N (typically 2\u20134) load-bearing commitments that define this category. Each commitment is a structural axis; removing it changes the category. Pairs with `capabilities`: commitments are the *load-bearing definition*; capabilities are the *surface offering*. @example [ { name: 'Typed content graph', description: 'Schemas in code; references as edges; content is structured data.' }, { name: 'Real-time backend', description: 'Live queries, CRDT collaboration, sub-second propagation.' }, { name: 'Embeddable studio', description: 'Editor is a library hosted inside the team app, not an external portal.' }, ]" },
10467
- capabilities: { type: "object[]", description: "Structured capability bullets across the six canonical surfaces. Each surface appears at most once per `classification_value`. Pairs with `commitments`: capabilities describe what the category *offers*; commitments describe what *defines* it. @example [ { surface: 'delivery', bullets: ['GROQ', 'GraphQL', 'REST', 'Live Content API', 'Asset CDN'] }, { surface: 'extensibility', bullets: ['Custom input components', 'Studio plugins'] }, ]" }
10490
+ capabilities: { type: "object[]", description: "Structured capability bullets across the six canonical surfaces. Each surface appears at most once per `classification_value`. Pairs with `commitments`: capabilities describe what the category *offers*; commitments describe what *defines* it. @example [ { surface: 'delivery', bullets: ['NQL', 'GraphQL', 'REST', 'Live Sync API', 'Asset CDN'] }, { surface: 'extensibility', bullets: ['Custom input components', 'editor plugins'] }, ]" }
10468
10491
  },
10469
10492
  // CodeRepositoryProperties: Code repository.
10470
10493
  code_repository: {
@@ -10499,9 +10522,9 @@ var UPG_PROPERTY_SCHEMA = {
10499
10522
  analysis_type: { type: "string", enum: ["feature_comparison", "positioning", "swot", "pricing"], description: "Type of analysis. `feature_comparison` = side-by-side matrix. `positioning` = competitor positioning relative to each other. `swot` = strengths, weaknesses, opportunities, threats. `pricing` = pricing structure comparison." },
10500
10523
  analysis_date: { type: "string", description: 'ISO date conducted. Competitive intelligence decays quickly; track snapshot age. @example "2026-03-15"' },
10501
10524
  framework_id: { type: "string", description: 'Framework ID (references `UPGFramework.id`). @example "porter-five-forces", "swot-analysis", "competitive-matrix"' },
10502
- empty_cells: { type: "object[]", description: "Empty cells in a 2-axis classification matrix that earn explicit commentary. Only the strategically interesting cells. Opportunity-kind cells are the most valuable; they identify unoccupied strategic space. Each entry references two `classification_value` nodes by id (one from each `classification_axis` child of this `competitive_analysis`). `validate_graph` enforces that the refs resolve to `classification_value` nodes whose parents are distinct `classification_axis` instances. See `ClassificationValueProperties.commitments` for the inverse \"occupied cell\" structural-definition shape. @example [ { axis_a_value_ref: 'val-git-based', axis_b_value_ref: 'val-portable-text', rationale_kind: 'opportunity', rationale_md: 'No technical reason; only adoption inertia. Watching brief.' }, { axis_a_value_ref: 'val-composable', axis_b_value_ref: 'val-wysiwyg', rationale_kind: 'structural', rationale_md: 'Composable rejects HTML blobs; WYSIWYG requires them.' }, ]" },
10525
+ empty_cells: { type: "object[]", description: "Empty cells in a 2-axis classification matrix that earn explicit commentary. Only the strategically interesting cells. Opportunity-kind cells are the most valuable; they identify unoccupied strategic space. Each entry references two `classification_value` nodes by id (one from each `classification_axis` child of this `competitive_analysis`). `validate_graph` enforces that the refs resolve to `classification_value` nodes whose parents are distinct `classification_axis` instances. See `ClassificationValueProperties.commitments` for the inverse \"occupied cell\" structural-definition shape. @example [ { axis_a_value_ref: 'val-git-based', axis_b_value_ref: 'val-structured-text', rationale_kind: 'opportunity', rationale_md: 'No technical reason; only adoption inertia. Watching brief.' }, { axis_a_value_ref: 'val-composable', axis_b_value_ref: 'val-wysiwyg', rationale_kind: 'structural', rationale_md: 'Composable rejects HTML blobs; WYSIWYG requires them.' }, ]" },
10503
10526
  last_updated: { type: "string", description: 'Provenance: ISO date-time this record was last observed or refreshed. Distinct from `analysis_date` (when the analysis was conducted). @example "2026-06-13"' },
10504
- source: { type: "string", description: 'Provenance: where this was observed. A changelog, pricing, or docs URL, an analyst report, or a research note. @example "https://www.contentful.com/changelog/"' },
10527
+ source: { type: "string", description: 'Provenance: where this was observed. A changelog, pricing, or docs URL, an analyst report, or a research note. @example "https://docs.larch.example/changelog/"' },
10505
10528
  confidence: {
10506
10529
  type: "assessment",
10507
10530
  scale_id: "confidence_5",
@@ -10529,7 +10552,7 @@ var UPG_PROPERTY_SCHEMA = {
10529
10552
  strengths: { type: "string[]", description: "Bulleted factual strengths. Each item is a short statement, not prose. @example ['Real-time multiplayer canvas', 'Generous free tier']" },
10530
10553
  weaknesses: { type: "string[]", description: "Bulleted factual weaknesses: gaps, friction, or capabilities materially below market. @example ['Weak API query capabilities', 'No mobile companion']" },
10531
10554
  last_updated: { type: "string", description: 'Provenance: ISO date-time this record was last observed or refreshed. Lets a stale record be told apart from a fresh one. @example "2026-06-13"' },
10532
- source: { type: "string", description: 'Provenance: where this was observed. A changelog, pricing, or docs URL, an analyst report, or a research note. @example "https://www.contentful.com/pricing/"' },
10555
+ source: { type: "string", description: 'Provenance: where this was observed. A changelog, pricing, or docs URL, an analyst report, or a research note. @example "https://docs.larch.example/pricing/"' },
10533
10556
  confidence: {
10534
10557
  type: "assessment",
10535
10558
  scale_id: "confidence_5",
@@ -10551,7 +10574,7 @@ var UPG_PROPERTY_SCHEMA = {
10551
10574
  quality: { type: "string", enum: ["better", "same", "worse", "missing"], description: "Quality comparison. `better` = ours is meaningfully superior. `same` = roughly equivalent. `worse` = theirs is meaningfully superior. `missing` = we have no equivalent." },
10552
10575
  parity_status: { type: "string", enum: ["ahead", "behind", "parity", "unique_to_us", "unique_to_them"], description: "Parity. More granular than `quality`; captures whether the gap is offensive or defensive. `ahead` = we lead. `behind` = they lead. `parity` = equivalent. `unique_to_us` / `unique_to_them` = only one side offers it." },
10553
10576
  last_updated: { type: "string", description: 'ISO date this assessment was last updated. Competitor feature landscapes change quickly. @example "2026-02-15"' },
10554
- source: { type: "string", description: 'Provenance: where this was observed. A changelog, pricing, or docs URL, an analyst report, or a research note. @example "https://www.contentful.com/changelog/"' },
10577
+ source: { type: "string", description: 'Provenance: where this was observed. A changelog, pricing, or docs URL, an analyst report, or a research note. @example "https://docs.larch.example/changelog/"' },
10555
10578
  confidence: {
10556
10579
  type: "assessment",
10557
10580
  scale_id: "confidence_5",
@@ -10577,7 +10600,7 @@ var UPG_PROPERTY_SCHEMA = {
10577
10600
  from_value: { type: "string", description: "Reclassification only. The prior `classification_value` id the competitor was classified as before this move (the superseded cell). Absent for a first-time classification (nothing was superseded)." },
10578
10601
  to_value: { type: "string", description: "Reclassification only. The new `classification_value` id the competitor is classified as after this move (the cell the new classify edge points at)." },
10579
10602
  last_updated: { type: "string", description: 'Provenance: ISO date-time this record was last observed or refreshed. @example "2026-06-13"' },
10580
- source: { type: "string", description: 'Provenance: where this was observed. A changelog, pricing, or docs URL, an analyst report, or a research note. @example "https://www.contentful.com/changelog/"' },
10603
+ source: { type: "string", description: 'Provenance: where this was observed. A changelog, pricing, or docs URL, an analyst report, or a research note. @example "https://docs.larch.example/changelog/"' },
10581
10604
  confidence: {
10582
10605
  type: "assessment",
10583
10606
  scale_id: "confidence_5",
@@ -10717,7 +10740,7 @@ var UPG_PROPERTY_SCHEMA = {
10717
10740
  },
10718
10741
  // DashboardProperties: Dashboard entity.
10719
10742
  dashboard: {
10720
- tool: { type: "string", enum: ["looker", "amplitude", "mixpanel", "posthog", "custom"], description: "Analytics tool hosting this dashboard" },
10743
+ tool: { type: "string", enum: ["looker", "amplitude", "mixpanel", "posthog", "omni", "custom"], description: "Analytics tool hosting this dashboard" },
10721
10744
  url: { type: "string", description: "URL to the live dashboard", modifier: "volatile" },
10722
10745
  audience: { type: "string", description: "Intended audience for this dashboard" },
10723
10746
  element_count: { type: "number", description: "Number of widgets or panels on the dashboard", modifier: "derived" },
@@ -12008,7 +12031,7 @@ var UPG_PROPERTY_SCHEMA = {
12008
12031
  // OperatingLifecycleProperties: An operating_lifecycle: a canonical, ordered (often cyclic) operating process
12009
12032
  operating_lifecycle: {
12010
12033
  cyclic: { type: "boolean", description: "True if the process loops (e.g. Analyze \u2192 Extend \u2192 Plan). The sequence is fully expressed by the stages' `stage_order`; `cyclic` adds the wrap from the last stage back to the first." },
12011
- source: { type: "string", description: 'Origin of the canonical model (e.g. "Sanity official content-ops lifecycle"). Optional provenance; promote to an edge if it names a real `specification`/`document`.' }
12034
+ source: { type: "string", description: 'Origin of the canonical model (e.g. "a published content-ops lifecycle"). Optional provenance; promote to an edge if it names a real `specification`/`document`.' }
12012
12035
  },
12013
12036
  // OperatingStageProperties: An operating_stage: one ordered stage of an `operating_lifecycle`. A product's
12014
12037
  operating_stage: {
@@ -22876,6 +22899,12 @@ var PRODUCT_SPEC_GUIDE = {
22876
22899
  entity_types: ["feature_area", "feature", "epic", "user_story", "task"],
22877
22900
  edge_chain: ["feature_area_contains_feature", "feature_decomposed_into_epic", "epic_specified_by_user_story", "task_implements_user_story"]
22878
22901
  },
22902
+ {
22903
+ name: "Epic Work Items",
22904
+ description: "A bug or a pure engineering/infra task that belongs to one specific epic (not the feature as a whole) attaches directly to that epic, mirroring how task and bug attach at the feature level. Use this when importing a real tracker (Linear/Jira) whose tickets are heterogeneous: keep genuine stories as user_story, but let bugs, spikes, and engineering tasks nest under their epic with their true type instead of being mislabelled to preserve the grouping.",
22905
+ entity_types: ["epic", "task", "bug"],
22906
+ edge_chain: ["epic_decomposes_into_task", "epic_affected_by_bug"]
22907
+ },
22879
22908
  {
22880
22909
  name: "Planning Cadence",
22881
22910
  description: "The cadence axis. Create a planning_cycle (a sprint, iteration, quarter, or PI), nest finer cycles inside a coarse one, schedule the stories that flow through it, and scope the objectives the cycle serves. Scheduling and scoping are deliberate links, not containment: a story keeps its feature/epic parent.",
@@ -29692,7 +29721,7 @@ function isCanonical(text) {
29692
29721
  }
29693
29722
 
29694
29723
  // src/index.ts
29695
- var UPG_VERSION = "0.22.2";
29724
+ var UPG_VERSION = "0.23.1";
29696
29725
  var UPG_FORMAT_VERSION = "0.4.0";
29697
29726
  var MARKDOWN_FORMAT_VERSION = "0.1";
29698
29727
  var UPG_TYPES = getTypes();