@unified-product-graph/core 0.23.0 → 0.23.2
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/README.md +1 -1
- package/dist/index.cjs +27 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -21
- package/dist/index.d.ts +43 -21
- package/dist/index.js +27 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/spec/examples/cms-field-guide.upg +24 -24
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
The TypeScript core for the **Unified Product Graph (UPG)**, an open specification that gives product tools a shared vocabulary for entities, edges, and frameworks.
|
|
9
9
|
|
|
10
|
-
320 entity types across 37 domains.
|
|
10
|
+
320 entity types across 37 domains. 1042 typed edges. 46 canonical framework definitions, with more added as each is reviewed.
|
|
11
11
|
|
|
12
12
|
## Install
|
|
13
13
|
|
package/dist/index.cjs
CHANGED
|
@@ -750,7 +750,7 @@ var UPG_DOMAINS = [
|
|
|
750
750
|
{
|
|
751
751
|
id: "foundations",
|
|
752
752
|
label: "Foundations",
|
|
753
|
-
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
|
|
753
|
+
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.",
|
|
754
754
|
types: ["specification", "primitive", "operating_lifecycle", "operating_stage"]
|
|
755
755
|
}
|
|
756
756
|
];
|
|
@@ -1693,8 +1693,14 @@ var UPG_EDGE_CATALOG = {
|
|
|
1693
1693
|
// feature-level edges (same verbs/classification), so `pickCanonicalEdge` /
|
|
1694
1694
|
// `resolveContainmentEdge('epic', 'task'|'bug')` and the adapter import path
|
|
1695
1695
|
// resolve them with no further wiring.
|
|
1696
|
-
|
|
1697
|
-
|
|
1696
|
+
// cross_product_eligible (feedback 9a10be30): an epic is a cross-team planning
|
|
1697
|
+
// unit — its implementing task or affecting bug may live in a different
|
|
1698
|
+
// product's engineering substrate (e.g. a consumer product's epic whose
|
|
1699
|
+
// backend work is tracked in a separate platform/infra graph). Dual-registered
|
|
1700
|
+
// like the objective↔dependency edges: valid within a product AND across
|
|
1701
|
+
// products (endpoints referenced by qualified id).
|
|
1702
|
+
epic_decomposes_into_task: { forward_verb: "decomposes_into", reverse_verb: "implements", classification: "hierarchy", source_type: "epic", target_type: "task", cross_product_eligible: true },
|
|
1703
|
+
epic_affected_by_bug: { forward_verb: "affected_by", reverse_verb: "affects", classification: "hierarchy", source_type: "epic", target_type: "bug", cross_product_eligible: true },
|
|
1698
1704
|
task_has_subtask: { forward_verb: "has_subtask", reverse_verb: "is_subtask_of", classification: "hierarchy", source_type: "task", target_type: "task" },
|
|
1699
1705
|
// ── Planning cadence (0.20.0) ────────────────────────────────────────────────
|
|
1700
1706
|
// The cadence axis. E1 self-nests the interval (a program-increment contains
|
|
@@ -3471,6 +3477,15 @@ var UPG_EDGE_CATALOG = {
|
|
|
3471
3477
|
// by another team's graph within the portfolio (0.17.3 locked predicate).
|
|
3472
3478
|
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 },
|
|
3473
3479
|
dependency_blocks_objective: { forward_verb: "blocks", reverse_verb: "blocked_by", classification: "cross-domain", source_type: "dependency", target_type: "objective", cross_product_eligible: true },
|
|
3480
|
+
// The RESOLVING side, distinct from the two blocking edges above.
|
|
3481
|
+
// `dependency_blocks_objective` names an objective the dependency holds up (the
|
|
3482
|
+
// waiting side); this names the objective whose completion CLEARS the
|
|
3483
|
+
// dependency (the providing side). In a portfolio, a dependency in one
|
|
3484
|
+
// product's graph points at the objective in another product's graph that
|
|
3485
|
+
// delivers the awaited work, instead of recording it only in the free-text
|
|
3486
|
+
// `resolution` property. cross_product_eligible — the resolving objective
|
|
3487
|
+
// lives in another product's graph.
|
|
3488
|
+
dependency_resolved_by_objective: { forward_verb: "resolved_by", reverse_verb: "resolves", classification: "cross-domain", source_type: "dependency", target_type: "objective", cross_product_eligible: true },
|
|
3474
3489
|
// objective / initiative → strategic_question. A planning doc's "Risks & Open
|
|
3475
3490
|
// Questions" section names unresolved coordination questions the plan is
|
|
3476
3491
|
// exposed to (who owns a capability across teams after a reorg). The
|
|
@@ -10731,9 +10746,9 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10731
10746
|
// ClassificationValueProperties: ClassificationValue: a value on a classification axis.
|
|
10732
10747
|
classification_value: {
|
|
10733
10748
|
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." },
|
|
10734
|
-
exemplars: { type: "string[]", description: "Free-text examples of products occupying this value. For queryable occupancy, prefer `competitor` nodes with `classified_as` edges. @example ['
|
|
10749
|
+
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']" },
|
|
10735
10750
|
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.' }, ]" },
|
|
10736
|
-
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: ['
|
|
10751
|
+
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'] }, ]" }
|
|
10737
10752
|
},
|
|
10738
10753
|
// CodeRepositoryProperties: Code repository.
|
|
10739
10754
|
code_repository: {
|
|
@@ -10768,9 +10783,9 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10768
10783
|
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." },
|
|
10769
10784
|
analysis_date: { type: "string", description: 'ISO date conducted. Competitive intelligence decays quickly; track snapshot age. @example "2026-03-15"' },
|
|
10770
10785
|
framework_id: { type: "string", description: 'Framework ID (references `UPGFramework.id`). @example "porter-five-forces", "swot-analysis", "competitive-matrix"' },
|
|
10771
|
-
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-
|
|
10786
|
+
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.' }, ]" },
|
|
10772
10787
|
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"' },
|
|
10773
|
-
source: { type: "string", description: 'Provenance: where this was observed. A changelog, pricing, or docs URL, an analyst report, or a research note. @example "https://
|
|
10788
|
+
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/"' },
|
|
10774
10789
|
confidence: {
|
|
10775
10790
|
type: "assessment",
|
|
10776
10791
|
scale_id: "confidence_5",
|
|
@@ -10798,7 +10813,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10798
10813
|
strengths: { type: "string[]", description: "Bulleted factual strengths. Each item is a short statement, not prose. @example ['Real-time multiplayer canvas', 'Generous free tier']" },
|
|
10799
10814
|
weaknesses: { type: "string[]", description: "Bulleted factual weaknesses: gaps, friction, or capabilities materially below market. @example ['Weak API query capabilities', 'No mobile companion']" },
|
|
10800
10815
|
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"' },
|
|
10801
|
-
source: { type: "string", description: 'Provenance: where this was observed. A changelog, pricing, or docs URL, an analyst report, or a research note. @example "https://
|
|
10816
|
+
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/"' },
|
|
10802
10817
|
confidence: {
|
|
10803
10818
|
type: "assessment",
|
|
10804
10819
|
scale_id: "confidence_5",
|
|
@@ -10820,7 +10835,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10820
10835
|
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." },
|
|
10821
10836
|
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." },
|
|
10822
10837
|
last_updated: { type: "string", description: 'ISO date this assessment was last updated. Competitor feature landscapes change quickly. @example "2026-02-15"' },
|
|
10823
|
-
source: { type: "string", description: 'Provenance: where this was observed. A changelog, pricing, or docs URL, an analyst report, or a research note. @example "https://
|
|
10838
|
+
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/"' },
|
|
10824
10839
|
confidence: {
|
|
10825
10840
|
type: "assessment",
|
|
10826
10841
|
scale_id: "confidence_5",
|
|
@@ -10846,7 +10861,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10846
10861
|
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)." },
|
|
10847
10862
|
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)." },
|
|
10848
10863
|
last_updated: { type: "string", description: 'Provenance: ISO date-time this record was last observed or refreshed. @example "2026-06-13"' },
|
|
10849
|
-
source: { type: "string", description: 'Provenance: where this was observed. A changelog, pricing, or docs URL, an analyst report, or a research note. @example "https://
|
|
10864
|
+
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/"' },
|
|
10850
10865
|
confidence: {
|
|
10851
10866
|
type: "assessment",
|
|
10852
10867
|
scale_id: "confidence_5",
|
|
@@ -12277,7 +12292,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
12277
12292
|
// OperatingLifecycleProperties: An operating_lifecycle: a canonical, ordered (often cyclic) operating process
|
|
12278
12293
|
operating_lifecycle: {
|
|
12279
12294
|
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." },
|
|
12280
|
-
source: { type: "string", description: 'Origin of the canonical model (e.g. "
|
|
12295
|
+
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`.' }
|
|
12281
12296
|
},
|
|
12282
12297
|
// OperatingStageProperties: An operating_stage: one ordered stage of an `operating_lifecycle`. A product's
|
|
12283
12298
|
operating_stage: {
|
|
@@ -29967,7 +29982,7 @@ function isCanonical(text) {
|
|
|
29967
29982
|
}
|
|
29968
29983
|
|
|
29969
29984
|
// src/index.ts
|
|
29970
|
-
var UPG_VERSION = "0.23.
|
|
29985
|
+
var UPG_VERSION = "0.23.2";
|
|
29971
29986
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
29972
29987
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
29973
29988
|
var UPG_TYPES = getTypes();
|