@unified-product-graph/core 0.11.5 → 0.12.0
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 +372 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +314 -73
- package/dist/index.d.ts +314 -73
- package/dist/index.js +370 -51
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -90,6 +90,7 @@ __export(index_exports, {
|
|
|
90
90
|
UPG_REGION_COUNT: () => UPG_REGION_COUNT,
|
|
91
91
|
UPG_REGION_MAP: () => UPG_REGION_MAP,
|
|
92
92
|
UPG_RELATIONSHIP_BENCHMARKS: () => UPG_RELATIONSHIP_BENCHMARKS,
|
|
93
|
+
UPG_SCALAR_TO_EDGE_MIGRATIONS: () => UPG_SCALAR_TO_EDGE_MIGRATIONS,
|
|
93
94
|
UPG_SCALES: () => UPG_SCALES,
|
|
94
95
|
UPG_SPLIT_MIGRATIONS: () => UPG_SPLIT_MIGRATIONS,
|
|
95
96
|
UPG_STATUS_MIGRATIONS: () => UPG_STATUS_MIGRATIONS,
|
|
@@ -158,6 +159,7 @@ __export(index_exports, {
|
|
|
158
159
|
getRegionForEntityType: () => getRegionForEntityType,
|
|
159
160
|
getReplacementType: () => getReplacementType,
|
|
160
161
|
getRingForDomain: () => getRingForDomain,
|
|
162
|
+
getScalarToEdgeMigrations: () => getScalarToEdgeMigrations,
|
|
161
163
|
getScale: () => getScale,
|
|
162
164
|
getSplitMigrations: () => getSplitMigrations,
|
|
163
165
|
getTreePattern: () => getTreePattern,
|
|
@@ -706,7 +708,7 @@ var UPG_DOMAINS = [
|
|
|
706
708
|
id: "foundations",
|
|
707
709
|
label: "Foundations",
|
|
708
710
|
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 GROQ or Portable 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.",
|
|
709
|
-
types: ["specification", "primitive"]
|
|
711
|
+
types: ["specification", "primitive", "operating_lifecycle", "operating_stage"]
|
|
710
712
|
}
|
|
711
713
|
];
|
|
712
714
|
var UPG_ENTITY_TO_DOMAIN = Object.freeze(
|
|
@@ -729,6 +731,8 @@ var UPG_ENTITY_META = [
|
|
|
729
731
|
// Foundations (0.9.12): shared specifications + the primitives they define.
|
|
730
732
|
{ name: "specification", type_id: "ent_352", maturity: "proposed", since: "0.9.12" },
|
|
731
733
|
{ name: "primitive", type_id: "ent_353", maturity: "proposed", since: "0.9.12" },
|
|
734
|
+
{ name: "operating_lifecycle", type_id: "ent_355", maturity: "proposed", since: "0.11.6" },
|
|
735
|
+
{ name: "operating_stage", type_id: "ent_356", maturity: "proposed", since: "0.11.6" },
|
|
732
736
|
// ── Strategic ──
|
|
733
737
|
{ name: "product", type_id: "ent_001", maturity: "stable", since: "0.1.0" },
|
|
734
738
|
{ name: "outcome", type_id: "ent_002", maturity: "stable", since: "0.1.0" },
|
|
@@ -1229,6 +1233,9 @@ var UPG_EDGE_CATALOG = {
|
|
|
1229
1233
|
persona_pursues_job: { forward_verb: "pursues", reverse_verb: "pursued_by", classification: "semantic", source_type: "persona", target_type: "job" },
|
|
1230
1234
|
persona_experiences_need: { forward_verb: "experiences", reverse_verb: "experienced_by", classification: "semantic", source_type: "persona", target_type: "need" },
|
|
1231
1235
|
persona_aspires_to_desired_outcome: { forward_verb: "aspires_to", reverse_verb: "aspirational_for", classification: "hierarchy", source_type: "persona", target_type: "desired_outcome" },
|
|
1236
|
+
// Delegation (0.11.6): a persona delegates work to another. The common case is human -> agent
|
|
1237
|
+
// (Content Ops Lead -> Content Agent), but it also expresses human -> human (editor -> reviewer).
|
|
1238
|
+
persona_delegates_to_persona: { forward_verb: "delegates_to", reverse_verb: "delegated_by", classification: "semantic", source_type: "persona", target_type: "persona" },
|
|
1232
1239
|
persona_incurs_switching_cost: { forward_verb: "incurs", reverse_verb: "incurred_by", classification: "hierarchy", source_type: "persona", target_type: "switching_cost" },
|
|
1233
1240
|
job_surfaces_need: { forward_verb: "surfaces", reverse_verb: "surfaces_from", classification: "causal", source_type: "job", target_type: "need" },
|
|
1234
1241
|
job_motivates_desired_outcome: { forward_verb: "motivates", reverse_verb: "motivated_by", classification: "causal", source_type: "job", target_type: "desired_outcome" },
|
|
@@ -2391,6 +2398,32 @@ var UPG_EDGE_CATALOG = {
|
|
|
2391
2398
|
// owned by feature_area / theme / product. Relationship is semantic.
|
|
2392
2399
|
changelog_includes_feature: { forward_verb: "includes", reverse_verb: "included_in", classification: "semantic", source_type: "changelog", target_type: "feature" },
|
|
2393
2400
|
ai_trace_spawns_ai_trace: { forward_verb: "spawns", reverse_verb: "spawned_by", classification: "hierarchy", source_type: "ai_trace", target_type: "ai_trace" },
|
|
2401
|
+
// ── P14 conformance edges (0.12.0) — promote orphan entity-reference scalars ──
|
|
2402
|
+
// Each replaces a string property that named a first-class entity. The matching
|
|
2403
|
+
// `UPGScalarToEdgeMigration['0.12.0']` rule losslessly mints/links + drops the
|
|
2404
|
+
// scalar. See the P14 string-reference sweep.
|
|
2405
|
+
business_model_guided_by_metric: { forward_verb: "guided_by", reverse_verb: "guides", classification: "cross-domain", source_type: "business_model", target_type: "metric" },
|
|
2406
|
+
vision_anchored_by_metric: { forward_verb: "anchored_by", reverse_verb: "anchors", classification: "cross-domain", source_type: "vision", target_type: "metric" },
|
|
2407
|
+
metric_fed_by_data_source: { forward_verb: "fed_by", reverse_verb: "feeds", classification: "cross-domain", source_type: "metric", target_type: "data_source" },
|
|
2408
|
+
hallucination_report_has_root_cause: { forward_verb: "has_root_cause", reverse_verb: "root_cause_of", classification: "causal", source_type: "hallucination_report", target_type: "root_cause" },
|
|
2409
|
+
model_comparison_compares_ai_model: { forward_verb: "compares", reverse_verb: "compared_in", classification: "semantic", source_type: "model_comparison", target_type: "ai_model" },
|
|
2410
|
+
launch_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "cross-domain", source_type: "launch", target_type: "metric" },
|
|
2411
|
+
wireframe_depicts_screen: { forward_verb: "depicts", reverse_verb: "depicted_by", classification: "semantic", source_type: "wireframe", target_type: "screen" },
|
|
2412
|
+
service_level_indicator_measures_metric: { forward_verb: "measures", reverse_verb: "measured_by", classification: "cross-domain", source_type: "service_level_indicator", target_type: "metric" },
|
|
2413
|
+
agent_definition_uses_ai_model: { forward_verb: "uses", reverse_verb: "used_by", classification: "semantic", source_type: "agent_definition", target_type: "ai_model" },
|
|
2414
|
+
privacy_policy_governs_compliance_requirement: { forward_verb: "governs", reverse_verb: "governed_by", classification: "semantic", source_type: "privacy_policy", target_type: "compliance_requirement" },
|
|
2415
|
+
a11y_annotation_targets_design_component: { forward_verb: "targets", reverse_verb: "targeted_by", classification: "cross-domain", source_type: "a11y_annotation", target_type: "design_component" },
|
|
2416
|
+
metric_quality_assessment_considers_proxy_metric: { forward_verb: "considers_proxy", reverse_verb: "proxy_for", classification: "semantic", source_type: "metric_quality_assessment", target_type: "metric" },
|
|
2417
|
+
ai_experiment_based_on_ai_model: { forward_verb: "based_on", reverse_verb: "basis_for", classification: "semantic", source_type: "ai_experiment", target_type: "ai_model" },
|
|
2418
|
+
rebuttal_supported_by_evidence: { forward_verb: "supported_by", reverse_verb: "supports", classification: "cross-domain", source_type: "rebuttal", target_type: "evidence" },
|
|
2419
|
+
bug_observed_in_release: { forward_verb: "observed_in", reverse_verb: "exhibits", classification: "semantic", source_type: "bug", target_type: "release" },
|
|
2420
|
+
vulnerability_affects_library_dependency: { forward_verb: "affects", reverse_verb: "affected_by", classification: "cross-domain", source_type: "vulnerability", target_type: "library_dependency" },
|
|
2421
|
+
a11y_issue_found_in_screen: { forward_verb: "found_in", reverse_verb: "site_of", classification: "cross-domain", source_type: "a11y_issue", target_type: "screen" },
|
|
2422
|
+
team_okr_cascades_from_team_okr: { forward_verb: "cascades_from", reverse_verb: "cascades_to", classification: "semantic", source_type: "team_okr", target_type: "team_okr" },
|
|
2423
|
+
agent_session_invoked_agent_skill: { forward_verb: "invoked", reverse_verb: "invoked_by", classification: "semantic", source_type: "agent_session", target_type: "agent_skill" },
|
|
2424
|
+
agent_task_uses_agent_skill: { forward_verb: "uses", reverse_verb: "used_by", classification: "semantic", source_type: "agent_task", target_type: "agent_skill" },
|
|
2425
|
+
participant_belongs_to_behavioral_segment: { forward_verb: "belongs_to", reverse_verb: "includes", classification: "cross-domain", source_type: "participant", target_type: "behavioral_segment" },
|
|
2426
|
+
classification_axis_owned_by_product: { forward_verb: "owned_by", reverse_verb: "owns", classification: "cross-domain", source_type: "classification_axis", target_type: "product" },
|
|
2394
2427
|
// ── Part 9: Cross-Layer Influence Edges ────────────────────────────────────
|
|
2395
2428
|
product_expressed_as_design_component: { forward_verb: "expressed_as", reverse_verb: "expresses", classification: "cross-domain", source_type: "product", target_type: "design_component" },
|
|
2396
2429
|
product_manifests_in_design_component: { forward_verb: "manifests_in", reverse_verb: "manifested_by", classification: "cross-domain", source_type: "product", target_type: "design_component" },
|
|
@@ -3210,8 +3243,13 @@ var UPG_EDGE_CATALOG = {
|
|
|
3210
3243
|
specification_competes_with_specification: { forward_verb: "competes_with", reverse_verb: "competes_with", classification: "semantic", source_type: "specification", target_type: "specification" },
|
|
3211
3244
|
primitive_defined_by_specification: { forward_verb: "defined_by", reverse_verb: "defines", classification: "semantic", source_type: "primitive", target_type: "specification" },
|
|
3212
3245
|
primitive_composes_primitive: { forward_verb: "composes", reverse_verb: "composed_by", classification: "hierarchy", source_type: "primitive", target_type: "primitive" },
|
|
3246
|
+
operating_lifecycle_contains_operating_stage: { forward_verb: "contains", reverse_verb: "belongs_to", classification: "hierarchy", source_type: "operating_lifecycle", target_type: "operating_stage" },
|
|
3213
3247
|
// Stewardship: a registry specification is governed by a (registry-hostable) organization (0.9.13).
|
|
3214
|
-
specification_governed_by_organization: { forward_verb: "governed_by", reverse_verb: "governs", classification: "semantic", source_type: "specification", target_type: "organization" }
|
|
3248
|
+
specification_governed_by_organization: { forward_verb: "governed_by", reverse_verb: "governs", classification: "semantic", source_type: "specification", target_type: "organization" },
|
|
3249
|
+
// Operating-lifecycle cross-edges (0.11.6): a product's journey phase realises a canonical
|
|
3250
|
+
// operating stage (the cross-surface join key); a stage is measured by a rollup metric (loop close).
|
|
3251
|
+
journey_phase_realises_operating_stage: { forward_verb: "realises", reverse_verb: "realised_by", classification: "cross-domain", source_type: "journey_phase", target_type: "operating_stage" },
|
|
3252
|
+
operating_stage_measured_by_metric: { forward_verb: "measured_by", reverse_verb: "measures", classification: "cross-domain", source_type: "operating_stage", target_type: "metric" }
|
|
3215
3253
|
};
|
|
3216
3254
|
var UPG_POLYMORPHIC_EDGE_KEYS = [
|
|
3217
3255
|
// Universal semantic verbs
|
|
@@ -3367,6 +3405,9 @@ var UPG_VALID_CHILDREN = {
|
|
|
3367
3405
|
// primitive_composes_primitive catalog edges.
|
|
3368
3406
|
specification: ["specification"],
|
|
3369
3407
|
primitive: ["primitive"],
|
|
3408
|
+
// An operating_lifecycle (e.g. the content-ops lifecycle) contains its ordered
|
|
3409
|
+
// operating_stage children. Backs the operating_lifecycle_contains_operating_stage edge.
|
|
3410
|
+
operating_lifecycle: ["operating_stage"],
|
|
3370
3411
|
// ── Product (root) ─────────────────────────────────────────────────────────
|
|
3371
3412
|
product: [
|
|
3372
3413
|
// Strategy
|
|
@@ -6430,9 +6471,13 @@ function getLifecycleForType(entityType) {
|
|
|
6430
6471
|
return UPG_LIFECYCLES.find((l) => l.entity_type === entityType);
|
|
6431
6472
|
}
|
|
6432
6473
|
var UPG_LIFECYCLE_FREE_TYPES = /* @__PURE__ */ new Set([
|
|
6433
|
-
// ── Foundations (
|
|
6434
|
-
// phase ladder (like metric). `
|
|
6474
|
+
// ── Foundations (3 of 4): a primitive either exists or is deprecated; no
|
|
6475
|
+
// phase ladder (like metric). `operating_lifecycle`/`operating_stage` are
|
|
6476
|
+
// static ordered reference data (the loop is a `cyclic` flag, not a state
|
|
6477
|
+
// machine). `specification` carries a lifecycle. ──
|
|
6435
6478
|
"primitive",
|
|
6479
|
+
"operating_lifecycle",
|
|
6480
|
+
"operating_stage",
|
|
6436
6481
|
// ── User (5): personas and JTBD atoms are reference data ──────────────────
|
|
6437
6482
|
"persona",
|
|
6438
6483
|
"job",
|
|
@@ -7517,6 +7562,25 @@ function getDeprecatedTypes() {
|
|
|
7517
7562
|
return deprecated;
|
|
7518
7563
|
}
|
|
7519
7564
|
var UPG_PROPERTY_MIGRATIONS = {
|
|
7565
|
+
// ── v0.12.0: P14 Bucket C — drop the one non-derived denormalized aggregate ──
|
|
7566
|
+
//
|
|
7567
|
+
// The count caches (feature_count, evidence_count, workflow step_count /
|
|
7568
|
+
// agent_count) are KEPT — 0.11.6 marked them `modifier:'derived'` (the
|
|
7569
|
+
// sanctioned "derived cache" reframe), so tooling knows to recompute rather
|
|
7570
|
+
// than removing them. `business_model.monetisation_basis` is NOT a count: it's
|
|
7571
|
+
// a categorical rollup of the model's revenue_stream.billing_model children, so
|
|
7572
|
+
// it drops here. `pattern` stays (a chosen archetype, not a rollup).
|
|
7573
|
+
// (customer_health_score.metrics — a metric→value map — is deferred: dropping
|
|
7574
|
+
// it is lossy until the per-metric values move onto the composed_of_metric
|
|
7575
|
+
// edges; tracked as a follow-up.)
|
|
7576
|
+
"0.12.0": [
|
|
7577
|
+
{
|
|
7578
|
+
kind: "drop_props",
|
|
7579
|
+
type: "business_model",
|
|
7580
|
+
drop_props: ["monetisation_basis"],
|
|
7581
|
+
reason: "P14 Bucket C: monetisation_basis is a categorical rollup of the model\u2019s revenue_stream.billing_model children, not a first-class attribute. Drop it; KEEP `pattern` (a chosen archetype)."
|
|
7582
|
+
}
|
|
7583
|
+
],
|
|
7520
7584
|
// ── v0.10.2: market_intelligence number -> assessment reshape ──────────────
|
|
7521
7585
|
//
|
|
7522
7586
|
// The v0.10.0 property-registry generator fix (#43) corrected several property
|
|
@@ -8346,6 +8410,245 @@ function getSplitMigrations(fromVersion, toVersion) {
|
|
|
8346
8410
|
}
|
|
8347
8411
|
return result;
|
|
8348
8412
|
}
|
|
8413
|
+
var UPG_SCALAR_TO_EDGE_MIGRATIONS = {
|
|
8414
|
+
"0.12.0": [
|
|
8415
|
+
// ── Bucket A1 — orphan scalars (no edge existed): add edge + migrate + drop ──
|
|
8416
|
+
{
|
|
8417
|
+
from_type: "business_model",
|
|
8418
|
+
scalar_property: "north_star_metric",
|
|
8419
|
+
target_type: "metric",
|
|
8420
|
+
edge_type: "business_model_guided_by_metric",
|
|
8421
|
+
target_match: "title",
|
|
8422
|
+
target_defaults: { designation: "north_star" },
|
|
8423
|
+
drop_scalar: true,
|
|
8424
|
+
reason: 'P14: the optimised metric is a first-class entity you query across business models ("which models optimise for this metric"), not a label. Mint metric{designation:north_star} + link via business_model_guided_by_metric; drop the orphan string.'
|
|
8425
|
+
},
|
|
8426
|
+
// NOTE: revenue_stream.forecast is NOT promoted — its JSDoc ("Free-text
|
|
8427
|
+
// forecast or projection") is narrative prose, not a ref to a forecast
|
|
8428
|
+
// entity. The additive revenue_stream_projected_by_forecast edge exists for
|
|
8429
|
+
// an explicit stream→forecast link; the free-text field stays.
|
|
8430
|
+
{
|
|
8431
|
+
from_type: "metric",
|
|
8432
|
+
scalar_property: "data_source",
|
|
8433
|
+
target_type: "data_source",
|
|
8434
|
+
edge_type: "metric_fed_by_data_source",
|
|
8435
|
+
drop_scalar: true,
|
|
8436
|
+
reason: 'P14: the data source feeding a metric is queryable across metrics ("everything fed by this source"); promote the string to a metric_fed_by_data_source edge.'
|
|
8437
|
+
},
|
|
8438
|
+
{
|
|
8439
|
+
from_type: "hallucination_report",
|
|
8440
|
+
scalar_property: "root_cause",
|
|
8441
|
+
target_type: "root_cause",
|
|
8442
|
+
edge_type: "hallucination_report_has_root_cause",
|
|
8443
|
+
drop_scalar: true,
|
|
8444
|
+
reason: "P14: a root_cause is a first-class entity reused across reports; link it rather than restating the cause as a string."
|
|
8445
|
+
},
|
|
8446
|
+
// NOTE: prompt_version.template is NOT promoted — its JSDoc ("Template body
|
|
8447
|
+
// with variable placeholders") is the prompt CONTENT, not a ref to a
|
|
8448
|
+
// prompt_template entity. The additive prompt_version_child_of_prompt_template
|
|
8449
|
+
// edge exists for an explicit version→template link; the content field stays.
|
|
8450
|
+
{
|
|
8451
|
+
from_type: "model_comparison",
|
|
8452
|
+
scalar_property: "model_ids",
|
|
8453
|
+
target_type: "ai_model",
|
|
8454
|
+
edge_type: "model_comparison_compares_ai_model",
|
|
8455
|
+
multi: true,
|
|
8456
|
+
drop_scalar: true,
|
|
8457
|
+
reason: "P14: the models being compared are first-class ai_model entities; one compares edge per model replaces the id-string list."
|
|
8458
|
+
},
|
|
8459
|
+
{
|
|
8460
|
+
from_type: "launch",
|
|
8461
|
+
scalar_property: "success_metrics",
|
|
8462
|
+
target_type: "metric",
|
|
8463
|
+
edge_type: "launch_measured_by_metric",
|
|
8464
|
+
multi: true,
|
|
8465
|
+
drop_scalar: true,
|
|
8466
|
+
reason: "P14: success metrics are first-class metric entities measured across launches; one measured_by edge per metric replaces the string list."
|
|
8467
|
+
},
|
|
8468
|
+
// NOTE: user_story.as_a is NOT promoted — it is a load-bearing field of the
|
|
8469
|
+
// user_story → story_statement split (the "As a <persona>" templated promise),
|
|
8470
|
+
// and the value is often a role descriptor, not a persona node. Left in place.
|
|
8471
|
+
{
|
|
8472
|
+
from_type: "wireframe",
|
|
8473
|
+
scalar_property: "screen_name",
|
|
8474
|
+
target_type: "screen",
|
|
8475
|
+
edge_type: "wireframe_depicts_screen",
|
|
8476
|
+
drop_scalar: true,
|
|
8477
|
+
reason: "P14: the depicted screen is a first-class entity; link it via wireframe_depicts_screen rather than naming it in a string."
|
|
8478
|
+
},
|
|
8479
|
+
{
|
|
8480
|
+
from_type: "service_level_indicator",
|
|
8481
|
+
scalar_property: "metric_name",
|
|
8482
|
+
target_type: "metric",
|
|
8483
|
+
edge_type: "service_level_indicator_measures_metric",
|
|
8484
|
+
drop_scalar: true,
|
|
8485
|
+
reason: "P14: the SLI\u2019s metric is a first-class entity; link it via service_level_indicator_measures_metric rather than naming it in a string."
|
|
8486
|
+
},
|
|
8487
|
+
{
|
|
8488
|
+
from_type: "agent_definition",
|
|
8489
|
+
scalar_property: "model_ref",
|
|
8490
|
+
target_type: "ai_model",
|
|
8491
|
+
edge_type: "agent_definition_uses_ai_model",
|
|
8492
|
+
drop_scalar: true,
|
|
8493
|
+
reason: 'P14: the model an agent uses is a first-class ai_model entity ("every agent on this model"); promote the ref string to a uses edge.'
|
|
8494
|
+
},
|
|
8495
|
+
{
|
|
8496
|
+
from_type: "privacy_policy",
|
|
8497
|
+
scalar_property: "regulations",
|
|
8498
|
+
target_type: "compliance_requirement",
|
|
8499
|
+
edge_type: "privacy_policy_governs_compliance_requirement",
|
|
8500
|
+
multi: true,
|
|
8501
|
+
drop_scalar: true,
|
|
8502
|
+
reason: "P14: each regulation is a first-class compliance_requirement entity tracked across policies; one governs edge per requirement replaces the string list."
|
|
8503
|
+
},
|
|
8504
|
+
{
|
|
8505
|
+
from_type: "a11y_annotation",
|
|
8506
|
+
scalar_property: "target_component",
|
|
8507
|
+
target_type: "design_component",
|
|
8508
|
+
edge_type: "a11y_annotation_targets_design_component",
|
|
8509
|
+
drop_scalar: true,
|
|
8510
|
+
reason: "P14: the annotated component is a real design_component entity; link it so accessibility coverage rolls up by component."
|
|
8511
|
+
},
|
|
8512
|
+
{
|
|
8513
|
+
from_type: "metric_quality_assessment",
|
|
8514
|
+
scalar_property: "proxy_alternatives",
|
|
8515
|
+
target_type: "metric",
|
|
8516
|
+
edge_type: "metric_quality_assessment_considers_proxy_metric",
|
|
8517
|
+
multi: true,
|
|
8518
|
+
drop_scalar: true,
|
|
8519
|
+
reason: "P14: proxy alternatives are first-class metric entities; one considers_proxy edge per metric replaces the name list."
|
|
8520
|
+
},
|
|
8521
|
+
{
|
|
8522
|
+
from_type: "ai_experiment",
|
|
8523
|
+
scalar_property: "foundation_model",
|
|
8524
|
+
target_type: "ai_model",
|
|
8525
|
+
edge_type: "ai_experiment_based_on_ai_model",
|
|
8526
|
+
drop_scalar: true,
|
|
8527
|
+
reason: "P14: the foundation model is a first-class ai_model entity reused across experiments; promote the string to a based_on edge."
|
|
8528
|
+
},
|
|
8529
|
+
{
|
|
8530
|
+
from_type: "rebuttal",
|
|
8531
|
+
scalar_property: "evidence_refs",
|
|
8532
|
+
target_type: "evidence",
|
|
8533
|
+
edge_type: "rebuttal_supported_by_evidence",
|
|
8534
|
+
multi: true,
|
|
8535
|
+
drop_scalar: true,
|
|
8536
|
+
reason: "P14: each evidence ref is a first-class evidence entity; one supported_by edge per item replaces the ref-string list."
|
|
8537
|
+
},
|
|
8538
|
+
{
|
|
8539
|
+
from_type: "bug",
|
|
8540
|
+
scalar_property: "affected_version",
|
|
8541
|
+
target_type: "release",
|
|
8542
|
+
edge_type: "bug_observed_in_release",
|
|
8543
|
+
drop_scalar: true,
|
|
8544
|
+
reason: 'P14: the affected version is a first-class release entity ("every bug in this release"); promote the version string to an observed_in edge.'
|
|
8545
|
+
},
|
|
8546
|
+
{
|
|
8547
|
+
from_type: "vulnerability",
|
|
8548
|
+
scalar_property: "affected_package",
|
|
8549
|
+
target_type: "library_dependency",
|
|
8550
|
+
edge_type: "vulnerability_affects_library_dependency",
|
|
8551
|
+
drop_scalar: true,
|
|
8552
|
+
reason: "P14: the affected package is a first-class library_dependency entity; link it so vulnerabilities roll up by dependency."
|
|
8553
|
+
},
|
|
8554
|
+
{
|
|
8555
|
+
from_type: "a11y_issue",
|
|
8556
|
+
scalar_property: "discovered_in",
|
|
8557
|
+
target_type: "screen",
|
|
8558
|
+
edge_type: "a11y_issue_found_in_screen",
|
|
8559
|
+
drop_scalar: true,
|
|
8560
|
+
reason: "P14: the screen an issue was found in is a real screen entity; link it so issues roll up by screen rather than naming it in a string."
|
|
8561
|
+
},
|
|
8562
|
+
{
|
|
8563
|
+
from_type: "team_okr",
|
|
8564
|
+
scalar_property: "cascade_from",
|
|
8565
|
+
target_type: "team_okr",
|
|
8566
|
+
edge_type: "team_okr_cascades_from_team_okr",
|
|
8567
|
+
drop_scalar: true,
|
|
8568
|
+
reason: "P14: a cascaded OKR points at its parent OKR (a real entity); the cascade is a self-referential edge, not a name string."
|
|
8569
|
+
},
|
|
8570
|
+
{
|
|
8571
|
+
from_type: "agent_session",
|
|
8572
|
+
scalar_property: "tools_invoked",
|
|
8573
|
+
target_type: "agent_skill",
|
|
8574
|
+
edge_type: "agent_session_invoked_agent_skill",
|
|
8575
|
+
multi: true,
|
|
8576
|
+
drop_scalar: true,
|
|
8577
|
+
reason: "P14: invoked tools are first-class agent_skill entities tracked across sessions; one invoked edge per skill replaces the string list."
|
|
8578
|
+
},
|
|
8579
|
+
{
|
|
8580
|
+
from_type: "agent_task",
|
|
8581
|
+
scalar_property: "tools",
|
|
8582
|
+
target_type: "agent_skill",
|
|
8583
|
+
edge_type: "agent_task_uses_agent_skill",
|
|
8584
|
+
multi: true,
|
|
8585
|
+
drop_scalar: true,
|
|
8586
|
+
reason: "P14: the tools a task uses are first-class agent_skill entities; one uses edge per skill replaces the string list."
|
|
8587
|
+
},
|
|
8588
|
+
{
|
|
8589
|
+
from_type: "participant",
|
|
8590
|
+
scalar_property: "segment",
|
|
8591
|
+
target_type: "behavioral_segment",
|
|
8592
|
+
edge_type: "participant_belongs_to_behavioral_segment",
|
|
8593
|
+
drop_scalar: true,
|
|
8594
|
+
reason: "P14: a participant\u2019s segment is a first-class behavioral_segment entity queried across studies; promote the string to a belongs_to edge."
|
|
8595
|
+
},
|
|
8596
|
+
{
|
|
8597
|
+
from_type: "classification_axis",
|
|
8598
|
+
scalar_property: "owner_product",
|
|
8599
|
+
target_type: "product",
|
|
8600
|
+
edge_type: "classification_axis_owned_by_product",
|
|
8601
|
+
target_match: "id",
|
|
8602
|
+
drop_scalar: true,
|
|
8603
|
+
reason: "P14: the product that owns an axis is a first-class entity; link it via classification_axis_owned_by_product. The scalar holds a product id, so match by id (no mint)."
|
|
8604
|
+
},
|
|
8605
|
+
// ── Bucket A2 — shadow scalars (the canonical edge ALREADY exists): backfill + drop ──
|
|
8606
|
+
{
|
|
8607
|
+
from_type: "growth_campaign",
|
|
8608
|
+
scalar_property: "channels_targeted",
|
|
8609
|
+
target_type: "acquisition_channel",
|
|
8610
|
+
edge_type: "acquisition_channel_runs_growth_campaign",
|
|
8611
|
+
reverse: true,
|
|
8612
|
+
multi: true,
|
|
8613
|
+
drop_scalar: true,
|
|
8614
|
+
reason: "P14 shadow: the acquisition_channel_runs_growth_campaign edge already exists (channel\u2192campaign). Backfill any string-only channels as edges, then drop the drift-prone list."
|
|
8615
|
+
},
|
|
8616
|
+
{
|
|
8617
|
+
from_type: "journey_step",
|
|
8618
|
+
scalar_property: "touchpoint",
|
|
8619
|
+
target_type: "touchpoint",
|
|
8620
|
+
edge_type: "touchpoint_occurs_in_journey_step",
|
|
8621
|
+
reverse: true,
|
|
8622
|
+
drop_scalar: true,
|
|
8623
|
+
reason: "P14 shadow: the touchpoint_occurs_in_journey_step edge already exists (touchpoint\u2192journey_step) and the field was @deprecated 0.9.9. Backfill + finish the drop."
|
|
8624
|
+
},
|
|
8625
|
+
{
|
|
8626
|
+
from_type: "decision",
|
|
8627
|
+
scalar_property: "superseded_by",
|
|
8628
|
+
target_type: "decision",
|
|
8629
|
+
edge_type: "decision_superseded_by_decision",
|
|
8630
|
+
drop_scalar: true,
|
|
8631
|
+
reason: "P14 shadow: the decision_superseded_by_decision edge already exists. Backfill the superseding decision as an edge, then drop the reference string."
|
|
8632
|
+
},
|
|
8633
|
+
{
|
|
8634
|
+
from_type: "subscription",
|
|
8635
|
+
scalar_property: "plan_name",
|
|
8636
|
+
target_type: "pricing_tier",
|
|
8637
|
+
edge_type: "subscription_subscribes_to_pricing_tier",
|
|
8638
|
+
drop_scalar: true,
|
|
8639
|
+
reason: "P14 shadow: the subscription_subscribes_to_pricing_tier edge already exists. Backfill the plan as a pricing_tier edge, then drop the name string."
|
|
8640
|
+
}
|
|
8641
|
+
]
|
|
8642
|
+
};
|
|
8643
|
+
function getScalarToEdgeMigrations(fromVersion, toVersion) {
|
|
8644
|
+
const result = [];
|
|
8645
|
+
for (const [version, migrations] of Object.entries(UPG_SCALAR_TO_EDGE_MIGRATIONS)) {
|
|
8646
|
+
if (versionInRange(version, fromVersion, toVersion)) {
|
|
8647
|
+
result.push(...migrations);
|
|
8648
|
+
}
|
|
8649
|
+
}
|
|
8650
|
+
return result;
|
|
8651
|
+
}
|
|
8349
8652
|
var UPG_EDGE_MIGRATIONS = {
|
|
8350
8653
|
"0.9.9": [
|
|
8351
8654
|
// (since v0.9.9, UPG-664/UPG-678) Validation experiment-model + test_plan
|
|
@@ -9334,7 +9637,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9334
9637
|
// A11yAnnotationProperties: Accessibility annotation.
|
|
9335
9638
|
a11y_annotation: {
|
|
9336
9639
|
category: { type: "string", enum: ["focus_order", "alt_text", "heading_level", "aria_label", "colour_contrast", "keyboard_nav", "screen_reader", "motion_preference", "other"], description: "Category of accessibility annotation. Expanded from the original 5-value enum to cover the full range of a11y annotation types." },
|
|
9337
|
-
target_component: { type: "string", description: "Component or element this annotation applies to" },
|
|
9338
9640
|
requirement: { type: "string", description: "Specific accessibility requirement described" },
|
|
9339
9641
|
wcag_criterion: { type: "string", description: "WCAG success criterion this annotation relates to" },
|
|
9340
9642
|
annotation_priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Priority for implementing this annotation" },
|
|
@@ -9383,8 +9685,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9383
9685
|
html_snippet: { type: "string", description: "HTML snippet containing the violation" },
|
|
9384
9686
|
tags: { type: "string[]", description: 'Tags from the audit tool (e.g. "wcag2aa", "cat.color")' },
|
|
9385
9687
|
remediation: { type: "string", description: "Recommended fix for the issue" },
|
|
9386
|
-
impact_description: { type: "string", description: "Description of the user impact" }
|
|
9387
|
-
discovered_in: { type: "string", description: "Page or component where the issue was found" }
|
|
9688
|
+
impact_description: { type: "string", description: "Description of the user impact" }
|
|
9388
9689
|
},
|
|
9389
9690
|
// A11yStandardProperties: Accessibility standard.
|
|
9390
9691
|
a11y_standard: {
|
|
@@ -9450,7 +9751,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9450
9751
|
agent_scope: { type: "string", description: "Boundaries of what this agent can act on" },
|
|
9451
9752
|
goal: { type: "string", description: "Primary objective the agent is trying to achieve" },
|
|
9452
9753
|
backstory: { type: "string", description: "Context or persona narrative for the agent" },
|
|
9453
|
-
model_ref: { type: "string", description: "Reference to the AI model powering this agent" },
|
|
9454
9754
|
allow_delegation: { type: "boolean", description: "Whether the agent can delegate tasks to other agents" },
|
|
9455
9755
|
memory_enabled: { type: "boolean", description: "Whether the agent retains memory across sessions" },
|
|
9456
9756
|
max_iterations: { type: "number", description: "Maximum number of reasoning iterations allowed" },
|
|
@@ -9474,7 +9774,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9474
9774
|
turns: { type: "number", description: "Number of conversational turns in the session" },
|
|
9475
9775
|
tokens_used: { type: "number", description: "Total tokens consumed during the session" },
|
|
9476
9776
|
cost: { type: "number", description: "Total monetary cost of the session" },
|
|
9477
|
-
tools_invoked: { type: "string[]", description: "List of tools invoked during the session" },
|
|
9478
9777
|
error_count: { type: "number", description: "Number of errors encountered during the session" },
|
|
9479
9778
|
session_status: { type: "string", enum: ["active", "completed", "errored", "timed_out"], description: "Current status of the session" },
|
|
9480
9779
|
output_summary: { type: "string", description: "Brief summary of the session's output" }
|
|
@@ -9490,7 +9789,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9490
9789
|
description: { type: "string", description: "What the agent should accomplish" },
|
|
9491
9790
|
expected_output: { type: "string", description: "Description of the expected output format or content" },
|
|
9492
9791
|
context: { type: "string", description: "Additional context provided to the agent for this task" },
|
|
9493
|
-
tools: { type: "string[]", description: "Tools the agent may use for this task" },
|
|
9494
9792
|
output_file: { type: "string", description: "File path where the agent should write output" },
|
|
9495
9793
|
blocking: { type: "boolean", description: "Whether this task blocks downstream tasks" },
|
|
9496
9794
|
priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Relative priority of this task" }
|
|
@@ -9532,7 +9830,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9532
9830
|
summary_metrics: { type: "string", description: "Key-metric summary" },
|
|
9533
9831
|
started_at: { type: "string", description: "ISO timestamp started" },
|
|
9534
9832
|
completed_at: { type: "string", description: "ISO timestamp completed" },
|
|
9535
|
-
foundation_model: { type: "string", description: "Foundation starting model" },
|
|
9536
9833
|
training_steps: { type: "number", description: "Training steps or epochs completed" },
|
|
9537
9834
|
artifact_uri: { type: "string", description: "Produced artifact URI" },
|
|
9538
9835
|
notes: { type: "string", description: "Free-text notes" },
|
|
@@ -9763,7 +10060,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9763
10060
|
environment: { type: "string", description: 'Observed environment (e.g. "prod", "staging", "iOS 17.4")' },
|
|
9764
10061
|
priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Urgency relative to other work. Independent of `bug_severity` (a critical bug can have low priority if rare)." },
|
|
9765
10062
|
assignee: { type: "string", description: "Assigned person" },
|
|
9766
|
-
affected_version: { type: "string", description: "Product version where first observed. Helps triage regressions." },
|
|
9767
10063
|
due_date: { type: "string", description: "ISO date due. Often tied to a release gate or SLA." },
|
|
9768
10064
|
labels: { type: "string[]", description: "Free-form classification tags. Applied uniformly across work item types." }
|
|
9769
10065
|
},
|
|
@@ -9779,9 +10075,9 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9779
10075
|
business_model: {
|
|
9780
10076
|
framework_id: { type: "string", description: "Framework ID (references `UPGFramework.id`)" },
|
|
9781
10077
|
stage: { type: "string", enum: ["draft", "validated", "active"], description: "Maturity" },
|
|
9782
|
-
pattern: { type: "string", enum: ["freemium", "marketplace", "saas", "subscription", "transactional", "advertising", "licensing", "hybrid"], description: "Canonical pattern. Useful for benchmarking against peer businesses with the same shape." }
|
|
9783
|
-
monetisation_basis
|
|
9784
|
-
north_star_metric
|
|
10078
|
+
pattern: { type: "string", enum: ["freemium", "marketplace", "saas", "subscription", "transactional", "advertising", "licensing", "hybrid"], description: "Canonical pattern. Useful for benchmarking against peer businesses with the same shape." }
|
|
10079
|
+
// monetisation_basis removed in 0.12.0 (P14 Bucket C) — categorical rollup of revenue_stream.billing_model.
|
|
10080
|
+
// north_star_metric removed in 0.12.0 (P14) → `business_model_guided_by_metric` edge.
|
|
9785
10081
|
},
|
|
9786
10082
|
// CapabilityProperties: Capability entity.
|
|
9787
10083
|
capability: {
|
|
@@ -9849,8 +10145,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9849
10145
|
// ClassificationAxisProperties: ClassificationAxis: a dimension along which subjects are classified.
|
|
9850
10146
|
classification_axis: {
|
|
9851
10147
|
axis_kind: { type: "string", enum: ["categorical", "ordinal", "continuous"], description: "Structural kind of values on this axis. `categorical` = discrete, unordered (most common; CMS architectures). `ordinal` = discrete, ordered (maturity tiers, T-shirt sizes). `continuous` = numeric range (latency budget, price points)." },
|
|
9852
|
-
cardinality: { type: "string", enum: ["single", "multi"], description: 'How many values a subject may hold on this axis at once (UPG 0.11.3). `single` (default) = a subject sits at exactly one value; a re-classification to a new value SUPERSEDES the prior one (the classify writer retires the old same-axis edge and records the move in the reclassification history). `multi` = a subject may legitimately hold several values at once (e.g. an axis like "supported frameworks"); re-classifying ADDS a value and does not supersede. A separate axis from `axis_kind`: an axis can be `categorical` (unordered) yet `single`-select, or `categorical` yet `multi`-select.' }
|
|
9853
|
-
owner_product: { type: "string", description: "Product id when product-specific. Axes are usually product-agnostic; leave empty for shared taxonomies." }
|
|
10148
|
+
cardinality: { type: "string", enum: ["single", "multi"], description: 'How many values a subject may hold on this axis at once (UPG 0.11.3). `single` (default) = a subject sits at exactly one value; a re-classification to a new value SUPERSEDES the prior one (the classify writer retires the old same-axis edge and records the move in the reclassification history). `multi` = a subject may legitimately hold several values at once (e.g. an axis like "supported frameworks"); re-classifying ADDS a value and does not supersede. A separate axis from `axis_kind`: an axis can be `categorical` (unordered) yet `single`-select, or `categorical` yet `multi`-select.' }
|
|
9854
10149
|
},
|
|
9855
10150
|
// ClassificationValueProperties: ClassificationValue: a value on a classification axis.
|
|
9856
10151
|
classification_value: {
|
|
@@ -9861,7 +10156,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9861
10156
|
},
|
|
9862
10157
|
// CodeRepositoryProperties: Code repository.
|
|
9863
10158
|
code_repository: {
|
|
9864
|
-
repo_url: { type: "string", description: "URL" },
|
|
10159
|
+
repo_url: { type: "string", description: "URL", modifier: "volatile" },
|
|
9865
10160
|
default_branch: { type: "string", description: "Default branch" },
|
|
9866
10161
|
language: { type: "string", description: "Primary programming language" },
|
|
9867
10162
|
ci_status: { type: "string", enum: ["passing", "failing", "unknown"], description: "Current CI status" },
|
|
@@ -10122,7 +10417,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10122
10417
|
data_classification: {
|
|
10123
10418
|
level: { type: "string", enum: ["public", "internal", "confidential", "restricted"], description: "Sensitivity level" },
|
|
10124
10419
|
handling_requirements: { type: "string", description: "Handling rules" },
|
|
10125
|
-
examples: { type: "string", description: "Example data covered" },
|
|
10420
|
+
examples: { type: "string[]", description: "Example data covered" },
|
|
10126
10421
|
retention_period: { type: "string", description: "Retention period" },
|
|
10127
10422
|
encryption_required: { type: "boolean", description: "Whether encryption is mandatory" }
|
|
10128
10423
|
},
|
|
@@ -10219,8 +10514,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10219
10514
|
decision_outcome: { type: "string", description: "Outcome text. What was decided. Separate from `rationale` (which explains why)." },
|
|
10220
10515
|
consequences: { type: "string", description: `Known positive and negative consequences. Mirrors MADR's "Consequences" section.` },
|
|
10221
10516
|
decision_makers: { type: "string[]", description: `People who made the decision. Mirrors MADR's "Deciders" field.` },
|
|
10222
|
-
decision_drivers: { type: "string[]", description: `Forces, constraints, and goals that shaped the decision. Mirrors MADR's "Decision Drivers" section. @example ["must work offline", "team has no Go expertise", "cost < $500/mo"]` }
|
|
10223
|
-
superseded_by: { type: "string", description: "Reference to the superseding decision, if any." }
|
|
10517
|
+
decision_drivers: { type: "string[]", description: `Forces, constraints, and goals that shaped the decision. Mirrors MADR's "Decision Drivers" section. @example ["must work offline", "team has no Go expertise", "cost < $500/mo"]` }
|
|
10224
10518
|
},
|
|
10225
10519
|
// DeliverableProperties: Deliverable.
|
|
10226
10520
|
deliverable: {
|
|
@@ -10616,7 +10910,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10616
10910
|
feature_area: {
|
|
10617
10911
|
scope_summary: { type: "string", description: "One-line scope description. Disambiguates from sibling areas at a glance." },
|
|
10618
10912
|
owning_team: { type: "string", description: "Team identifier or slug. Free-form display. Canonical relationship is the `team_owns_feature_area` edge." },
|
|
10619
|
-
feature_count: { type: "number", description: "Approximate feature count under this area. Snapshot; `feature_area_contains_feature` edges are the source of truth." },
|
|
10913
|
+
feature_count: { type: "number", description: "Approximate feature count under this area. Snapshot; `feature_area_contains_feature` edges are the source of truth.", modifier: "derived" },
|
|
10620
10914
|
owner: { type: "string", description: "Area owner (handle or email)" },
|
|
10621
10915
|
priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Importance to the product overall" },
|
|
10622
10916
|
maturity: { type: "string", enum: ["nascent", "growing", "mature", "legacy"], description: "Maturity. `nascent` = newly-formed grouping. `mature` = established surface. `legacy` = being phased out for a successor." },
|
|
@@ -10733,7 +11027,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10733
11027
|
// FunnelProperties: Funnel entity.
|
|
10734
11028
|
funnel: {
|
|
10735
11029
|
funnel_type: { type: "string", enum: ["acquisition", "activation", "retention", "revenue", "referral", "custom"], description: "Which stage of the customer lifecycle this funnel measures" },
|
|
10736
|
-
step_count: { type: "number", description: "Number of steps in the funnel" },
|
|
11030
|
+
step_count: { type: "number", description: "Number of steps in the funnel", modifier: "derived" },
|
|
10737
11031
|
overall_conversion_rate: { type: "number", description: "End-to-end conversion rate through the funnel (0-1)" }
|
|
10738
11032
|
},
|
|
10739
11033
|
// FunnelStepProperties: FunnelStep entity.
|
|
@@ -10754,7 +11048,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10754
11048
|
end_date: { type: "string", description: "ISO end date" },
|
|
10755
11049
|
budget_amount: { type: "number", description: "Total allocated budget. Use with `budget_currency`." },
|
|
10756
11050
|
budget_currency: { type: "string", description: 'ISO 4217 currency code (e.g. "USD", "EUR", "GBP")' },
|
|
10757
|
-
channels_targeted: { type: "string[]", description: 'Channels the campaign runs across. Free-form so partner channels and ad networks both fit (e.g. "google_ads", "linkedin", "podcast_sponsorship").' },
|
|
10758
11051
|
primary_kpi: { type: "string", description: 'Primary KPI optimised for (e.g. "qualified_signups", "MQL_volume", "activated_teams")' },
|
|
10759
11052
|
kpi_target: { type: "number", description: "Numeric target for `primary_kpi` over the campaign window" },
|
|
10760
11053
|
utm_parameters: { type: "string", description: "UTM tracking parameters for this campaign" },
|
|
@@ -10788,7 +11081,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10788
11081
|
required: ["value", "label"]
|
|
10789
11082
|
},
|
|
10790
11083
|
user_facing: { type: "boolean", description: "Visible to end users" },
|
|
10791
|
-
root_cause: { type: "string", description: "Identified cause" },
|
|
10792
11084
|
remediation: { type: "string", description: "Remediation steps" }
|
|
10793
11085
|
},
|
|
10794
11086
|
// HelpVideoProperties: Help video.
|
|
@@ -10886,7 +11178,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10886
11178
|
},
|
|
10887
11179
|
required: ["value", "label"]
|
|
10888
11180
|
},
|
|
10889
|
-
evidence_count: { type: "number", description: "Supporting observations, quotes, or evidence items. Higher counts increase confidence." },
|
|
11181
|
+
evidence_count: { type: "number", description: "Supporting observations, quotes, or evidence items. Higher counts increase confidence.", modifier: "derived" },
|
|
10890
11182
|
novelty: { type: "string", enum: ["known", "surprising", "contradictory"], description: "Novelty against existing knowledge. `known` = confirms what we already believed. `surprising` = challenges or extends our understanding. `contradictory` = directly conflicts with a prior assumption." },
|
|
10891
11183
|
actionability: { type: "string", enum: ["immediate", "needs_validation", "informational"], description: "Current actionability. `immediate` = clear action, no further research needed. `needs_validation` = promising but requires more evidence. `informational` = important context, no direct action." },
|
|
10892
11184
|
source_method: { type: "string", description: 'Producing research method. @example "usability_study", "interview_series", "survey"' },
|
|
@@ -11042,7 +11334,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11042
11334
|
// JourneyStepProperties: Single step within a user journey. A user-moment on the journey's single
|
|
11043
11335
|
journey_step: {
|
|
11044
11336
|
step_order: { type: "number", description: "Display order within the journey's step timeline (0-indexed). The scalar ordering convention shared with `journey_phase.phase_order` and `journey_action.action_order` (UPG-663). For branching journeys, the explicit `journey_step_precedes_journey_step` edge captures the chain." },
|
|
11045
|
-
touchpoint: { type: "string", description: "@deprecated since v0.9.9 (UPG-675). Touchpoints are modelled in two places, neither of which is this string: the `touchpoint` *entity* is the cross-channel customer-success layer (`touchpoint_occurs_in_journey_step`), and `journey_action` is the in-product blueprint layer (the finest band of a `journey_step`). Use one of those rather than a free-text string here. Removed in a future major." },
|
|
11046
11337
|
channel: { type: "string", description: 'Channel (e.g. "web", "email", "in-store")' },
|
|
11047
11338
|
emotion_score: {
|
|
11048
11339
|
type: "assessment",
|
|
@@ -11115,8 +11406,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11115
11406
|
// LaunchProperties: Launch entity.
|
|
11116
11407
|
launch: {
|
|
11117
11408
|
launch_type: { type: "string", enum: ["soft", "beta", "public", "feature"], description: "Scale and audience of the launch" },
|
|
11118
|
-
target_date: { type: "string", description: "Planned launch date (ISO format)" }
|
|
11119
|
-
success_metrics: { type: "string[]", description: "Metrics that define launch success" }
|
|
11409
|
+
target_date: { type: "string", description: "Planned launch date (ISO format)" }
|
|
11120
11410
|
},
|
|
11121
11411
|
// LeadProperties: Lead.
|
|
11122
11412
|
lead: {
|
|
@@ -11276,7 +11566,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11276
11566
|
range_min: { type: "number", description: "Minimum expected or baseline value" },
|
|
11277
11567
|
range_max: { type: "number", description: "Maximum expected or ceiling value" },
|
|
11278
11568
|
cadence: { type: "string", enum: ["continuous", "hourly", "daily", "weekly", "monthly", "quarterly", "yearly", "on_demand", "other"], description: "Measurement cadence. Canonical `Cadence` since v0.4.0. `'realtime'` migrates to `'continuous'`; all other values 1:1." },
|
|
11279
|
-
data_source: { type: "string", description: 'Data source or tool that feeds this metric (e.g. "PostHog", "Stripe")' },
|
|
11280
11569
|
owner: { type: "string", description: "Person or team responsible for tracking this metric" },
|
|
11281
11570
|
metric_health: { type: "string", enum: ["healthy", "at_risk", "unhealthy", "unknown"], description: "Universal health rollup. Orthogonal to lifecycle and `guardrail_status`. Applies to every metric regardless of `designation`. `healthy` = trending well against target / inside safe range. `at_risk` = drifting, approaching breach or target shortfall. `unhealthy` = missed target or breached; action needed. `unknown` = no current reading or not yet measured. For guardrails specifically, `guardrail_status` remains the breach-specific signal (`safe`/`warning`/`breached`)." },
|
|
11282
11571
|
guardrail_threshold_min: { type: "number", description: "Lower bound for guardrail safety (below this = breach)" },
|
|
@@ -11294,8 +11583,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11294
11583
|
quality_related: { type: "boolean", description: "Quality signal: metric relates to other key metrics in the system" },
|
|
11295
11584
|
quality_score: { type: "number", description: "Computed quality score across all quality signals (0\u20135)" },
|
|
11296
11585
|
proxy_reason: { type: "string", enum: ["qualitative", "no_direct_measure", "not_yet_instrumented", "too_expensive"], description: "Why this metric is used as a proxy instead of measuring directly" },
|
|
11297
|
-
proxy_confidence: { type: "string", enum: ["strong", "moderate", "weak"], description: "How strongly this metric predicts the direct measure" }
|
|
11298
|
-
proxy_alternatives: { type: "string[]", description: "Other metrics considered as proxy candidates" }
|
|
11586
|
+
proxy_confidence: { type: "string", enum: ["strong", "moderate", "weak"], description: "How strongly this metric predicts the direct measure" }
|
|
11299
11587
|
},
|
|
11300
11588
|
// MilestoneProperties: Milestone.
|
|
11301
11589
|
milestone: {
|
|
@@ -11311,7 +11599,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11311
11599
|
},
|
|
11312
11600
|
// ModelComparisonProperties: Model comparison.
|
|
11313
11601
|
model_comparison: {
|
|
11314
|
-
model_ids: { type: "string[]", description: "Compared model identifiers" },
|
|
11315
11602
|
comparison_criteria: { type: "string[]", description: 'Comparison dimensions (e.g. "accuracy", "cost", "latency")' },
|
|
11316
11603
|
comparison_date: { type: "string", description: "ISO conduct date" }
|
|
11317
11604
|
},
|
|
@@ -11488,7 +11775,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11488
11775
|
// ParticipantProperties: Research participant.
|
|
11489
11776
|
participant: {
|
|
11490
11777
|
alias: { type: "string", description: 'Anonymous alias for privacy (e.g. "P01")' },
|
|
11491
|
-
segment: { type: "string", description: "User segment this participant belongs to" },
|
|
11492
11778
|
recruit_source: { type: "string", description: "How the participant was recruited" },
|
|
11493
11779
|
consent_status: { type: "string", enum: ["pending", "given", "withdrawn"], description: "Current consent status for data usage" }
|
|
11494
11780
|
},
|
|
@@ -11560,7 +11846,8 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11560
11846
|
motivation: { type: "string", description: 'Primary motivation or driving need @example "Making confident, evidence-based decisions"' },
|
|
11561
11847
|
tech_comfort: { type: "string", enum: ["low", "medium", "high", "expert", "other"], description: "Tech comfort. Closed set so personas across products compare on the same axis. Free-text colour belongs in `context` or `motivation`." },
|
|
11562
11848
|
domain_expertise: { type: "string", description: 'Industry or domain knowledge this persona brings @example "10+ years SaaS experience", "New to healthcare IT"' },
|
|
11563
|
-
audience_role: { type: "string", enum: ["buyer", "user", "champion", "influencer", "partner"], description: 'Role in the buying / adoption decision (the decision-making-unit split): who signs (buyer) vs who uses (user) vs who advocates internally (champion) vs who shapes the choice (influencer) vs who delivers / implements (partner). A portfolio must separate the economic buyer from the practitioner user; they are distinct personas with distinct jobs. Closed set so roles compare across products. @example "buyer"' }
|
|
11849
|
+
audience_role: { type: "string", enum: ["buyer", "user", "champion", "influencer", "partner"], description: 'Role in the buying / adoption decision (the decision-making-unit split): who signs (buyer) vs who uses (user) vs who advocates internally (champion) vs who shapes the choice (influencer) vs who delivers / implements (partner). A portfolio must separate the economic buyer from the practitioner user; they are distinct personas with distinct jobs. Closed set so roles compare across products. @example "buyer"' },
|
|
11850
|
+
actor_kind: { type: "string", enum: ["human", "agent", "system"], description: "Who performs the work: a human archetype (default; absent = human, no migration), an autonomous AI agent (e.g. Content Agent), or a non-agentic platform service. An agent persona participates in journeys via the same persona machinery and is delegated to via persona_delegates_to_persona. Human-coverage / segmentation metrics count human only; agent/system opt-in." }
|
|
11564
11851
|
},
|
|
11565
11852
|
// PipelineSalesProperties: Sales pipeline.
|
|
11566
11853
|
pipeline_sales: {
|
|
@@ -11623,13 +11910,27 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11623
11910
|
defined_by: { type: "string", description: "The `specification/<slug>` this primitive comes from; nullable for spec-less internal primitives. Mirrors the `primitive_defined_by_specification` edge for quick lookup." },
|
|
11624
11911
|
since: { type: "string", description: "Year or version the primitive was introduced." }
|
|
11625
11912
|
},
|
|
11913
|
+
// OperatingLifecycleProperties: a canonical ordered (often cyclic) operating process products' journey phases map onto.
|
|
11914
|
+
operating_lifecycle: {
|
|
11915
|
+
label: { type: "string", description: "Human-readable name of the operating process." },
|
|
11916
|
+
cyclic: { type: "boolean", description: "True if the process loops (e.g. Analyze \u2192 Extend \u2192 Plan). Rendered linearly by stage_order with the wrap on the final stage." },
|
|
11917
|
+
source: { type: "string", description: 'Origin of the canonical model (e.g. "Sanity official content-ops lifecycle").' }
|
|
11918
|
+
},
|
|
11919
|
+
// OperatingStageProperties: one ordered stage of an operating_lifecycle.
|
|
11920
|
+
operating_stage: {
|
|
11921
|
+
stage_order: { type: "number", description: "Ordered position within the lifecycle, 0-indexed." },
|
|
11922
|
+
label: { type: "string", description: "Human-readable stage name." },
|
|
11923
|
+
goal: { type: "string", description: "What this stage accomplishes." },
|
|
11924
|
+
owner_role: { type: "string", description: "Role that owns the stage (free-text role label)." },
|
|
11925
|
+
os_analogy: { type: "string", description: 'The Content-OS analogy from the source volume (e.g. "Drivers + daemons / cron").' },
|
|
11926
|
+
next_stage: { type: "string", description: "Label of the next stage; on the final stage of a cyclic lifecycle this carries the wrap." }
|
|
11927
|
+
},
|
|
11626
11928
|
// PrivacyPolicyProperties: Privacy policy.
|
|
11627
11929
|
privacy_policy: {
|
|
11628
11930
|
version: { type: "string", description: "Version identifier of the policy" },
|
|
11629
11931
|
last_updated: { type: "string", description: "Date the policy was last updated (ISO format)" },
|
|
11630
11932
|
effective_date: { type: "string", description: "Date the policy takes effect (ISO format)" },
|
|
11631
|
-
url: { type: "string", description: "URL where the policy is published" }
|
|
11632
|
-
regulations: { type: "string[]", description: 'Regulations this policy addresses (e.g. "GDPR", "CCPA")' }
|
|
11933
|
+
url: { type: "string", description: "URL where the policy is published" }
|
|
11633
11934
|
},
|
|
11634
11935
|
// ProductProperties: The product being created. Root of the graph.
|
|
11635
11936
|
product: {
|
|
@@ -12021,9 +12322,8 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
12021
12322
|
},
|
|
12022
12323
|
// ServiceLevelIndicatorProperties: Service Level Indicator.
|
|
12023
12324
|
service_level_indicator: {
|
|
12024
|
-
metric_name: { type: "string", description: 'Indicator metric name. @example "Request latency p99", "Error rate", "Availability"' },
|
|
12025
12325
|
threshold: { type: "number", description: 'Threshold that defines a "good" event. @example 200 (ms latency), 0.01 (1% error rate), 99.9 (% availability)' },
|
|
12026
|
-
current_value: { type: "number", description: "Current observed value. Compared against `threshold` for SLO compliance. @example 150 (ms), 0.003 (0.3% error rate)" },
|
|
12326
|
+
current_value: { type: "number", description: "Current observed value. Compared against `threshold` for SLO compliance. @example 150 (ms), 0.003 (0.3% error rate)", modifier: "snapshot" },
|
|
12027
12327
|
unit: { type: "string", description: 'Unit of measurement. Required to interpret `threshold` and `current_value`. @example "ms", "%", "req/s", "errors/min"' },
|
|
12028
12328
|
aggregation: { type: "string", enum: ["avg", "sum", "max", "min", "p50", "p95", "p99", "count"], description: 'Aggregation over the evaluation window. p99 and avg tell different stories. @example "p99" for tail latency, "avg" for mean throughput, "count" for total events' },
|
|
12029
12329
|
measurement_query: { type: "string", description: "Query expression that produces `current_value`. Free-form to fit PromQL, Datadog query strings, SQL, or vendor-specific DSLs. @example 'sum(rate(http_requests_total{status=~\"5..\"}[5m])) / sum(rate(http_requests_total[5m]))'" },
|
|
@@ -12179,7 +12479,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
12179
12479
|
},
|
|
12180
12480
|
// SubscriptionProperties: Subscription.
|
|
12181
12481
|
subscription: {
|
|
12182
|
-
plan_name: { type: "string", description: "Name of the subscribed plan" },
|
|
12183
12482
|
monthly_recurring_revenue: { type: "number", description: "Monthly recurring revenue from this subscription" },
|
|
12184
12483
|
start_date: { type: "string", description: "Subscription start date (ISO format)" },
|
|
12185
12484
|
renewal_date: { type: "string", description: "Next renewal date (ISO format)" },
|
|
@@ -12272,8 +12571,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
12272
12571
|
team_okr: {
|
|
12273
12572
|
period: { type: "string", description: 'Time period for the OKR (e.g. "Q2 2026")' },
|
|
12274
12573
|
progress: { type: "number", description: "Overall progress toward the objective (0-100%)" },
|
|
12275
|
-
objective_statement: { type: "string", description: "The team-level objective statement (key results live in child entities)" }
|
|
12276
|
-
cascade_from: { type: "string", description: "Higher-level objective this OKR cascades from (company or department OKR)" }
|
|
12574
|
+
objective_statement: { type: "string", description: "The team-level objective statement (key results live in child entities)" }
|
|
12277
12575
|
},
|
|
12278
12576
|
// TechnicalDebtItemProperties: Technical debt item.
|
|
12279
12577
|
technical_debt_item: {
|
|
@@ -12526,7 +12824,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
12526
12824
|
},
|
|
12527
12825
|
cvss_version: { type: "string", enum: ["v3.1", "v4.0"], description: 'CVSS scoring version. v3.1 and v4.0 differ significantly for the same vulnerability. @example "v4.0" for vulnerabilities scored after the v4.0 release in 2023' },
|
|
12528
12826
|
affected_component: { type: "string", description: 'Affected component, library, or system. @example "lodash", "openssl", "login service"' },
|
|
12529
|
-
affected_package: { type: "string", description: 'Affected package with version. More precise than `affected_component`. @example "lodash@4.17.20", "openssl@1.1.1q"' },
|
|
12530
12827
|
exploit_maturity: { type: "string", enum: ["no_known_exploit", "proof_of_concept", "functional_exploit", "active_exploitation"], description: 'Exploit maturity. Primary prioritisation factor after severity. `no_known_exploit` = theoretical. `proof_of_concept` = exploit code exists, not weaponised. `functional_exploit` = working exploit available. `active_exploitation` = active in the wild. @example "active_exploitation" demands immediate response regardless of severity score' },
|
|
12531
12828
|
fix_available: { type: "boolean", description: "Patch availability. Common triage question after severity. @example false for a zero-day with no available patch" },
|
|
12532
12829
|
disclosed_at: { type: "string", description: 'ISO date publicly disclosed. Time since disclosure matters for SLA. @example "2024-03-15"' },
|
|
@@ -12551,7 +12848,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
12551
12848
|
// WireframeProperties: Wireframe.
|
|
12552
12849
|
wireframe: {
|
|
12553
12850
|
fidelity: { type: "string", enum: ["low", "medium", "high"], description: "Detail level" },
|
|
12554
|
-
screen_name: { type: "string", description: "Represented screen name" },
|
|
12555
12851
|
version: { type: "string", description: 'Version or iteration (e.g. "v2", "2026-04-B")' },
|
|
12556
12852
|
tool: { type: "string", description: 'Authoring tool. @example "Figma", "Balsamiq", "pen and paper"' },
|
|
12557
12853
|
review_status: { type: "string", enum: ["draft", "in_review", "approved", "rejected"], description: "Review gate status" },
|
|
@@ -12569,7 +12865,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
12569
12865
|
completed_at: { type: "string", description: "ISO timestamp when the run completed" },
|
|
12570
12866
|
run_status: { type: "string", enum: ["pending", "running", "completed", "failed", "canceled"], description: "Current execution status of the run" },
|
|
12571
12867
|
triggering_event: { type: "string", description: "Event or action that triggered this run" },
|
|
12572
|
-
step_count: { type: "number", description: "Number of steps executed in this run" },
|
|
12868
|
+
step_count: { type: "number", description: "Number of steps executed in this run", modifier: "derived" },
|
|
12573
12869
|
total_tokens: { type: "number", description: "Total tokens consumed across all steps" },
|
|
12574
12870
|
total_cost: { type: "number", description: "Total monetary cost of the run" },
|
|
12575
12871
|
error_message: { type: "string", description: "Error message if the run failed" }
|
|
@@ -12577,8 +12873,8 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
12577
12873
|
// WorkflowTemplateProperties: Workflow template.
|
|
12578
12874
|
workflow_template: {
|
|
12579
12875
|
template_type: { type: "string", enum: ["sequential", "parallel", "conditional", "loop"], description: "Execution pattern for the workflow steps" },
|
|
12580
|
-
step_count: { type: "number", description: "Number of steps in the workflow" },
|
|
12581
|
-
agent_count: { type: "number", description: "Number of agents involved in the workflow" },
|
|
12876
|
+
step_count: { type: "number", description: "Number of steps in the workflow", modifier: "derived" },
|
|
12877
|
+
agent_count: { type: "number", description: "Number of agents involved in the workflow", modifier: "derived" },
|
|
12582
12878
|
estimated_duration: { type: "string", description: "Estimated wall-clock duration of a full run" },
|
|
12583
12879
|
state_schema: { type: "string", description: "Schema describing the workflow's state object" },
|
|
12584
12880
|
checkpoint_enabled: { type: "boolean", description: "Whether the workflow supports checkpointing for recovery" },
|
|
@@ -19077,6 +19373,8 @@ var ENTITY_EMOJI = {
|
|
|
19077
19373
|
pricing_strategy: "\u{1F4B1}",
|
|
19078
19374
|
pricing_tier: "\u{1F949}",
|
|
19079
19375
|
primitive: "\u{1F4CB}",
|
|
19376
|
+
operating_lifecycle: "\u{1F504}",
|
|
19377
|
+
operating_stage: "\u{1F539}",
|
|
19080
19378
|
privacy_policy: "\u{1F6E1}\uFE0F",
|
|
19081
19379
|
product: "\u{1F9EC}",
|
|
19082
19380
|
product_area: "\u{1FA80}",
|
|
@@ -22889,7 +23187,7 @@ var WORKSPACE_GUIDE = {
|
|
|
22889
23187
|
var FOUNDATIONS_GUIDE = {
|
|
22890
23188
|
domain_id: "foundations",
|
|
22891
23189
|
anchor_entity: "specification",
|
|
22892
|
-
creation_sequence: ["specification", "primitive"],
|
|
23190
|
+
creation_sequence: ["specification", "primitive", "operating_lifecycle", "operating_stage"],
|
|
22893
23191
|
patterns: [
|
|
22894
23192
|
{
|
|
22895
23193
|
name: "Specification defines primitives",
|
|
@@ -26256,6 +26554,7 @@ var UPG_REGIONS = [
|
|
|
26256
26554
|
"persona_experiences_need",
|
|
26257
26555
|
"persona_aspires_to_desired_outcome",
|
|
26258
26556
|
"persona_incurs_switching_cost",
|
|
26557
|
+
"persona_delegates_to_persona",
|
|
26259
26558
|
"job_surfaces_need"
|
|
26260
26559
|
],
|
|
26261
26560
|
boundary_edges: [
|
|
@@ -28275,6 +28574,14 @@ var UPG_REGIONS = [
|
|
|
28275
28574
|
{
|
|
28276
28575
|
type: "primitive",
|
|
28277
28576
|
role: "container"
|
|
28577
|
+
},
|
|
28578
|
+
{
|
|
28579
|
+
type: "operating_lifecycle",
|
|
28580
|
+
role: "container"
|
|
28581
|
+
},
|
|
28582
|
+
{
|
|
28583
|
+
type: "operating_stage",
|
|
28584
|
+
role: "leaf"
|
|
28278
28585
|
}
|
|
28279
28586
|
],
|
|
28280
28587
|
anchor: {
|
|
@@ -28287,9 +28594,21 @@ var UPG_REGIONS = [
|
|
|
28287
28594
|
"specification_extends_specification",
|
|
28288
28595
|
"specification_competes_with_specification",
|
|
28289
28596
|
"primitive_defined_by_specification",
|
|
28290
|
-
"primitive_composes_primitive"
|
|
28597
|
+
"primitive_composes_primitive",
|
|
28598
|
+
"operating_lifecycle_contains_operating_stage"
|
|
28291
28599
|
],
|
|
28292
|
-
boundary_edges: [
|
|
28600
|
+
boundary_edges: [
|
|
28601
|
+
{
|
|
28602
|
+
direction: "import",
|
|
28603
|
+
edge_id: "journey_phase_realises_operating_stage",
|
|
28604
|
+
crosses_into: "experience_design_brand"
|
|
28605
|
+
},
|
|
28606
|
+
{
|
|
28607
|
+
direction: "export",
|
|
28608
|
+
edge_id: "operating_stage_measured_by_metric",
|
|
28609
|
+
crosses_into: "analytics_data"
|
|
28610
|
+
}
|
|
28611
|
+
]
|
|
28293
28612
|
}
|
|
28294
28613
|
];
|
|
28295
28614
|
var UPG_REGION_MAP = Object.fromEntries(UPG_REGIONS.map((r) => [r.id, r]));
|
|
@@ -28815,7 +29134,7 @@ function isCanonical(text) {
|
|
|
28815
29134
|
}
|
|
28816
29135
|
|
|
28817
29136
|
// src/index.ts
|
|
28818
|
-
var UPG_VERSION = "0.
|
|
29137
|
+
var UPG_VERSION = "0.12.0";
|
|
28819
29138
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
28820
29139
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
28821
29140
|
var UPG_TYPES = getTypes();
|
|
@@ -28950,6 +29269,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
28950
29269
|
UPG_REGION_COUNT,
|
|
28951
29270
|
UPG_REGION_MAP,
|
|
28952
29271
|
UPG_RELATIONSHIP_BENCHMARKS,
|
|
29272
|
+
UPG_SCALAR_TO_EDGE_MIGRATIONS,
|
|
28953
29273
|
UPG_SCALES,
|
|
28954
29274
|
UPG_SPLIT_MIGRATIONS,
|
|
28955
29275
|
UPG_STATUS_MIGRATIONS,
|
|
@@ -29018,6 +29338,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
29018
29338
|
getRegionForEntityType,
|
|
29019
29339
|
getReplacementType,
|
|
29020
29340
|
getRingForDomain,
|
|
29341
|
+
getScalarToEdgeMigrations,
|
|
29021
29342
|
getScale,
|
|
29022
29343
|
getSplitMigrations,
|
|
29023
29344
|
getTreePattern,
|