@unified-product-graph/core 0.8.2 → 0.8.5
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 +13 -0
- package/dist/index.cjs +69 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +86 -8
- package/dist/index.d.ts +86 -8
- package/dist/index.js +68 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -486,8 +486,8 @@ var UPG_DOMAINS = [
|
|
|
486
486
|
{
|
|
487
487
|
id: "workspace",
|
|
488
488
|
label: "Workspace",
|
|
489
|
-
description: "Spatial thinking spaces for arranging entities, debating decisions, and committing to the graph. Workspaces are transient canvases that sit alongside all other domains, letting you compose and explore relationships before they become permanent graph structure.",
|
|
490
|
-
types: ["workspace"]
|
|
489
|
+
description: "Spatial thinking spaces for arranging entities, debating decisions, and committing to the graph. Workspaces are transient canvases that sit alongside all other domains, letting you compose and explore relationships before they become permanent graph structure. A framework exercise is a structured workspace: one run of a framework (MoSCoW, RICE, Kano, \u2026) applied to a chosen set of entities, with each entity's result recorded on the exercise-to-entity edge rather than the entity itself.",
|
|
490
|
+
types: ["workspace", "framework_exercise"]
|
|
491
491
|
}
|
|
492
492
|
];
|
|
493
493
|
var UPG_ENTITY_TO_DOMAIN = Object.freeze(
|
|
@@ -913,7 +913,8 @@ var UPG_ENTITY_META = [
|
|
|
913
913
|
{ name: "integration_partner", type_id: "ent_311", maturity: "stable", since: "0.1.0" },
|
|
914
914
|
{ name: "partner_revenue_share", type_id: "ent_312", maturity: "stable", since: "0.1.0" },
|
|
915
915
|
// ── Workspace ──
|
|
916
|
-
{ name: "workspace", type_id: "ent_328", maturity: "proposed", since: "0.2.0" }
|
|
916
|
+
{ name: "workspace", type_id: "ent_328", maturity: "proposed", since: "0.2.0" },
|
|
917
|
+
{ name: "framework_exercise", type_id: "ent_350", maturity: "proposed", since: "0.8.4" }
|
|
917
918
|
];
|
|
918
919
|
var UPG_ENTITY_META_BY_NAME = new Map(
|
|
919
920
|
UPG_ENTITY_META.map((m) => [m.name, m])
|
|
@@ -2066,6 +2067,18 @@ var UPG_EDGE_CATALOG = {
|
|
|
2066
2067
|
// universal across the DDD type family. Verbs follow DDD literature:
|
|
2067
2068
|
// aggregate belongs_to context, context contains aggregates.
|
|
2068
2069
|
node_belongs_to_bounded_context: { forward_verb: "belongs_to", reverse_verb: "contains", classification: "cross-domain", source_type: "node", target_type: "bounded_context" },
|
|
2070
|
+
// ── Cross-domain: Framework exercises ────────────────────────────────────────
|
|
2071
|
+
// A framework_exercise is one run of a framework (MoSCoW, RICE, Kano, …) over a
|
|
2072
|
+
// set of entities. It `includes` each entity it touches; the framework's
|
|
2073
|
+
// per-entity result — a MoSCoW bucket, a RICE score, a canvas slot, a funnel
|
|
2074
|
+
// stage — rides on this edge's `properties`, NOT on the entity node. A value
|
|
2075
|
+
// that exists only within a specific exercise is a fact about the relationship,
|
|
2076
|
+
// not the entity, so it lives on the edge (same principle as owner-as-edge).
|
|
2077
|
+
// Polymorphic (`target_type: 'node'`): an exercise can include any entity type,
|
|
2078
|
+
// which closes the feature-only limitation structurally. `carries_properties`
|
|
2079
|
+
// opts this edge into the gated edge-property model. See ADR
|
|
2080
|
+
// 2026-06-02-framework-exercises.
|
|
2081
|
+
framework_exercise_includes_node: { forward_verb: "includes", reverse_verb: "included_in", classification: "cross-domain", source_type: "framework_exercise", target_type: "node", carries_properties: true },
|
|
2069
2082
|
// ── New edges replacing deleted string properties ────────────────────
|
|
2070
2083
|
// Marketing
|
|
2071
2084
|
marketing_strategy_pursues_outcome: { forward_verb: "pursues", reverse_verb: "pursued_by", classification: "cross-domain", source_type: "marketing_strategy", target_type: "outcome" },
|
|
@@ -2695,7 +2708,9 @@ var UPG_POLYMORPHIC_EDGE_KEYS = [
|
|
|
2695
2708
|
"node_owned_by_department",
|
|
2696
2709
|
"node_owned_by_person",
|
|
2697
2710
|
// Universal architecture references
|
|
2698
|
-
"node_belongs_to_bounded_context"
|
|
2711
|
+
"node_belongs_to_bounded_context",
|
|
2712
|
+
// Framework exercises (an exercise can include any entity type)
|
|
2713
|
+
"framework_exercise_includes_node"
|
|
2699
2714
|
];
|
|
2700
2715
|
var _POLY_KEY_SET = new Set(UPG_POLYMORPHIC_EDGE_KEYS);
|
|
2701
2716
|
function isPolymorphicEdge(key) {
|
|
@@ -2705,6 +2720,10 @@ function isPolymorphicEdge(key) {
|
|
|
2705
2720
|
function isRegisteredPolymorphicEdge(key) {
|
|
2706
2721
|
return _POLY_KEY_SET.has(key);
|
|
2707
2722
|
}
|
|
2723
|
+
function edgeCarriesProperties(type) {
|
|
2724
|
+
const def = UPG_EDGE_CATALOG[type];
|
|
2725
|
+
return def?.carries_properties === true;
|
|
2726
|
+
}
|
|
2708
2727
|
|
|
2709
2728
|
// src/catalog/legacy-product-stages.ts
|
|
2710
2729
|
var LEGACY_PRODUCT_STAGES = Object.freeze({
|
|
@@ -3356,7 +3375,13 @@ function canBeChildOf(childType, parentType) {
|
|
|
3356
3375
|
return getValidChildren(parentType).includes(childType);
|
|
3357
3376
|
}
|
|
3358
3377
|
var UPG_CONTAINMENT_FREE_TYPES = /* @__PURE__ */ new Set([
|
|
3359
|
-
"person"
|
|
3378
|
+
"person",
|
|
3379
|
+
// A framework_exercise has no structural parent: it anchors to the entities
|
|
3380
|
+
// it scores via the `framework_exercise_includes_node` edge, not by
|
|
3381
|
+
// containment. Modelling it as a product child would force a containment edge
|
|
3382
|
+
// and read against the whole point of the exercise model (relational, not
|
|
3383
|
+
// hierarchical). Same posture as `person`. See ADR 2026-06-02-framework-exercises.
|
|
3384
|
+
"framework_exercise"
|
|
3360
3385
|
]);
|
|
3361
3386
|
function isContainmentFreeType(entityType) {
|
|
3362
3387
|
return UPG_CONTAINMENT_FREE_TYPES.has(entityType);
|
|
@@ -5658,6 +5683,31 @@ var TEMPLATE_LIFECYCLES = [
|
|
|
5658
5683
|
// ── Phase B: SALES_DEAL (qualified → proposal → negotiation → won/lost) ─────
|
|
5659
5684
|
fromTemplate("deal", SALES_DEAL_TEMPLATE)
|
|
5660
5685
|
];
|
|
5686
|
+
var FRAMEWORK_EXERCISE_LIFECYCLE = {
|
|
5687
|
+
entity_type: "framework_exercise",
|
|
5688
|
+
initial_phase: "draft",
|
|
5689
|
+
terminal_phases: ["archived"],
|
|
5690
|
+
phases: [
|
|
5691
|
+
{
|
|
5692
|
+
id: "draft",
|
|
5693
|
+
label: "Draft",
|
|
5694
|
+
description: "The exercise has been created and entities pulled into scope, but the framework's inputs have not all been filled in yet.",
|
|
5695
|
+
transitions_to: ["active", "archived"]
|
|
5696
|
+
},
|
|
5697
|
+
{
|
|
5698
|
+
id: "active",
|
|
5699
|
+
label: "Active",
|
|
5700
|
+
description: "The current, authoritative run of its framework. Its include edges carry the live results consumers read, rank, and render by.",
|
|
5701
|
+
transitions_to: ["archived"]
|
|
5702
|
+
},
|
|
5703
|
+
{
|
|
5704
|
+
id: "archived",
|
|
5705
|
+
label: "Archived",
|
|
5706
|
+
description: "A past run, retained for provenance. Still queryable but superseded by a newer exercise and hidden from default views. Can be revived to active.",
|
|
5707
|
+
transitions_to: ["active"]
|
|
5708
|
+
}
|
|
5709
|
+
]
|
|
5710
|
+
};
|
|
5661
5711
|
var UPG_LIFECYCLES = [
|
|
5662
5712
|
// Product (root)
|
|
5663
5713
|
PRODUCT_LIFECYCLE,
|
|
@@ -5759,6 +5809,8 @@ var UPG_LIFECYCLES = [
|
|
|
5759
5809
|
// Product & Growth
|
|
5760
5810
|
VARIANT_LIFECYCLE,
|
|
5761
5811
|
GROWTH_CAMPAIGN_LIFECYCLE,
|
|
5812
|
+
// Workspace
|
|
5813
|
+
FRAMEWORK_EXERCISE_LIFECYCLE,
|
|
5762
5814
|
// ── Template-generated lifecycles ─────────────────────────────────
|
|
5763
5815
|
...TEMPLATE_LIFECYCLES
|
|
5764
5816
|
];
|
|
@@ -9948,6 +10000,11 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9948
10000
|
},
|
|
9949
10001
|
methodology: { type: "string", description: "Forecasting methodology used" }
|
|
9950
10002
|
},
|
|
10003
|
+
// FrameworkExerciseProperties: Framework exercise: one run of a framework over a set of entities.
|
|
10004
|
+
framework_exercise: {
|
|
10005
|
+
framework_id: { type: "string", description: "Which framework this exercise runs: a framework id (e.g. 'moscow', 'rice-scoring', 'kano-model'). Resolves against the framework catalog." },
|
|
10006
|
+
inputs_snapshot: { type: "object", description: "Optional frozen copy of the framework's input spec at apply time, so a historical exercise still renders correctly if the framework definition later evolves (inputs added, removed, or rescaled)." }
|
|
10007
|
+
},
|
|
9951
10008
|
// FunnelProperties: Funnel entity.
|
|
9952
10009
|
funnel: {
|
|
9953
10010
|
funnel_type: { type: "string", enum: ["acquisition", "activation", "retention", "revenue", "referral", "custom"], description: "Which stage of the customer lifecycle this funnel measures" },
|
|
@@ -19566,7 +19623,7 @@ var PORTFOLIO_GUIDE = {
|
|
|
19566
19623
|
var WORKSPACE_GUIDE = {
|
|
19567
19624
|
domain_id: "workspace",
|
|
19568
19625
|
anchor_entity: "workspace",
|
|
19569
|
-
creation_sequence: ["workspace"],
|
|
19626
|
+
creation_sequence: ["workspace", "framework_exercise"],
|
|
19570
19627
|
patterns: [],
|
|
19571
19628
|
required_bridges: [],
|
|
19572
19629
|
anti_patterns: [
|
|
@@ -24574,7 +24631,7 @@ var NODE_KEY_ORDER = [
|
|
|
24574
24631
|
"sort_order",
|
|
24575
24632
|
"properties"
|
|
24576
24633
|
];
|
|
24577
|
-
var EDGE_KEY_ORDER = ["id", "source", "target", "type", "mapping_confidence"];
|
|
24634
|
+
var EDGE_KEY_ORDER = ["id", "source", "target", "type", "mapping_confidence", "properties"];
|
|
24578
24635
|
var CROSS_EDGE_KEY_ORDER = ["id", "source", "target", "type", "source_product_id", "target_product_id", "mapping_confidence"];
|
|
24579
24636
|
var PRODUCT_KEY_ORDER = ["id", "title", "description", "stage", "properties"];
|
|
24580
24637
|
function canonicalNode(node) {
|
|
@@ -24586,7 +24643,8 @@ function canonicalNode(node) {
|
|
|
24586
24643
|
}
|
|
24587
24644
|
function canonicalEdge(edge) {
|
|
24588
24645
|
return orderedObject(edge, EDGE_KEY_ORDER, {
|
|
24589
|
-
forceKeys: ["id", "source", "target", "type"]
|
|
24646
|
+
forceKeys: ["id", "source", "target", "type"],
|
|
24647
|
+
openKeys: ["properties"]
|
|
24590
24648
|
});
|
|
24591
24649
|
}
|
|
24592
24650
|
function canonicalCrossEdge(edge) {
|
|
@@ -24740,7 +24798,7 @@ function isCanonical(text) {
|
|
|
24740
24798
|
}
|
|
24741
24799
|
|
|
24742
24800
|
// src/index.ts
|
|
24743
|
-
var UPG_VERSION = "0.8.
|
|
24801
|
+
var UPG_VERSION = "0.8.4";
|
|
24744
24802
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
24745
24803
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
24746
24804
|
var UPG_TYPES = getTypes();
|
|
@@ -24888,6 +24946,7 @@ export {
|
|
|
24888
24946
|
collectSlugsForType,
|
|
24889
24947
|
compareVersions,
|
|
24890
24948
|
computeBodyChecksum,
|
|
24949
|
+
edgeCarriesProperties,
|
|
24891
24950
|
evaluateAntiPatterns,
|
|
24892
24951
|
findInvalidStatusMigrationTargets,
|
|
24893
24952
|
formatUpgText,
|