@unified-product-graph/core 0.9.19 → 0.9.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/index.cjs +67 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -2
- package/dist/index.d.ts +62 -2
- package/dist/index.js +64 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,21 @@ This project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [0.9.20] - 2026-06-11
|
|
11
|
+
|
|
12
|
+
**The tree-pattern catalogue is now introspectable and drift-guarded.** A pattern can no longer cite an edge the grammar lacks, and clients can read the catalogue instead of reverse-engineering it.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
- **Two introspection tools** (local + cloud, spec-introspection family, local 121 to 123 / cloud 95 to 97):
|
|
16
|
+
- **`list_tree_patterns`** returns every `get_tree` pattern as a summary row: id, label, the region it is the tree view of, anchor, fallback anchors, natural depth, gap policy, and slot count. Paired with `list_regions`, coverage becomes a queryable diff.
|
|
17
|
+
- **`get_tree_pattern(id)`** returns the full declarative record: region, anchor, fallbacks, gap policy, depth, and the child map resolved to concrete edges. Each parent-to-child slot carries the canonical `via` edge and its `kind`, resolved live from the edge catalogue, so a client reads the real wiring rather than reverse-engineering it from behaviour.
|
|
18
|
+
- **Declarative pattern records.** `UPGTreePattern` gains `region` (ties a pattern to its region and that region's `shape`) and `gap_policy` (`required-children-only` or `all-optional`). Helpers `listTreePatternSummaries`, `describeTreePattern`, and `resolveTreePatternEdges` expose the catalogue from core.
|
|
19
|
+
- **A drift-guard test.** Every pattern's every `(parent -> child)` slot must resolve to a canonical edge in the catalogue. A pattern that cites an ungrounded pair fails the build. This makes the whole class of bug structural (it already caught an `aggregate -> read_model` slot in the 0.9.19 architecture sketch that the grammar does not wire).
|
|
20
|
+
|
|
21
|
+
No entity, domain, region, or edge-count change (entities 315, edges 980); local tools 121 to 123, cloud 95 to 97.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
10
25
|
## [0.9.19] - 2026-06-11
|
|
11
26
|
|
|
12
27
|
**The tree-pattern catalogue covers every tree-shaped region, and `delivery` finally roots at the roadmap.** `get_tree` now offers 11 patterns (was 8), one per hierarchical region.
|
package/dist/index.cjs
CHANGED
|
@@ -113,6 +113,7 @@ __export(index_exports, {
|
|
|
113
113
|
collectSlugsForType: () => collectSlugsForType,
|
|
114
114
|
compareVersions: () => compareVersions,
|
|
115
115
|
computeBodyChecksum: () => computeBodyChecksum,
|
|
116
|
+
describeTreePattern: () => describeTreePattern,
|
|
116
117
|
edgeCarriesProperties: () => edgeCarriesProperties,
|
|
117
118
|
evaluateAntiPatterns: () => evaluateAntiPatterns,
|
|
118
119
|
findInvalidStatusMigrationTargets: () => findInvalidStatusMigrationTargets,
|
|
@@ -180,6 +181,7 @@ __export(index_exports, {
|
|
|
180
181
|
isSubSequenceStep: () => isSubSequenceStep,
|
|
181
182
|
isUPGDocument: () => isUPGDocument,
|
|
182
183
|
listStatusMigrations: () => listStatusMigrations,
|
|
184
|
+
listTreePatternSummaries: () => listTreePatternSummaries,
|
|
183
185
|
migrateEdge: () => migrateEdge,
|
|
184
186
|
migrateNode: () => migrateNode,
|
|
185
187
|
migrateNodeProperties: () => migrateNodeProperties,
|
|
@@ -193,6 +195,7 @@ __export(index_exports, {
|
|
|
193
195
|
resolveEntityType: () => resolveEntityType,
|
|
194
196
|
resolveLabel: () => resolveLabel,
|
|
195
197
|
resolveSlugCollision: () => resolveSlugCollision,
|
|
198
|
+
resolveTreePatternEdges: () => resolveTreePatternEdges,
|
|
196
199
|
ringOrderedDomainIds: () => ringOrderedDomainIds,
|
|
197
200
|
rotateSlug: () => rotateSlug,
|
|
198
201
|
serializeCanonical: () => serializeCanonical,
|
|
@@ -19879,6 +19882,8 @@ var UPG_TREE_PATTERNS = [
|
|
|
19879
19882
|
label: "Opportunity Solution Tree",
|
|
19880
19883
|
description: "A desired outcome branching into the opportunities under it, the solutions that address them, and the hypotheses + experiment plans that validate them (Teresa Torres).",
|
|
19881
19884
|
framework_id: "opportunity-solution-tree",
|
|
19885
|
+
region: "discovery_research_validation",
|
|
19886
|
+
gap_policy: "required-children-only",
|
|
19882
19887
|
anchor_type: "outcome",
|
|
19883
19888
|
fallback_anchors: ["desired_outcome", "opportunity"],
|
|
19884
19889
|
child_map: {
|
|
@@ -19895,6 +19900,8 @@ var UPG_TREE_PATTERNS = [
|
|
|
19895
19900
|
label: "Objectives and Key Results",
|
|
19896
19901
|
description: "Strategic themes containing objectives, each measured by its key results and the metric that quantifies them (John Doerr).",
|
|
19897
19902
|
framework_id: "okr-framework",
|
|
19903
|
+
region: "strategy_outcomes",
|
|
19904
|
+
gap_policy: "required-children-only",
|
|
19898
19905
|
anchor_type: "strategic_theme",
|
|
19899
19906
|
fallback_anchors: ["objective"],
|
|
19900
19907
|
child_map: {
|
|
@@ -19908,6 +19915,8 @@ var UPG_TREE_PATTERNS = [
|
|
|
19908
19915
|
id: "user",
|
|
19909
19916
|
label: "User chain",
|
|
19910
19917
|
description: "A persona and the jobs it pursues, branching into the needs and desired outcomes behind them.",
|
|
19918
|
+
region: "users_needs",
|
|
19919
|
+
gap_policy: "required-children-only",
|
|
19911
19920
|
anchor_type: "persona",
|
|
19912
19921
|
fallback_anchors: ["job"],
|
|
19913
19922
|
child_map: {
|
|
@@ -19920,6 +19929,8 @@ var UPG_TREE_PATTERNS = [
|
|
|
19920
19929
|
id: "product",
|
|
19921
19930
|
label: "Product breakdown",
|
|
19922
19931
|
description: "The product organised into feature areas, then features, and the optional epic + user story tiers beneath them.",
|
|
19932
|
+
region: "product_delivery",
|
|
19933
|
+
gap_policy: "required-children-only",
|
|
19923
19934
|
anchor_type: "product",
|
|
19924
19935
|
fallback_anchors: ["feature_area", "feature"],
|
|
19925
19936
|
child_map: {
|
|
@@ -19935,6 +19946,8 @@ var UPG_TREE_PATTERNS = [
|
|
|
19935
19946
|
label: "Validation chain",
|
|
19936
19947
|
description: "A hypothesis through its experiment plan, the experiment (or its runs), and the learning it produced.",
|
|
19937
19948
|
framework_id: "build-measure-learn",
|
|
19949
|
+
region: "discovery_research_validation",
|
|
19950
|
+
gap_policy: "required-children-only",
|
|
19938
19951
|
anchor_type: "hypothesis",
|
|
19939
19952
|
fallback_anchors: ["experiment_plan", "experiment"],
|
|
19940
19953
|
child_map: {
|
|
@@ -19949,6 +19962,8 @@ var UPG_TREE_PATTERNS = [
|
|
|
19949
19962
|
id: "strategy",
|
|
19950
19963
|
label: "Strategy cascade",
|
|
19951
19964
|
description: "Vision and mission into the strategic themes (bets), the initiatives that pursue them, and the outcomes they drive. Themes are polymorphically parented: they hang off vision, the product, or a strategic pillar, whichever the graph wired.",
|
|
19965
|
+
region: "strategy_outcomes",
|
|
19966
|
+
gap_policy: "required-children-only",
|
|
19952
19967
|
anchor_type: "vision",
|
|
19953
19968
|
fallback_anchors: ["product", "strategic_theme"],
|
|
19954
19969
|
child_map: {
|
|
@@ -19965,6 +19980,8 @@ var UPG_TREE_PATTERNS = [
|
|
|
19965
19980
|
id: "feature_areas",
|
|
19966
19981
|
label: "Feature areas",
|
|
19967
19982
|
description: "Feature areas and the features they contain.",
|
|
19983
|
+
region: "product_delivery",
|
|
19984
|
+
gap_policy: "all-optional",
|
|
19968
19985
|
anchor_type: "feature_area",
|
|
19969
19986
|
fallback_anchors: ["feature"],
|
|
19970
19987
|
child_map: {
|
|
@@ -19976,6 +19993,8 @@ var UPG_TREE_PATTERNS = [
|
|
|
19976
19993
|
id: "delivery",
|
|
19977
19994
|
label: "Delivery roadmap",
|
|
19978
19995
|
description: "How product work is scheduled and shipped: the roadmap and its themes/items, the releases they schedule, the features (and the changelog + bugs) those releases deliver, and the feature areas a theme spans. Optional epic + user story tiers appear on request.",
|
|
19996
|
+
region: "product_delivery",
|
|
19997
|
+
gap_policy: "all-optional",
|
|
19979
19998
|
anchor_type: "roadmap",
|
|
19980
19999
|
// Fallback is the product alone: a graph with no roadmap roots at the
|
|
19981
20000
|
// product (product -> release -> feature), reported as anchor_resolved_from:
|
|
@@ -20004,6 +20023,8 @@ var UPG_TREE_PATTERNS = [
|
|
|
20004
20023
|
id: "architecture",
|
|
20005
20024
|
label: "Architecture",
|
|
20006
20025
|
description: "The engineering platform: services and the API contracts, endpoints, schemas, queues, deployments, and dependencies they own, grouped by bounded context, with domain aggregates and their members. A DAG (a schema or queue shared by several services renders once, then as a reference).",
|
|
20026
|
+
region: "engineering_platform",
|
|
20027
|
+
gap_policy: "all-optional",
|
|
20007
20028
|
anchor_type: "service",
|
|
20008
20029
|
fallback_anchors: ["bounded_context"],
|
|
20009
20030
|
child_map: {
|
|
@@ -20027,7 +20048,7 @@ var UPG_TREE_PATTERNS = [
|
|
|
20027
20048
|
opt("library_dependency"),
|
|
20028
20049
|
opt("feature_flag")
|
|
20029
20050
|
],
|
|
20030
|
-
aggregate: [opt("domain_entity"), opt("value_object"), opt("command"), opt("
|
|
20051
|
+
aggregate: [opt("domain_entity"), opt("value_object"), opt("command"), opt("domain_event")]
|
|
20031
20052
|
},
|
|
20032
20053
|
natural_depth: 3
|
|
20033
20054
|
},
|
|
@@ -20035,6 +20056,8 @@ var UPG_TREE_PATTERNS = [
|
|
|
20035
20056
|
id: "journey",
|
|
20036
20057
|
label: "User journey",
|
|
20037
20058
|
description: "A user journey over time: its phases and steps, the actions within each step, and the screens those steps surface. Falls back to a user_flow when journeys are not yet mapped.",
|
|
20059
|
+
region: "experience_design_brand",
|
|
20060
|
+
gap_policy: "all-optional",
|
|
20038
20061
|
anchor_type: "user_journey",
|
|
20039
20062
|
fallback_anchors: ["user_flow"],
|
|
20040
20063
|
child_map: {
|
|
@@ -20050,6 +20073,8 @@ var UPG_TREE_PATTERNS = [
|
|
|
20050
20073
|
id: "design_system",
|
|
20051
20074
|
label: "Design system",
|
|
20052
20075
|
description: "A design system broken into its components, their nested sub-components (atom to molecule to organism), and the design tokens they consume.",
|
|
20076
|
+
region: "experience_design_brand",
|
|
20077
|
+
gap_policy: "all-optional",
|
|
20053
20078
|
anchor_type: "design_system",
|
|
20054
20079
|
fallback_anchors: ["design_component"],
|
|
20055
20080
|
child_map: {
|
|
@@ -20065,6 +20090,43 @@ var UPG_TREE_PATTERNS_BY_ID = Object.fromEntries(
|
|
|
20065
20090
|
function getTreePattern(id) {
|
|
20066
20091
|
return UPG_TREE_PATTERNS_BY_ID[id];
|
|
20067
20092
|
}
|
|
20093
|
+
function resolvePatternEdge(source, target) {
|
|
20094
|
+
for (const [id, def] of Object.entries(UPG_EDGE_CATALOG)) {
|
|
20095
|
+
if (def.source_type === source && def.target_type === target) {
|
|
20096
|
+
return { via: id, kind: def.classification };
|
|
20097
|
+
}
|
|
20098
|
+
}
|
|
20099
|
+
return null;
|
|
20100
|
+
}
|
|
20101
|
+
function resolveTreePatternEdges(pattern) {
|
|
20102
|
+
const out = [];
|
|
20103
|
+
for (const [parent, children] of Object.entries(pattern.child_map)) {
|
|
20104
|
+
for (const c of children) {
|
|
20105
|
+
const e = resolvePatternEdge(parent, c.type);
|
|
20106
|
+
out.push({ parent, child: c.type, via: e?.via ?? null, kind: e?.kind ?? null, required: !!c.required });
|
|
20107
|
+
}
|
|
20108
|
+
}
|
|
20109
|
+
return out;
|
|
20110
|
+
}
|
|
20111
|
+
function describeTreePattern(id) {
|
|
20112
|
+
const p = getTreePattern(id);
|
|
20113
|
+
if (!p) return void 0;
|
|
20114
|
+
return { ...p, fallback_anchors: [...p.fallback_anchors], edges: resolveTreePatternEdges(p) };
|
|
20115
|
+
}
|
|
20116
|
+
function listTreePatternSummaries() {
|
|
20117
|
+
return UPG_TREE_PATTERNS.map((p) => ({
|
|
20118
|
+
id: p.id,
|
|
20119
|
+
label: p.label,
|
|
20120
|
+
description: p.description,
|
|
20121
|
+
framework_id: p.framework_id,
|
|
20122
|
+
region: p.region,
|
|
20123
|
+
anchor_type: p.anchor_type,
|
|
20124
|
+
fallback_anchors: [...p.fallback_anchors],
|
|
20125
|
+
natural_depth: p.natural_depth,
|
|
20126
|
+
gap_policy: p.gap_policy,
|
|
20127
|
+
slot_count: Object.values(p.child_map).reduce((n, cs) => n + cs.length, 0)
|
|
20128
|
+
}));
|
|
20129
|
+
}
|
|
20068
20130
|
|
|
20069
20131
|
// src/presentation/area-taxonomy.ts
|
|
20070
20132
|
var UPG_AREA_TAXONOMY = [
|
|
@@ -28369,7 +28431,7 @@ function isCanonical(text) {
|
|
|
28369
28431
|
}
|
|
28370
28432
|
|
|
28371
28433
|
// src/index.ts
|
|
28372
|
-
var UPG_VERSION = "0.9.
|
|
28434
|
+
var UPG_VERSION = "0.9.20";
|
|
28373
28435
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
28374
28436
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
28375
28437
|
var UPG_TYPES = getTypes();
|
|
@@ -28527,6 +28589,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
28527
28589
|
collectSlugsForType,
|
|
28528
28590
|
compareVersions,
|
|
28529
28591
|
computeBodyChecksum,
|
|
28592
|
+
describeTreePattern,
|
|
28530
28593
|
edgeCarriesProperties,
|
|
28531
28594
|
evaluateAntiPatterns,
|
|
28532
28595
|
findInvalidStatusMigrationTargets,
|
|
@@ -28594,6 +28657,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
28594
28657
|
isSubSequenceStep,
|
|
28595
28658
|
isUPGDocument,
|
|
28596
28659
|
listStatusMigrations,
|
|
28660
|
+
listTreePatternSummaries,
|
|
28597
28661
|
migrateEdge,
|
|
28598
28662
|
migrateNode,
|
|
28599
28663
|
migrateNodeProperties,
|
|
@@ -28607,6 +28671,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
28607
28671
|
resolveEntityType,
|
|
28608
28672
|
resolveLabel,
|
|
28609
28673
|
resolveSlugCollision,
|
|
28674
|
+
resolveTreePatternEdges,
|
|
28610
28675
|
ringOrderedDomainIds,
|
|
28611
28676
|
rotateSlug,
|
|
28612
28677
|
serializeCanonical,
|