@unified-product-graph/core 0.10.2 → 0.10.4
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 +108 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -32
- package/dist/index.d.ts +79 -32
- package/dist/index.js +105 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -977,6 +977,32 @@ function getTypeName(typeId) {
|
|
|
977
977
|
|
|
978
978
|
// src/catalog/edge-catalog.ts
|
|
979
979
|
var UPG_WILDCARD_ENDPOINT = "node";
|
|
980
|
+
var CLASSIFICATION_EDGE_PROPERTY_SCHEMA = {
|
|
981
|
+
confidence: {
|
|
982
|
+
type: "assessment",
|
|
983
|
+
scale_id: "confidence_5",
|
|
984
|
+
description: "How sure we are this node belongs in this classification cell, on the canonical confidence_5 scale. Numeric value plus a high/medium/low label.",
|
|
985
|
+
properties: {
|
|
986
|
+
value: { type: "number", description: "Numeric value 1-5 (confidence_5)." },
|
|
987
|
+
label: { type: "string", description: "Qualitative label (Guessing/Hunch/Some evidence/Confident/Data-backed, or high/medium/low)." },
|
|
988
|
+
scale_id: { type: "string", description: "Scale rated on (optional; defaults confidence_5)." },
|
|
989
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
990
|
+
},
|
|
991
|
+
required: ["value", "label"]
|
|
992
|
+
},
|
|
993
|
+
assessed_on: {
|
|
994
|
+
type: "string",
|
|
995
|
+
description: 'Provenance: ISO date-time the classification was made or last re-checked. Drives staleness queries. @example "2026-06-13"'
|
|
996
|
+
},
|
|
997
|
+
rationale: {
|
|
998
|
+
type: "string",
|
|
999
|
+
description: "Optional. Short note on why this node sits in this cell. Edge-level, distinct from classification_value.rationale (why the value exists as a category)."
|
|
1000
|
+
},
|
|
1001
|
+
evidence: {
|
|
1002
|
+
type: "string",
|
|
1003
|
+
description: "Optional. A source URL, or a competitor_signal / evidence node id backing the classification. Mirrors feature_rivals_competitor_feature.evidence (free text or a node id)."
|
|
1004
|
+
}
|
|
1005
|
+
};
|
|
980
1006
|
var UPG_EDGE_CATALOG = {
|
|
981
1007
|
// ── Part 1: Core Narrative Spine (Ring 1) ──────────────────────────────────
|
|
982
1008
|
// 1.1 User Domain
|
|
@@ -1149,7 +1175,13 @@ var UPG_EDGE_CATALOG = {
|
|
|
1149
1175
|
// competitor can be classified directly against a `registry/{classification_value}`
|
|
1150
1176
|
// canonical, eliminating the per-graph taxonomy node. Within-graph (the catalogue
|
|
1151
1177
|
// case) here; cross-product against the registry canonical via create_cross_product_edge.
|
|
1152
|
-
competitor_classified_as_classification_value: { forward_verb: "classified_as", reverse_verb: "classification_of", classification: "semantic", source_type: "competitor", target_type: "classification_value" },
|
|
1178
|
+
competitor_classified_as_classification_value: { forward_verb: "classified_as", reverse_verb: "classification_of", classification: "semantic", source_type: "competitor", target_type: "classification_value", carries_properties: true, property_schema: CLASSIFICATION_EDGE_PROPERTY_SCHEMA },
|
|
1179
|
+
// 0.10.3: the polymorphic, type-agnostic sibling. ANY node (a feature, a
|
|
1180
|
+
// product, a market_segment) classified against a classification_value, so
|
|
1181
|
+
// classification is not welded to the competitor type. Also dual-registered as
|
|
1182
|
+
// a cross-edge for the registry-canonical case. source_type:'node' (wildcard);
|
|
1183
|
+
// listed in UPG_POLYMORPHIC_EDGE_KEYS.
|
|
1184
|
+
node_classified_as_classification_value: { forward_verb: "classified_as", reverse_verb: "classification_of", classification: "semantic", source_type: "node", target_type: "classification_value", carries_properties: true, property_schema: CLASSIFICATION_EDGE_PROPERTY_SCHEMA },
|
|
1153
1185
|
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" },
|
|
1154
1186
|
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" },
|
|
1155
1187
|
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" },
|
|
@@ -2987,7 +3019,9 @@ var UPG_POLYMORPHIC_EDGE_KEYS = [
|
|
|
2987
3019
|
// Universal architecture references
|
|
2988
3020
|
"node_belongs_to_bounded_context",
|
|
2989
3021
|
// Framework exercises (an exercise can include any entity type)
|
|
2990
|
-
"framework_exercise_includes_node"
|
|
3022
|
+
"framework_exercise_includes_node",
|
|
3023
|
+
// Universal classification (any node classified against a classification_value)
|
|
3024
|
+
"node_classified_as_classification_value"
|
|
2991
3025
|
];
|
|
2992
3026
|
var _POLY_KEY_SET = new Set(UPG_POLYMORPHIC_EDGE_KEYS);
|
|
2993
3027
|
function isPolymorphicEdge(key) {
|
|
@@ -3001,6 +3035,10 @@ function edgeCarriesProperties(type) {
|
|
|
3001
3035
|
const def = UPG_EDGE_CATALOG[type];
|
|
3002
3036
|
return def?.carries_properties === true;
|
|
3003
3037
|
}
|
|
3038
|
+
function getEdgePropertySchema(type) {
|
|
3039
|
+
const def = UPG_EDGE_CATALOG[type];
|
|
3040
|
+
return def?.property_schema;
|
|
3041
|
+
}
|
|
3004
3042
|
|
|
3005
3043
|
// src/catalog/legacy-product-stages.ts
|
|
3006
3044
|
var LEGACY_PRODUCT_STAGES = Object.freeze({
|
|
@@ -3045,7 +3083,8 @@ var UPG_CROSS_EDGE_TYPES = [
|
|
|
3045
3083
|
"feature_rivals_competitor_feature",
|
|
3046
3084
|
"competitor_signal_maps_to_feature",
|
|
3047
3085
|
"competitor_signal_surfaces_opportunity",
|
|
3048
|
-
"competitor_classified_as_classification_value"
|
|
3086
|
+
"competitor_classified_as_classification_value",
|
|
3087
|
+
"node_classified_as_classification_value"
|
|
3049
3088
|
];
|
|
3050
3089
|
var REGISTRY_PRODUCT_ID = "registry";
|
|
3051
3090
|
|
|
@@ -18530,6 +18569,65 @@ function isUPGDocument(doc) {
|
|
|
18530
18569
|
return validateUPGDocument(doc).valid;
|
|
18531
18570
|
}
|
|
18532
18571
|
|
|
18572
|
+
// src/properties/edge-property-validation.ts
|
|
18573
|
+
function validateEdgeProperties(edgeType, properties) {
|
|
18574
|
+
const schema = getEdgePropertySchema(edgeType);
|
|
18575
|
+
if (!schema || !properties) return [];
|
|
18576
|
+
const errors = [];
|
|
18577
|
+
const allowed = Object.keys(schema);
|
|
18578
|
+
for (const key of Object.keys(properties)) {
|
|
18579
|
+
if (!allowed.includes(key)) {
|
|
18580
|
+
errors.push(`unknown property "${key}" for edge type "${edgeType}" (allowed: ${allowed.join(", ")})`);
|
|
18581
|
+
}
|
|
18582
|
+
}
|
|
18583
|
+
for (const [key, def] of Object.entries(schema)) {
|
|
18584
|
+
const val = properties[key];
|
|
18585
|
+
if (val === void 0 || val === null) continue;
|
|
18586
|
+
errors.push(...validateValue(key, def, val));
|
|
18587
|
+
}
|
|
18588
|
+
return errors;
|
|
18589
|
+
}
|
|
18590
|
+
function validateValue(key, def, val) {
|
|
18591
|
+
const errors = [];
|
|
18592
|
+
switch (def.type) {
|
|
18593
|
+
case "string":
|
|
18594
|
+
if (typeof val !== "string") errors.push(`property "${key}" must be a string`);
|
|
18595
|
+
break;
|
|
18596
|
+
case "number":
|
|
18597
|
+
if (typeof val !== "number") errors.push(`property "${key}" must be a number`);
|
|
18598
|
+
break;
|
|
18599
|
+
case "boolean":
|
|
18600
|
+
if (typeof val !== "boolean") errors.push(`property "${key}" must be a boolean`);
|
|
18601
|
+
break;
|
|
18602
|
+
case "assessment": {
|
|
18603
|
+
if (typeof val !== "object" || Array.isArray(val)) {
|
|
18604
|
+
errors.push(`property "${key}" must be an assessment object with value and label`);
|
|
18605
|
+
break;
|
|
18606
|
+
}
|
|
18607
|
+
const a = val;
|
|
18608
|
+
for (const r of def.required ?? ["value", "label"]) {
|
|
18609
|
+
if (a[r] === void 0 || a[r] === null) errors.push(`assessment "${key}" is missing required "${r}"`);
|
|
18610
|
+
}
|
|
18611
|
+
if (a.value !== void 0 && a.value !== null) {
|
|
18612
|
+
if (typeof a.value !== "number") {
|
|
18613
|
+
errors.push(`assessment "${key}".value must be a number`);
|
|
18614
|
+
} else {
|
|
18615
|
+
const scaleId = (typeof a.scale_id === "string" ? a.scale_id : void 0) ?? def.scale_id;
|
|
18616
|
+
const scale = scaleId ? getScale(scaleId) : void 0;
|
|
18617
|
+
if (scale && (a.value < scale.min || a.value > scale.max)) {
|
|
18618
|
+
errors.push(`assessment "${key}".value ${a.value} is out of range ${scale.min}-${scale.max} for scale ${scaleId}`);
|
|
18619
|
+
}
|
|
18620
|
+
}
|
|
18621
|
+
}
|
|
18622
|
+
if (typeof a.scale_id === "string" && def.scale_id !== void 0 && a.scale_id !== def.scale_id) {
|
|
18623
|
+
errors.push(`assessment "${key}".scale_id "${a.scale_id}" must be "${def.scale_id}"`);
|
|
18624
|
+
}
|
|
18625
|
+
break;
|
|
18626
|
+
}
|
|
18627
|
+
}
|
|
18628
|
+
return errors;
|
|
18629
|
+
}
|
|
18630
|
+
|
|
18533
18631
|
// src/presentation/entity-emoji.ts
|
|
18534
18632
|
var DEFAULT_ENTITY_EMOJI = "\u{1F4E6}";
|
|
18535
18633
|
var ENTITY_EMOJI = {
|
|
@@ -28429,7 +28527,7 @@ function isCanonical(text) {
|
|
|
28429
28527
|
}
|
|
28430
28528
|
|
|
28431
28529
|
// src/index.ts
|
|
28432
|
-
var UPG_VERSION = "0.10.
|
|
28530
|
+
var UPG_VERSION = "0.10.4";
|
|
28433
28531
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
28434
28532
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
28435
28533
|
var UPG_TYPES = getTypes();
|
|
@@ -28497,6 +28595,7 @@ export {
|
|
|
28497
28595
|
BUSINESS_GROWTH_METRIC_DRIVEN_PLAYBOOK,
|
|
28498
28596
|
BUSINESS_GTM_GROWTH_PLAYBOOK,
|
|
28499
28597
|
BUSINESS_MARKETING_AUDIENCE_FIRST_PLAYBOOK,
|
|
28598
|
+
CLASSIFICATION_EDGE_PROPERTY_SCHEMA,
|
|
28500
28599
|
CONTENT_DEPTH_WARNING_RULES,
|
|
28501
28600
|
DEFAULT_ENTITY_EMOJI,
|
|
28502
28601
|
DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK,
|
|
@@ -28608,6 +28707,7 @@ export {
|
|
|
28608
28707
|
getDomainForType,
|
|
28609
28708
|
getDomainIdForType,
|
|
28610
28709
|
getDomainsInRing,
|
|
28710
|
+
getEdgePropertySchema,
|
|
28611
28711
|
getEnumScale,
|
|
28612
28712
|
getEnumValueMeta,
|
|
28613
28713
|
getGuideForDomain,
|
|
@@ -28672,6 +28772,7 @@ export {
|
|
|
28672
28772
|
ringOrderedDomainIds,
|
|
28673
28773
|
rotateSlug,
|
|
28674
28774
|
serializeCanonical,
|
|
28775
|
+
validateEdgeProperties,
|
|
28675
28776
|
validateProductStageStrict,
|
|
28676
28777
|
validateUPGDocument,
|
|
28677
28778
|
validateUPGFramework,
|