@unified-product-graph/core 0.10.1 → 0.10.3
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.cjs +65 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -2
- package/dist/index.d.ts +34 -2
- package/dist/index.js +65 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -666,6 +666,13 @@ declare const UPG_EDGE_CATALOG: {
|
|
|
666
666
|
source_type: string;
|
|
667
667
|
target_type: string;
|
|
668
668
|
};
|
|
669
|
+
node_classified_as_classification_value: {
|
|
670
|
+
forward_verb: string;
|
|
671
|
+
reverse_verb: string;
|
|
672
|
+
classification: "semantic";
|
|
673
|
+
source_type: string;
|
|
674
|
+
target_type: string;
|
|
675
|
+
};
|
|
669
676
|
persona_anti_fit_for_classification_value: {
|
|
670
677
|
forward_verb: string;
|
|
671
678
|
reverse_verb: string;
|
|
@@ -7208,7 +7215,7 @@ interface UPGProduct {
|
|
|
7208
7215
|
/** Product lifecycle stages. Covers the full arc from napkin idea to end-of-life. */
|
|
7209
7216
|
type UPGProductStage = 'concept' | 'validation' | 'build' | 'beta' | 'launch' | 'growth' | 'mature' | 'maintenance' | 'sunset';
|
|
7210
7217
|
/** The set of valid cross-product relationship types */
|
|
7211
|
-
type UPGCrossEdgeType = 'shares_persona' | 'shares_competitor' | 'shares_metric' | 'depends_on_product' | 'cannibalises' | 'succeeds' | 'hosts' | 'contributes_to' | 'instance_of' | 'area_serves_persona' | 'area_targets_market_segment' | 'rolls_up_to' | 'product_implements_specification' | 'product_exposes_specification' | 'feature_conforms_to_specification' | 'api_contract_speaks_specification' | 'product_exposes_primitive' | 'feature_manipulates_primitive' | 'primitive_stored_as_data_type' | 'feature_rivals_competitor_feature' | 'competitor_signal_maps_to_feature' | 'competitor_signal_surfaces_opportunity';
|
|
7218
|
+
type UPGCrossEdgeType = 'shares_persona' | 'shares_competitor' | 'shares_metric' | 'depends_on_product' | 'cannibalises' | 'succeeds' | 'hosts' | 'contributes_to' | 'instance_of' | 'area_serves_persona' | 'area_targets_market_segment' | 'rolls_up_to' | 'product_implements_specification' | 'product_exposes_specification' | 'feature_conforms_to_specification' | 'api_contract_speaks_specification' | 'product_exposes_primitive' | 'feature_manipulates_primitive' | 'primitive_stored_as_data_type' | 'feature_rivals_competitor_feature' | 'competitor_signal_maps_to_feature' | 'competitor_signal_surfaces_opportunity' | 'competitor_classified_as_classification_value' | 'node_classified_as_classification_value';
|
|
7212
7219
|
/**
|
|
7213
7220
|
* Runtime-checkable list of valid cross-product edge types. Mirrors
|
|
7214
7221
|
* `UPGCrossEdgeType` for use in validators and writers that need to test
|
|
@@ -8657,6 +8664,25 @@ type UPGPropertyMigration = {
|
|
|
8657
8664
|
reset_value?: string;
|
|
8658
8665
|
/** Human-readable explanation surfaced in load-time warnings. */
|
|
8659
8666
|
reason: string;
|
|
8667
|
+
} | {
|
|
8668
|
+
/**
|
|
8669
|
+
* Reshape a bare numeric property into a `UPGAssessment` object
|
|
8670
|
+
* (`{ value, label, scale_id }`). For the v0.10.0 property-registry
|
|
8671
|
+
* correction (#43): interfaces that always declared `UPGAssessment` were
|
|
8672
|
+
* generated loosely, so pre-0.10.0 graphs stored a bare number (e.g.
|
|
8673
|
+
* `market_trend.impact: 4`). This wraps that number on its canonical scale,
|
|
8674
|
+
* deriving the qualitative `label` from the scale's points. Idempotent: a
|
|
8675
|
+
* value that is already an object (assessment) passes through untouched.
|
|
8676
|
+
*/
|
|
8677
|
+
kind: 'reshape_value_to_assessment';
|
|
8678
|
+
/** The entity type this rule applies to (or `'*'` for all types). */
|
|
8679
|
+
type: string;
|
|
8680
|
+
/** Key inside `properties` whose bare number is wrapped (stays in the bag). */
|
|
8681
|
+
property: string;
|
|
8682
|
+
/** The assessment scale to label the value on (e.g. `impact_5`, `importance_5`). */
|
|
8683
|
+
scale_id: string;
|
|
8684
|
+
/** Human-readable explanation surfaced in load-time warnings. */
|
|
8685
|
+
reason: string;
|
|
8660
8686
|
};
|
|
8661
8687
|
/**
|
|
8662
8688
|
* Version-scoped property migrations. Same convention as `UPG_MIGRATIONS`:
|
|
@@ -8688,6 +8714,12 @@ type UPGPropertyMigrationChange = {
|
|
|
8688
8714
|
property: string;
|
|
8689
8715
|
to_property?: string;
|
|
8690
8716
|
value_changed: boolean;
|
|
8717
|
+
} | {
|
|
8718
|
+
kind: 'reshaped_to_assessment';
|
|
8719
|
+
property: string;
|
|
8720
|
+
scale_id: string;
|
|
8721
|
+
value: number;
|
|
8722
|
+
label: string;
|
|
8691
8723
|
};
|
|
8692
8724
|
/**
|
|
8693
8725
|
* Apply property migrations to a single node. Returns the (possibly new) node
|
|
@@ -21413,7 +21445,7 @@ declare function isCanonical(text: string): boolean;
|
|
|
21413
21445
|
* it stamps the `upg_version` field of every `.upg` file written by the SDK.
|
|
21414
21446
|
* The `check:version-lockstep` gate enforces this at release time.
|
|
21415
21447
|
*/
|
|
21416
|
-
declare const UPG_VERSION: "0.10.
|
|
21448
|
+
declare const UPG_VERSION: "0.10.3";
|
|
21417
21449
|
/**
|
|
21418
21450
|
* The `.upg` JSON document format version. Written to the `upg_version` field.
|
|
21419
21451
|
* Evolves independently from `UPG_VERSION` (the catalogue version).
|
package/dist/index.d.ts
CHANGED
|
@@ -666,6 +666,13 @@ declare const UPG_EDGE_CATALOG: {
|
|
|
666
666
|
source_type: string;
|
|
667
667
|
target_type: string;
|
|
668
668
|
};
|
|
669
|
+
node_classified_as_classification_value: {
|
|
670
|
+
forward_verb: string;
|
|
671
|
+
reverse_verb: string;
|
|
672
|
+
classification: "semantic";
|
|
673
|
+
source_type: string;
|
|
674
|
+
target_type: string;
|
|
675
|
+
};
|
|
669
676
|
persona_anti_fit_for_classification_value: {
|
|
670
677
|
forward_verb: string;
|
|
671
678
|
reverse_verb: string;
|
|
@@ -7208,7 +7215,7 @@ interface UPGProduct {
|
|
|
7208
7215
|
/** Product lifecycle stages. Covers the full arc from napkin idea to end-of-life. */
|
|
7209
7216
|
type UPGProductStage = 'concept' | 'validation' | 'build' | 'beta' | 'launch' | 'growth' | 'mature' | 'maintenance' | 'sunset';
|
|
7210
7217
|
/** The set of valid cross-product relationship types */
|
|
7211
|
-
type UPGCrossEdgeType = 'shares_persona' | 'shares_competitor' | 'shares_metric' | 'depends_on_product' | 'cannibalises' | 'succeeds' | 'hosts' | 'contributes_to' | 'instance_of' | 'area_serves_persona' | 'area_targets_market_segment' | 'rolls_up_to' | 'product_implements_specification' | 'product_exposes_specification' | 'feature_conforms_to_specification' | 'api_contract_speaks_specification' | 'product_exposes_primitive' | 'feature_manipulates_primitive' | 'primitive_stored_as_data_type' | 'feature_rivals_competitor_feature' | 'competitor_signal_maps_to_feature' | 'competitor_signal_surfaces_opportunity';
|
|
7218
|
+
type UPGCrossEdgeType = 'shares_persona' | 'shares_competitor' | 'shares_metric' | 'depends_on_product' | 'cannibalises' | 'succeeds' | 'hosts' | 'contributes_to' | 'instance_of' | 'area_serves_persona' | 'area_targets_market_segment' | 'rolls_up_to' | 'product_implements_specification' | 'product_exposes_specification' | 'feature_conforms_to_specification' | 'api_contract_speaks_specification' | 'product_exposes_primitive' | 'feature_manipulates_primitive' | 'primitive_stored_as_data_type' | 'feature_rivals_competitor_feature' | 'competitor_signal_maps_to_feature' | 'competitor_signal_surfaces_opportunity' | 'competitor_classified_as_classification_value' | 'node_classified_as_classification_value';
|
|
7212
7219
|
/**
|
|
7213
7220
|
* Runtime-checkable list of valid cross-product edge types. Mirrors
|
|
7214
7221
|
* `UPGCrossEdgeType` for use in validators and writers that need to test
|
|
@@ -8657,6 +8664,25 @@ type UPGPropertyMigration = {
|
|
|
8657
8664
|
reset_value?: string;
|
|
8658
8665
|
/** Human-readable explanation surfaced in load-time warnings. */
|
|
8659
8666
|
reason: string;
|
|
8667
|
+
} | {
|
|
8668
|
+
/**
|
|
8669
|
+
* Reshape a bare numeric property into a `UPGAssessment` object
|
|
8670
|
+
* (`{ value, label, scale_id }`). For the v0.10.0 property-registry
|
|
8671
|
+
* correction (#43): interfaces that always declared `UPGAssessment` were
|
|
8672
|
+
* generated loosely, so pre-0.10.0 graphs stored a bare number (e.g.
|
|
8673
|
+
* `market_trend.impact: 4`). This wraps that number on its canonical scale,
|
|
8674
|
+
* deriving the qualitative `label` from the scale's points. Idempotent: a
|
|
8675
|
+
* value that is already an object (assessment) passes through untouched.
|
|
8676
|
+
*/
|
|
8677
|
+
kind: 'reshape_value_to_assessment';
|
|
8678
|
+
/** The entity type this rule applies to (or `'*'` for all types). */
|
|
8679
|
+
type: string;
|
|
8680
|
+
/** Key inside `properties` whose bare number is wrapped (stays in the bag). */
|
|
8681
|
+
property: string;
|
|
8682
|
+
/** The assessment scale to label the value on (e.g. `impact_5`, `importance_5`). */
|
|
8683
|
+
scale_id: string;
|
|
8684
|
+
/** Human-readable explanation surfaced in load-time warnings. */
|
|
8685
|
+
reason: string;
|
|
8660
8686
|
};
|
|
8661
8687
|
/**
|
|
8662
8688
|
* Version-scoped property migrations. Same convention as `UPG_MIGRATIONS`:
|
|
@@ -8688,6 +8714,12 @@ type UPGPropertyMigrationChange = {
|
|
|
8688
8714
|
property: string;
|
|
8689
8715
|
to_property?: string;
|
|
8690
8716
|
value_changed: boolean;
|
|
8717
|
+
} | {
|
|
8718
|
+
kind: 'reshaped_to_assessment';
|
|
8719
|
+
property: string;
|
|
8720
|
+
scale_id: string;
|
|
8721
|
+
value: number;
|
|
8722
|
+
label: string;
|
|
8691
8723
|
};
|
|
8692
8724
|
/**
|
|
8693
8725
|
* Apply property migrations to a single node. Returns the (possibly new) node
|
|
@@ -21413,7 +21445,7 @@ declare function isCanonical(text: string): boolean;
|
|
|
21413
21445
|
* it stamps the `upg_version` field of every `.upg` file written by the SDK.
|
|
21414
21446
|
* The `check:version-lockstep` gate enforces this at release time.
|
|
21415
21447
|
*/
|
|
21416
|
-
declare const UPG_VERSION: "0.10.
|
|
21448
|
+
declare const UPG_VERSION: "0.10.3";
|
|
21417
21449
|
/**
|
|
21418
21450
|
* The `.upg` JSON document format version. Written to the `upg_version` field.
|
|
21419
21451
|
* Evolves independently from `UPG_VERSION` (the catalogue version).
|
package/dist/index.js
CHANGED
|
@@ -1145,7 +1145,17 @@ var UPG_EDGE_CATALOG = {
|
|
|
1145
1145
|
// would be a separate catalog-mechanic change).
|
|
1146
1146
|
competitive_analysis_dimensioned_by_classification_axis: { forward_verb: "dimensioned_by", reverse_verb: "dimensions", classification: "hierarchy", source_type: "competitive_analysis", target_type: "classification_axis" },
|
|
1147
1147
|
classification_axis_includes_classification_value: { forward_verb: "includes", reverse_verb: "value_of", classification: "hierarchy", source_type: "classification_axis", target_type: "classification_value" },
|
|
1148
|
+
// 0.10.2: also dual-registered as a cross-edge (UPG_CROSS_EDGE_TYPES) so a
|
|
1149
|
+
// competitor can be classified directly against a `registry/{classification_value}`
|
|
1150
|
+
// canonical, eliminating the per-graph taxonomy node. Within-graph (the catalogue
|
|
1151
|
+
// case) here; cross-product against the registry canonical via create_cross_product_edge.
|
|
1148
1152
|
competitor_classified_as_classification_value: { forward_verb: "classified_as", reverse_verb: "classification_of", classification: "semantic", source_type: "competitor", target_type: "classification_value" },
|
|
1153
|
+
// 0.10.3: the polymorphic, type-agnostic sibling. ANY node (a feature, a
|
|
1154
|
+
// product, a market_segment) classified against a classification_value, so
|
|
1155
|
+
// classification is not welded to the competitor type. Also dual-registered as
|
|
1156
|
+
// a cross-edge for the registry-canonical case. source_type:'node' (wildcard);
|
|
1157
|
+
// listed in UPG_POLYMORPHIC_EDGE_KEYS.
|
|
1158
|
+
node_classified_as_classification_value: { forward_verb: "classified_as", reverse_verb: "classification_of", classification: "semantic", source_type: "node", target_type: "classification_value" },
|
|
1149
1159
|
persona_anti_fit_for_classification_value: { forward_verb: "is_anti_fit_for", reverse_verb: "should_not_be_picked_by", classification: "semantic", source_type: "persona", target_type: "classification_value" },
|
|
1150
1160
|
persona_anti_fit_for_product: { forward_verb: "is_anti_fit_for", reverse_verb: "should_not_be_picked_by", classification: "semantic", source_type: "persona", target_type: "product" },
|
|
1151
1161
|
persona_anti_fit_for_competitor: { forward_verb: "is_anti_fit_for", reverse_verb: "should_not_be_picked_by", classification: "semantic", source_type: "persona", target_type: "competitor" },
|
|
@@ -2983,7 +2993,9 @@ var UPG_POLYMORPHIC_EDGE_KEYS = [
|
|
|
2983
2993
|
// Universal architecture references
|
|
2984
2994
|
"node_belongs_to_bounded_context",
|
|
2985
2995
|
// Framework exercises (an exercise can include any entity type)
|
|
2986
|
-
"framework_exercise_includes_node"
|
|
2996
|
+
"framework_exercise_includes_node",
|
|
2997
|
+
// Universal classification (any node classified against a classification_value)
|
|
2998
|
+
"node_classified_as_classification_value"
|
|
2987
2999
|
];
|
|
2988
3000
|
var _POLY_KEY_SET = new Set(UPG_POLYMORPHIC_EDGE_KEYS);
|
|
2989
3001
|
function isPolymorphicEdge(key) {
|
|
@@ -3040,7 +3052,9 @@ var UPG_CROSS_EDGE_TYPES = [
|
|
|
3040
3052
|
"primitive_stored_as_data_type",
|
|
3041
3053
|
"feature_rivals_competitor_feature",
|
|
3042
3054
|
"competitor_signal_maps_to_feature",
|
|
3043
|
-
"competitor_signal_surfaces_opportunity"
|
|
3055
|
+
"competitor_signal_surfaces_opportunity",
|
|
3056
|
+
"competitor_classified_as_classification_value",
|
|
3057
|
+
"node_classified_as_classification_value"
|
|
3044
3058
|
];
|
|
3045
3059
|
var REGISTRY_PRODUCT_ID = "registry";
|
|
3046
3060
|
|
|
@@ -7250,6 +7264,34 @@ function getDeprecatedTypes() {
|
|
|
7250
7264
|
return deprecated;
|
|
7251
7265
|
}
|
|
7252
7266
|
var UPG_PROPERTY_MIGRATIONS = {
|
|
7267
|
+
// ── v0.10.2: market_intelligence number -> assessment reshape ──────────────
|
|
7268
|
+
//
|
|
7269
|
+
// The v0.10.0 property-registry generator fix (#43) corrected several property
|
|
7270
|
+
// types that interfaces already declared as `UPGAssessment` but the generator
|
|
7271
|
+
// had emitted loosely. A pre-0.10.0 graph that stored a bare number for
|
|
7272
|
+
// `market_trend.impact` / `relevance` is now invalid (the schema wants
|
|
7273
|
+
// `{value,label}`). These rules wrap the bare number on its canonical scale so
|
|
7274
|
+
// the migration is one command, not a hand-reshape. The enum tightenings the
|
|
7275
|
+
// same #43 fix surfaced (data_flow.direction, integration_pattern.pattern_type,
|
|
7276
|
+
// api_contract.protocol, service.service_type) already have rules under 0.9.12;
|
|
7277
|
+
// 0.10.2 also makes ALL of them visible to validate_graph (they were applied by
|
|
7278
|
+
// migrate_properties but never surfaced as a fixable drift).
|
|
7279
|
+
"0.10.2": [
|
|
7280
|
+
{
|
|
7281
|
+
kind: "reshape_value_to_assessment",
|
|
7282
|
+
type: "market_trend",
|
|
7283
|
+
property: "impact",
|
|
7284
|
+
scale_id: "impact_5",
|
|
7285
|
+
reason: "market_trend.impact is a UPGAssessment (impact_5); the 0.10.0 generator fix (#43) tightened it from a bare number. A legacy numeric value wraps to {value,label} on impact_5."
|
|
7286
|
+
},
|
|
7287
|
+
{
|
|
7288
|
+
kind: "reshape_value_to_assessment",
|
|
7289
|
+
type: "market_trend",
|
|
7290
|
+
property: "relevance",
|
|
7291
|
+
scale_id: "importance_5",
|
|
7292
|
+
reason: "market_trend.relevance is a UPGAssessment (importance_5); the 0.10.0 generator fix (#43) tightened it from a bare number. A legacy numeric value wraps to {value,label} on importance_5."
|
|
7293
|
+
}
|
|
7294
|
+
],
|
|
7253
7295
|
// ── v0.9.14: drop the key_result kr_status / status twin (A2) ──────────────
|
|
7254
7296
|
//
|
|
7255
7297
|
// key_result carried BOTH a lifecycle `status` and a `kr_status` property with
|
|
@@ -7822,6 +7864,26 @@ function migrateNodeProperties(node, fromVersion, toVersion) {
|
|
|
7822
7864
|
mutated = true;
|
|
7823
7865
|
break;
|
|
7824
7866
|
}
|
|
7867
|
+
case "reshape_value_to_assessment": {
|
|
7868
|
+
const props = workingNode.properties;
|
|
7869
|
+
if (!props || !(m.property in props)) break;
|
|
7870
|
+
const oldValue = props[m.property];
|
|
7871
|
+
let num = null;
|
|
7872
|
+
if (typeof oldValue === "number" && Number.isFinite(oldValue)) num = oldValue;
|
|
7873
|
+
else if (typeof oldValue === "string" && oldValue.trim() !== "" && Number.isFinite(Number(oldValue))) {
|
|
7874
|
+
num = Number(oldValue);
|
|
7875
|
+
}
|
|
7876
|
+
if (num === null) break;
|
|
7877
|
+
const label = getScale(m.scale_id)?.points.find((p) => p.value === num)?.label ?? String(num);
|
|
7878
|
+
const nextProps = {
|
|
7879
|
+
...props,
|
|
7880
|
+
[m.property]: { value: num, label, scale_id: m.scale_id }
|
|
7881
|
+
};
|
|
7882
|
+
workingNode.properties = nextProps;
|
|
7883
|
+
mutated = true;
|
|
7884
|
+
changes.push({ kind: "reshaped_to_assessment", property: m.property, scale_id: m.scale_id, value: num, label });
|
|
7885
|
+
break;
|
|
7886
|
+
}
|
|
7825
7887
|
}
|
|
7826
7888
|
}
|
|
7827
7889
|
}
|
|
@@ -28376,7 +28438,7 @@ function isCanonical(text) {
|
|
|
28376
28438
|
}
|
|
28377
28439
|
|
|
28378
28440
|
// src/index.ts
|
|
28379
|
-
var UPG_VERSION = "0.10.
|
|
28441
|
+
var UPG_VERSION = "0.10.3";
|
|
28380
28442
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
28381
28443
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
28382
28444
|
var UPG_TYPES = getTypes();
|