@unified-product-graph/core 0.7.4 → 0.8.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/CHANGELOG.md +33 -0
- package/dist/index.cjs +1042 -349
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +387 -141
- package/dist/index.d.ts +387 -141
- package/dist/index.js +1032 -349
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -43,12 +43,14 @@ __export(index_exports, {
|
|
|
43
43
|
OPERATIONS_TEAM_RITUALS_PLAYBOOK: () => OPERATIONS_TEAM_RITUALS_PLAYBOOK,
|
|
44
44
|
PRODUCT_DELIVERY_PLAYBOOK: () => PRODUCT_DELIVERY_PLAYBOOK,
|
|
45
45
|
PRODUCT_FEEDBACK_SYNTHESIS_PLAYBOOK: () => PRODUCT_FEEDBACK_SYNTHESIS_PLAYBOOK,
|
|
46
|
+
PROPERTY_SCALE_MAP: () => PROPERTY_SCALE_MAP,
|
|
46
47
|
REFLECT_MODES: () => REFLECT_MODES,
|
|
47
48
|
STRATEGY_OUTCOMES_PLAYBOOK: () => STRATEGY_OUTCOMES_PLAYBOOK,
|
|
48
49
|
UPG_ACTIVE_TYPES: () => UPG_ACTIVE_TYPES,
|
|
49
50
|
UPG_ANTI_PATTERNS: () => UPG_ANTI_PATTERNS,
|
|
50
51
|
UPG_APPROACHES: () => UPG_APPROACHES,
|
|
51
52
|
UPG_APPROACHES_BY_ID: () => UPG_APPROACHES_BY_ID,
|
|
53
|
+
UPG_CANONICAL_FORMAT_VERSION: () => UPG_CANONICAL_FORMAT_VERSION,
|
|
52
54
|
UPG_CONTAINMENT_FREE_TYPES: () => UPG_CONTAINMENT_FREE_TYPES,
|
|
53
55
|
UPG_COUNT_BENCHMARKS: () => UPG_COUNT_BENCHMARKS,
|
|
54
56
|
UPG_CROSS_EDGE_TYPES: () => UPG_CROSS_EDGE_TYPES,
|
|
@@ -112,8 +114,10 @@ __export(index_exports, {
|
|
|
112
114
|
coerceProductStage: () => coerceProductStage,
|
|
113
115
|
collectSlugsForType: () => collectSlugsForType,
|
|
114
116
|
compareVersions: () => compareVersions,
|
|
117
|
+
computeBodyChecksum: () => computeBodyChecksum,
|
|
115
118
|
evaluateAntiPatterns: () => evaluateAntiPatterns,
|
|
116
119
|
findInvalidStatusMigrationTargets: () => findInvalidStatusMigrationTargets,
|
|
120
|
+
formatUpgText: () => formatUpgText,
|
|
117
121
|
generateSlug: () => generateSlug,
|
|
118
122
|
getAnchorEntity: () => getAnchorEntity,
|
|
119
123
|
getAntiPatternById: () => getAntiPatternById,
|
|
@@ -140,6 +144,7 @@ __export(index_exports, {
|
|
|
140
144
|
getMigrationMap: () => getMigrationMap,
|
|
141
145
|
getPlaybookById: () => getPlaybookById,
|
|
142
146
|
getPlaybooksForRegion: () => getPlaybooksForRegion,
|
|
147
|
+
getPropertiesForScale: () => getPropertiesForScale,
|
|
143
148
|
getPropertyDefaultScale: () => getPropertyDefaultScale,
|
|
144
149
|
getPropertyMigrations: () => getPropertyMigrations,
|
|
145
150
|
getPropertySchema: () => getPropertySchema,
|
|
@@ -156,6 +161,7 @@ __export(index_exports, {
|
|
|
156
161
|
getValidChildren: () => getValidChildren,
|
|
157
162
|
getVisibleTypes: () => getVisibleTypes,
|
|
158
163
|
hasStatusMigration: () => hasStatusMigration,
|
|
164
|
+
isCanonical: () => isCanonical,
|
|
159
165
|
isCanonicalProductStage: () => isCanonicalProductStage,
|
|
160
166
|
isContainmentFreeType: () => isContainmentFreeType,
|
|
161
167
|
isDeprecatedType: () => isDeprecatedType,
|
|
@@ -166,6 +172,7 @@ __export(index_exports, {
|
|
|
166
172
|
isLifecycleFreeType: () => isLifecycleFreeType,
|
|
167
173
|
isLifecyclePlannedType: () => isLifecyclePlannedType,
|
|
168
174
|
isPolymorphicEdge: () => isPolymorphicEdge,
|
|
175
|
+
isPortfolio: () => isPortfolio,
|
|
169
176
|
isRegisteredPolymorphicEdge: () => isRegisteredPolymorphicEdge,
|
|
170
177
|
isSubSequenceStep: () => isSubSequenceStep,
|
|
171
178
|
isUPGDocument: () => isUPGDocument,
|
|
@@ -175,6 +182,8 @@ __export(index_exports, {
|
|
|
175
182
|
migrateNodeProperties: () => migrateNodeProperties,
|
|
176
183
|
migrateProductStage: () => migrateProductStage,
|
|
177
184
|
migrateStatusValue: () => migrateStatusValue,
|
|
185
|
+
normalizeDocument: () => normalizeDocument,
|
|
186
|
+
parseUpg: () => parseUpg,
|
|
178
187
|
pickCanonicalEdge: () => pickCanonicalEdge,
|
|
179
188
|
resolveAllEdges: () => resolveAllEdges,
|
|
180
189
|
resolveContainmentEdge: () => resolveContainmentEdge,
|
|
@@ -182,6 +191,7 @@ __export(index_exports, {
|
|
|
182
191
|
resolveLabel: () => resolveLabel,
|
|
183
192
|
resolveSlugCollision: () => resolveSlugCollision,
|
|
184
193
|
rotateSlug: () => rotateSlug,
|
|
194
|
+
serializeCanonical: () => serializeCanonical,
|
|
185
195
|
validateProductStageStrict: () => validateProductStageStrict,
|
|
186
196
|
validateUPGDocument: () => validateUPGDocument,
|
|
187
197
|
validateUPGFramework: () => validateUPGFramework,
|
|
@@ -6350,20 +6360,42 @@ var PROPERTY_SCALE_MAP = {
|
|
|
6350
6360
|
// discovery, users, feedback
|
|
6351
6361
|
// ── Severity ─────────────────────────────────────────────────────────────
|
|
6352
6362
|
severity: "severity_5",
|
|
6353
|
-
// users, engineering, ai, gtm, customer-success
|
|
6363
|
+
// users, engineering, ai, gtm, customer-success, security, accessibility
|
|
6354
6364
|
severity_of_finding: "severity_5",
|
|
6355
6365
|
// validation/experiment_run
|
|
6366
|
+
bug_severity: "severity_5",
|
|
6367
|
+
// product-spec/bug (UPG-579 Option C collapse)
|
|
6368
|
+
risk_level: "severity_5",
|
|
6369
|
+
// compliance/risk (UPG-579 Option B)
|
|
6370
|
+
scarcity_risk: "severity_5",
|
|
6371
|
+
// market-intelligence (UPG-579 Option B)
|
|
6356
6372
|
// ── Pain ─────────────────────────────────────────────────────────────────
|
|
6357
6373
|
pain: "pain_5",
|
|
6358
6374
|
// discovery
|
|
6375
|
+
pain_score: "pain_5",
|
|
6376
|
+
// user (UPG-579 Option B)
|
|
6377
|
+
friction_score: "pain_5",
|
|
6378
|
+
// growth/ux (UPG-579 Option B)
|
|
6359
6379
|
// ── Impact ───────────────────────────────────────────────────────────────
|
|
6360
6380
|
impact: "impact_5",
|
|
6361
6381
|
// discovery, market, security, compliance
|
|
6362
6382
|
projected_impact: "impact_5",
|
|
6363
6383
|
// validation/experiment_plan
|
|
6384
|
+
revenue_impact: "impact_5",
|
|
6385
|
+
// sales/business-model (UPG-579 Option B)
|
|
6386
|
+
effectiveness: "impact_5",
|
|
6387
|
+
// security/marketing (UPG-579 Option B)
|
|
6388
|
+
opportunity_score: "impact_5",
|
|
6389
|
+
// discovery/opportunity (UPG-579 Option B)
|
|
6364
6390
|
// ── Confidence ───────────────────────────────────────────────────────────
|
|
6365
6391
|
confidence: "confidence_5",
|
|
6366
6392
|
// discovery, validation, sales, product-spec
|
|
6393
|
+
current_confidence: "confidence_5",
|
|
6394
|
+
// validation/hypothesis (UPG-579 Option B)
|
|
6395
|
+
likelihood: "confidence_5",
|
|
6396
|
+
// market/risk (UPG-579 Option B)
|
|
6397
|
+
probability: "confidence_5",
|
|
6398
|
+
// sales/forecast (UPG-579 Option B)
|
|
6367
6399
|
// ── Effort ───────────────────────────────────────────────────────────────
|
|
6368
6400
|
effort: "effort_5",
|
|
6369
6401
|
// discovery
|
|
@@ -6371,17 +6403,35 @@ var PROPERTY_SCALE_MAP = {
|
|
|
6371
6403
|
// feedback
|
|
6372
6404
|
effort_to_fix: "effort_5",
|
|
6373
6405
|
// engineering
|
|
6406
|
+
cost_estimate: "effort_5",
|
|
6407
|
+
// validation/experiment_plan (UPG-579 Option B)
|
|
6374
6408
|
// ── Importance ───────────────────────────────────────────────────────────
|
|
6375
6409
|
importance: "importance_5",
|
|
6376
6410
|
// users
|
|
6411
|
+
influence: "importance_5",
|
|
6412
|
+
// team-org/stakeholder (UPG-579 Option B)
|
|
6413
|
+
interest: "importance_5",
|
|
6414
|
+
// team-org/stakeholder (UPG-579 Option B)
|
|
6415
|
+
relevance: "importance_5",
|
|
6416
|
+
// market/content (UPG-579 Option B)
|
|
6417
|
+
weight: "importance_5",
|
|
6418
|
+
// validation/evidence (UPG-579 Option B)
|
|
6377
6419
|
// ── Satisfaction ─────────────────────────────────────────────────────────
|
|
6378
|
-
current_satisfaction: "satisfaction_5"
|
|
6420
|
+
current_satisfaction: "satisfaction_5",
|
|
6379
6421
|
// users
|
|
6422
|
+
emotion_score: "satisfaction_5"
|
|
6423
|
+
// ux-design/customer-success journey (UPG-579 Option B)
|
|
6424
|
+
// Intentionally NOT mapped (resolve to the generic scale_5):
|
|
6425
|
+
// rarity : VRIO distinctiveness; no canonical named scale fits.
|
|
6426
|
+
// strength : deprecated (validation/evidence; superseded by weight).
|
|
6380
6427
|
};
|
|
6381
6428
|
var DEFAULT_SCALE_ID = "scale_5";
|
|
6382
6429
|
function getPropertyDefaultScale(_entityType, propertyName) {
|
|
6383
6430
|
return PROPERTY_SCALE_MAP[propertyName] ?? DEFAULT_SCALE_ID;
|
|
6384
6431
|
}
|
|
6432
|
+
function getPropertiesForScale(scaleId) {
|
|
6433
|
+
return Object.entries(PROPERTY_SCALE_MAP).filter(([, id]) => id === scaleId).map(([property]) => property);
|
|
6434
|
+
}
|
|
6385
6435
|
|
|
6386
6436
|
// src/grammar/enum-scales.ts
|
|
6387
6437
|
var UPG_ENUM_SCALES = {
|
|
@@ -6467,6 +6517,159 @@ var UPG_ENUM_SCALES = {
|
|
|
6467
6517
|
{ value: "warning", label: "Warning", description: "Soft signal: should consider and address, but can override with justification." },
|
|
6468
6518
|
{ value: "guideline", label: "Guideline", description: "Recommendation: encouraged and expected in most cases, but not enforced." }
|
|
6469
6519
|
]
|
|
6520
|
+
},
|
|
6521
|
+
// ── ProxyConfidence ─────────────────────────────────────────────────
|
|
6522
|
+
ProxyConfidence: {
|
|
6523
|
+
id: "ProxyConfidence",
|
|
6524
|
+
label: "Proxy confidence",
|
|
6525
|
+
description: "How strongly a proxy metric predicts the direct measure it stands in for.",
|
|
6526
|
+
tone_direction: "high-is-good",
|
|
6527
|
+
values: [
|
|
6528
|
+
{ value: "strong", label: "Strong", description: "Tracks the direct measure closely; a reliable stand-in." },
|
|
6529
|
+
{ value: "moderate", label: "Moderate", description: "Correlates with the direct measure but with meaningful slippage." },
|
|
6530
|
+
{ value: "weak", label: "Weak", description: "Loosely related; use with caution and corroborate." }
|
|
6531
|
+
]
|
|
6532
|
+
},
|
|
6533
|
+
// ── CauseConfidence ─────────────────────────────────────────────────
|
|
6534
|
+
CauseConfidence: {
|
|
6535
|
+
id: "CauseConfidence",
|
|
6536
|
+
label: "Cause confidence",
|
|
6537
|
+
description: "Maturity of a root-cause determination during incident debugging: how far a proposed cause has been validated.",
|
|
6538
|
+
tone_direction: "high-is-good",
|
|
6539
|
+
values: [
|
|
6540
|
+
{ value: "hypothesised", label: "Hypothesised", description: "A proposed cause, not yet tested against evidence." },
|
|
6541
|
+
{ value: "likely", label: "Likely", description: "Supported by evidence but not conclusively proven." },
|
|
6542
|
+
{ value: "confirmed", label: "Confirmed", description: "Verified as the cause; reproduced or otherwise established." }
|
|
6543
|
+
]
|
|
6544
|
+
},
|
|
6545
|
+
// ── ComfortLevel ────────────────────────────────────────────────────
|
|
6546
|
+
ComfortLevel: {
|
|
6547
|
+
id: "ComfortLevel",
|
|
6548
|
+
label: "Comfort level",
|
|
6549
|
+
description: "A person's comfort with a tool, technology, or practice. Closed set so personas compare on the same axis across products.",
|
|
6550
|
+
tone_direction: "high-is-good",
|
|
6551
|
+
values: [
|
|
6552
|
+
{ value: "low", label: "Low", description: "Little or no familiarity; needs guidance to proceed." },
|
|
6553
|
+
{ value: "medium", label: "Medium", description: "Functional, everyday competence." },
|
|
6554
|
+
{ value: "high", label: "High", description: "Confident, fluent use without assistance." },
|
|
6555
|
+
{ value: "expert", label: "Expert", description: "Deep mastery; can teach others or extend the tool." },
|
|
6556
|
+
{ value: "other", label: "Other", description: "A comfort profile not captured by the above tiers." }
|
|
6557
|
+
]
|
|
6558
|
+
},
|
|
6559
|
+
// ── LogLevel ────────────────────────────────────────────────────────
|
|
6560
|
+
LogLevel: {
|
|
6561
|
+
id: "LogLevel",
|
|
6562
|
+
label: "Log level",
|
|
6563
|
+
description: "Operational verbosity of a monitor or alert signal. How loud the signal should be, not how bad an outcome is for the user (kept distinct from severity_5).",
|
|
6564
|
+
tone_direction: "low-is-good",
|
|
6565
|
+
values: [
|
|
6566
|
+
{ value: "critical", label: "Critical", description: "Page immediately; the signal is service-affecting." },
|
|
6567
|
+
{ value: "warning", label: "Warning", description: "Needs attention soon; not yet service-affecting." },
|
|
6568
|
+
{ value: "info", label: "Info", description: "Informational; no action required." }
|
|
6569
|
+
]
|
|
6570
|
+
},
|
|
6571
|
+
// ── IncidentSeverity ────────────────────────────────────────────────
|
|
6572
|
+
IncidentSeverity: {
|
|
6573
|
+
id: "IncidentSeverity",
|
|
6574
|
+
label: "Incident severity",
|
|
6575
|
+
description: "Paging-tier classification of an incident, driving escalation and response process. Distinct from user-impact severity_5 and from LogLevel.",
|
|
6576
|
+
tone_direction: "low-is-good",
|
|
6577
|
+
values: [
|
|
6578
|
+
{ value: "sev1", label: "SEV1", description: "Critical outage; full response, executive-visible." },
|
|
6579
|
+
{ value: "sev2", label: "SEV2", description: "Major degradation; urgent response." },
|
|
6580
|
+
{ value: "sev3", label: "SEV3", description: "Minor or partial impact; handled within hours." },
|
|
6581
|
+
{ value: "sev4", label: "SEV4", description: "Negligible impact; routine handling." }
|
|
6582
|
+
]
|
|
6583
|
+
},
|
|
6584
|
+
// ── SignalSentiment ─────────────────────────────────────────────────
|
|
6585
|
+
SignalSentiment: {
|
|
6586
|
+
id: "SignalSentiment",
|
|
6587
|
+
label: "Signal sentiment",
|
|
6588
|
+
description: "Sentiment polarity of an inbound signal (feedback, support, customer).",
|
|
6589
|
+
tone_direction: "high-is-good",
|
|
6590
|
+
values: [
|
|
6591
|
+
{ value: "positive", label: "Positive", description: "Favourable signal; satisfaction or advocacy." },
|
|
6592
|
+
{ value: "neutral", label: "Neutral", description: "No clear positive or negative lean." },
|
|
6593
|
+
{ value: "negative", label: "Negative", description: "Unfavourable signal; dissatisfaction or risk." },
|
|
6594
|
+
{ value: "mixed", label: "Mixed", description: "Contains both positive and negative elements." }
|
|
6595
|
+
]
|
|
6596
|
+
},
|
|
6597
|
+
// ── MaturityLevel ───────────────────────────────────────────────────
|
|
6598
|
+
MaturityLevel: {
|
|
6599
|
+
id: "MaturityLevel",
|
|
6600
|
+
label: "Maturity level",
|
|
6601
|
+
description: "Capability or process maturity on the CMMI ladder.",
|
|
6602
|
+
tone_direction: "high-is-good",
|
|
6603
|
+
values: [
|
|
6604
|
+
{ value: "initial", label: "Initial", description: "Ad hoc and unpredictable; little process." },
|
|
6605
|
+
{ value: "developing", label: "Developing", description: "Basic process emerging but inconsistent." },
|
|
6606
|
+
{ value: "defined", label: "Defined", description: "Documented, standardised process in place." },
|
|
6607
|
+
{ value: "managed", label: "Managed", description: "Measured and controlled against objectives." },
|
|
6608
|
+
{ value: "optimizing", label: "Optimizing", description: "Continuous, data-driven improvement." }
|
|
6609
|
+
]
|
|
6610
|
+
},
|
|
6611
|
+
// ── ConformanceLevel ────────────────────────────────────────────────
|
|
6612
|
+
ConformanceLevel: {
|
|
6613
|
+
id: "ConformanceLevel",
|
|
6614
|
+
label: "Conformance level",
|
|
6615
|
+
description: "WCAG accessibility conformance level.",
|
|
6616
|
+
tone_direction: "high-is-good",
|
|
6617
|
+
values: [
|
|
6618
|
+
{ value: "A", label: "A", description: "Minimum conformance; essential barriers removed." },
|
|
6619
|
+
{ value: "AA", label: "AA", description: "Addresses the most common barriers; the usual legal target." },
|
|
6620
|
+
{ value: "AAA", label: "AAA", description: "Highest level; not achievable for all content." }
|
|
6621
|
+
]
|
|
6622
|
+
},
|
|
6623
|
+
// ── DataSensitivity ─────────────────────────────────────────────────
|
|
6624
|
+
DataSensitivity: {
|
|
6625
|
+
id: "DataSensitivity",
|
|
6626
|
+
label: "Data sensitivity",
|
|
6627
|
+
description: "Data classification tier governing handling and access.",
|
|
6628
|
+
tone_direction: "neutral",
|
|
6629
|
+
values: [
|
|
6630
|
+
{ value: "public", label: "Public", description: "No restriction; safe to disclose openly." },
|
|
6631
|
+
{ value: "internal", label: "Internal", description: "For internal use; not for external release." },
|
|
6632
|
+
{ value: "confidential", label: "Confidential", description: "Sensitive; restricted to a need-to-know basis." },
|
|
6633
|
+
{ value: "restricted", label: "Restricted", description: "Highly sensitive; strict controls and auditing." }
|
|
6634
|
+
]
|
|
6635
|
+
},
|
|
6636
|
+
// ── DifficultyLevel ─────────────────────────────────────────────────
|
|
6637
|
+
DifficultyLevel: {
|
|
6638
|
+
id: "DifficultyLevel",
|
|
6639
|
+
label: "Difficulty level",
|
|
6640
|
+
description: "Learner difficulty tier for educational content.",
|
|
6641
|
+
tone_direction: "neutral",
|
|
6642
|
+
values: [
|
|
6643
|
+
{ value: "beginner", label: "Beginner", description: "No prior knowledge assumed." },
|
|
6644
|
+
{ value: "intermediate", label: "Intermediate", description: "Assumes working familiarity with the basics." },
|
|
6645
|
+
{ value: "advanced", label: "Advanced", description: "Assumes deep, expert-level background." }
|
|
6646
|
+
]
|
|
6647
|
+
},
|
|
6648
|
+
// ── FrequencyRating ─────────────────────────────────────────────────
|
|
6649
|
+
FrequencyRating: {
|
|
6650
|
+
id: "FrequencyRating",
|
|
6651
|
+
label: "Frequency rating",
|
|
6652
|
+
description: "Qualitative how-often rating. Distinct from the numeric frequency_5 scale and from Cadence calendar tiers.",
|
|
6653
|
+
tone_direction: "neutral",
|
|
6654
|
+
values: [
|
|
6655
|
+
{ value: "constant", label: "Constant", description: "Effectively always; continuous occurrence." },
|
|
6656
|
+
{ value: "regular", label: "Regular", description: "Happens on a predictable, recurring basis." },
|
|
6657
|
+
{ value: "occasional", label: "Occasional", description: "Happens sometimes, without a fixed pattern." },
|
|
6658
|
+
{ value: "rare", label: "Rare", description: "Happens infrequently." },
|
|
6659
|
+
{ value: "other", label: "Other", description: "A frequency not captured by the above tiers." }
|
|
6660
|
+
]
|
|
6661
|
+
},
|
|
6662
|
+
// ── EvidenceDirection ───────────────────────────────────────────────
|
|
6663
|
+
EvidenceDirection: {
|
|
6664
|
+
id: "EvidenceDirection",
|
|
6665
|
+
label: "Evidence direction",
|
|
6666
|
+
description: "Direction of evidence relative to a claim. Distinct from confidence_impact (strengthens/weakens) per the UPG-579 polysemy verdicts.",
|
|
6667
|
+
tone_direction: "neutral",
|
|
6668
|
+
values: [
|
|
6669
|
+
{ value: "supports", label: "Supports", description: "The evidence backs the claim." },
|
|
6670
|
+
{ value: "refutes", label: "Refutes", description: "The evidence contradicts the claim." },
|
|
6671
|
+
{ value: "neutral", label: "Neutral", description: "The evidence is inconclusive either way." }
|
|
6672
|
+
]
|
|
6470
6673
|
}
|
|
6471
6674
|
};
|
|
6472
6675
|
function getEnumScale(name) {
|
|
@@ -6813,6 +7016,41 @@ function getDeprecatedTypes() {
|
|
|
6813
7016
|
return deprecated;
|
|
6814
7017
|
}
|
|
6815
7018
|
var UPG_PROPERTY_MIGRATIONS = {
|
|
7019
|
+
// ── v0.8.0: UPG-574 deprecated-property removal pass ───────────────────
|
|
7020
|
+
//
|
|
7021
|
+
// The seven properties tagged `@deprecated since v0.4.0` that survived the
|
|
7022
|
+
// v0.5.0 hygiene pass are removed from the spec in v0.8.0 (a breaking
|
|
7023
|
+
// release). Five of the seven already carry a migration:
|
|
7024
|
+
// - `task.task_status` / `bug.bug_status` lift to `UPGBaseNode.status`
|
|
7025
|
+
// (see `UPG_PROPERTY_MIGRATIONS['0.4.0']`, values identical).
|
|
7026
|
+
// - `learning.metric` drops in favour of the `learning_observed_on_metric`
|
|
7027
|
+
// edge (see `UPG_PROPERTY_MIGRATIONS['0.5.0']`).
|
|
7028
|
+
// The two remaining property surfaces are migrated here:
|
|
7029
|
+
// - `evidence.strength` (simple `strong | moderate | weak` enum) is
|
|
7030
|
+
// dropped in favour of `weight: UPGAssessment` (scale `weight_5pt`).
|
|
7031
|
+
// Authors carrying the legacy key should copy the value to `weight`
|
|
7032
|
+
// before applying this migration: `strong → 5`, `moderate → 3`,
|
|
7033
|
+
// `weak → 1`, with the old word preserved in `weight.label`.
|
|
7034
|
+
// - `story_task.estimate` / `.effort` / `.priority` drop. `story_task`
|
|
7035
|
+
// itself is deprecated (`UPG_MIGRATIONS['0.4.0']` renames it to the
|
|
7036
|
+
// canonical `task`); the type rename copies every property verbatim,
|
|
7037
|
+
// so the values survive on `task` (`TaskProperties.estimate` /
|
|
7038
|
+
// `.effort` / `.priority`, all live). This rule removes the residue
|
|
7039
|
+
// from any node still typed `story_task` at migration time.
|
|
7040
|
+
"0.8.0": [
|
|
7041
|
+
{
|
|
7042
|
+
kind: "drop_props",
|
|
7043
|
+
type: "evidence",
|
|
7044
|
+
drop_props: ["strength"],
|
|
7045
|
+
reason: "UPG-574 (v0.8.0). evidence.strength was `@deprecated since v0.4.0`; the structured `weight: UPGAssessment` (scale `weight_5pt`) replaces the `strong | moderate | weak` enum to align with the spec-wide scoring pattern. Authors should copy the value to `weight` before applying this migration (strong -> 5, moderate -> 3, weak -> 1; carry the old word in `weight.label`). The migration drops the residue."
|
|
7046
|
+
},
|
|
7047
|
+
{
|
|
7048
|
+
kind: "drop_props",
|
|
7049
|
+
type: "story_task",
|
|
7050
|
+
drop_props: ["estimate", "effort", "priority"],
|
|
7051
|
+
reason: 'UPG-574 (v0.8.0). story_task.estimate / .effort / .priority were `@deprecated since v0.4.0`; story_task itself is deprecated (UPG_MIGRATIONS["0.4.0"] renames it to canonical `task`, copying all properties verbatim), so the values survive on TaskProperties.estimate / .effort / .priority (all live). This rule removes the residue from any node still typed `story_task` at migration time.'
|
|
7052
|
+
}
|
|
7053
|
+
],
|
|
6816
7054
|
// ── v0.5.0: UPG-509 deprecation hygiene pass ───────────────────────────
|
|
6817
7055
|
//
|
|
6818
7056
|
// Properties tagged `@deprecated since="0.4.0" removeIn="0.5.0"` (and the
|
|
@@ -8616,7 +8854,18 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
8616
8854
|
},
|
|
8617
8855
|
// A11yIssueProperties: Accessibility issue.
|
|
8618
8856
|
a11y_issue: {
|
|
8619
|
-
severity: {
|
|
8857
|
+
severity: {
|
|
8858
|
+
type: "assessment",
|
|
8859
|
+
scale_id: "severity_5",
|
|
8860
|
+
description: "Impact severity (UPGAssessment on the `severity_5` scale). Migrated from the inline axe-core 4-level enum (`minor|moderate|serious|critical`) (UPG-579 Option C): map `critical` -> 5, `serious` -> 4, `moderate` -> 3, `minor` -> 2; carry the old word in `label`.",
|
|
8861
|
+
properties: {
|
|
8862
|
+
value: { type: "number", description: "The numeric value, used for computation." },
|
|
8863
|
+
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
8864
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
8865
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
8866
|
+
},
|
|
8867
|
+
required: ["value", "label"]
|
|
8868
|
+
},
|
|
8620
8869
|
wcag_criterion: { type: "string", description: 'WCAG success criterion violated (e.g. "1.1.1", "2.4.7")' },
|
|
8621
8870
|
rule_id: { type: "string", description: "Identifier of the rule that flagged the issue" },
|
|
8622
8871
|
help_url: { type: "string", description: "URL to documentation explaining the issue and how to fix it" },
|
|
@@ -8673,7 +8922,18 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
8673
8922
|
affinity_cluster: {
|
|
8674
8923
|
theme: { type: "string", description: "Emergent theme label" },
|
|
8675
8924
|
child_observation_count: { type: "number", description: "Observations in this cluster" },
|
|
8676
|
-
confidence: {
|
|
8925
|
+
confidence: {
|
|
8926
|
+
type: "assessment",
|
|
8927
|
+
scale_id: "confidence_5",
|
|
8928
|
+
description: "Confidence in the theme's validity (UPGAssessment on `confidence_5`).",
|
|
8929
|
+
properties: {
|
|
8930
|
+
value: { type: "number", description: "The numeric value, used for computation." },
|
|
8931
|
+
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
8932
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
8933
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
8934
|
+
},
|
|
8935
|
+
required: ["value", "label"]
|
|
8936
|
+
}
|
|
8677
8937
|
},
|
|
8678
8938
|
// AgentDefinitionProperties: Agent definition.
|
|
8679
8939
|
agent_definition: {
|
|
@@ -8807,7 +9067,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
8807
9067
|
// AlertRuleProperties: Alert rule.
|
|
8808
9068
|
alert_rule: {
|
|
8809
9069
|
condition: { type: "string", description: 'Triggering query or expression. @example "avg(rate(http_errors_total[5m])) > 0.05"' },
|
|
8810
|
-
severity: { type: "string", enum: ["critical", "warning", "info"], description: "Routes notification and escalation. `critical` = page immediately. `warning` = notify, don't page. `info` = log only." },
|
|
9070
|
+
severity: { type: "string", enum: ["critical", "warning", "info"], description: "Routes notification and escalation. Uses the `LogLevel` scale (operational verbosity, distinct from user-impact `severity_5`). `critical` = page immediately. `warning` = notify, don't page. `info` = log only." },
|
|
8811
9071
|
notification_channel: { type: "string", description: 'Notification destination. @example "pagerduty:sev1-rotation", "slack:#alerts-low"' },
|
|
8812
9072
|
evaluation_window: { type: "string", description: 'Required duration the condition holds before firing. Prevents flapping on transient spikes. @example "5m", "15m", "1h"' },
|
|
8813
9073
|
escalation_policy: { type: "string", description: 'Escalation behaviour on unacknowledged alerts. @example "Escalate to engineering lead after 10 minutes"' }
|
|
@@ -8846,16 +9106,28 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
8846
9106
|
},
|
|
8847
9107
|
// AssumptionProperties: Assumption entity.
|
|
8848
9108
|
assumption: {
|
|
8849
|
-
confidence: {
|
|
9109
|
+
confidence: {
|
|
9110
|
+
type: "assessment",
|
|
9111
|
+
scale_id: "confidence_5",
|
|
9112
|
+
description: "Confidence before testing (UPGAssessment on `confidence_5`). Independent of whether the assumption is validated (tracked in lifecycle).",
|
|
9113
|
+
properties: {
|
|
9114
|
+
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9115
|
+
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9116
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
9117
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9118
|
+
},
|
|
9119
|
+
required: ["value", "label"]
|
|
9120
|
+
},
|
|
8850
9121
|
validation_method: { type: "string", description: "Validation method, planned or used" },
|
|
8851
9122
|
risk_level: {
|
|
8852
|
-
type: "
|
|
9123
|
+
type: "assessment",
|
|
9124
|
+
scale_id: "severity_5",
|
|
8853
9125
|
description: "Exposure if the assumption turns out wrong",
|
|
8854
9126
|
properties: {
|
|
8855
9127
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
8856
9128
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
8857
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
8858
|
-
normalized: { type: "number", description: "Normalized 0
|
|
9129
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
9130
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
8859
9131
|
},
|
|
8860
9132
|
required: ["value", "label"]
|
|
8861
9133
|
},
|
|
@@ -8966,8 +9238,18 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
8966
9238
|
},
|
|
8967
9239
|
// BugProperties: Bug report.
|
|
8968
9240
|
bug: {
|
|
8969
|
-
bug_severity: {
|
|
8970
|
-
|
|
9241
|
+
bug_severity: {
|
|
9242
|
+
type: "assessment",
|
|
9243
|
+
scale_id: "severity_5",
|
|
9244
|
+
description: "Impact severity (UPGAssessment on the `severity_5` scale). Independent of priority (which governs when it gets fixed). Migrated from the inline `critical|major|minor|trivial` enum (UPG-579 Option C): map `critical` -> 5, `major` -> 4, `minor` -> 2, `trivial` -> 1; carry the old word in `label`.",
|
|
9245
|
+
properties: {
|
|
9246
|
+
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9247
|
+
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9248
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
9249
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9250
|
+
},
|
|
9251
|
+
required: ["value", "label"]
|
|
9252
|
+
},
|
|
8971
9253
|
steps_to_reproduce: { type: "string", description: "Step-by-step reproduction" },
|
|
8972
9254
|
environment: { type: "string", description: 'Observed environment (e.g. "prod", "staging", "iOS 17.4")' },
|
|
8973
9255
|
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)." },
|
|
@@ -8997,7 +9279,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
8997
9279
|
maturity_level: { type: "string", enum: ["initial", "developing", "defined", "managed", "optimizing"], description: "Current maturity" },
|
|
8998
9280
|
target_maturity: { type: "string", enum: ["initial", "developing", "defined", "managed", "optimizing"], description: "Target maturity" },
|
|
8999
9281
|
gap: { type: "string", description: "Gap between current and target" },
|
|
9000
|
-
evolution_stage: { type: "string", enum: ["genesis", "custom", "product", "commodity"], description:
|
|
9282
|
+
evolution_stage: { type: "string", enum: ["genesis", "custom", "product", "commodity"], description: "Wardley evolution axis: where this capability sits on the genesis \u2192 custom \u2192 product \u2192 commodity spectrum. Used by frameworks like `wardley-map`; generally useful as a maturity-of-the-domain signal independent of `maturity_level` (which measures the team's internal capability practice). @example 'product'" },
|
|
9001
9283
|
visibility: { type: "number", description: "Position on the visibility axis from `0.0` (deepest dependency, infra the user never sees) to `1.0` (user-visible anchor). Used by `wardley-map` for the y-axis position of each capability in the value chain. @example 0.8" }
|
|
9002
9284
|
},
|
|
9003
9285
|
// CapacityPlanProperties: CapacityPlan entity.
|
|
@@ -9010,7 +9292,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9010
9292
|
// CeremonyProperties: Ceremony entity.
|
|
9011
9293
|
ceremony: {
|
|
9012
9294
|
ceremony_type: { type: "string", enum: ["standup", "planning", "review", "retro", "sync", "demo", "other"], description: "Kind of recurring meeting" },
|
|
9013
|
-
cadence: { type: "string", description:
|
|
9295
|
+
cadence: { type: "string", enum: ["continuous", "hourly", "daily", "weekly", "monthly", "quarterly", "yearly", "on_demand", "other"], description: "How often the ceremony occurs. Uses the shared `Cadence` scale." },
|
|
9014
9296
|
duration_minutes: { type: "number", description: "Typical duration of the meeting in minutes" },
|
|
9015
9297
|
participants: { type: "string", description: "People or roles who attend" }
|
|
9016
9298
|
},
|
|
@@ -9039,9 +9321,9 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9039
9321
|
category: { type: "string", description: "High-level category of the churn reason" },
|
|
9040
9322
|
frequency_count: { type: "number", description: "Exact count of times this reason has been cited in `frequency_period`" },
|
|
9041
9323
|
frequency_period: { type: "string", description: "The recurrence period the count is measured over (ISO-8601 `Duration`, e.g. `'P30D'`)" },
|
|
9042
|
-
frequency_rating: { type: "string", enum: ["
|
|
9324
|
+
frequency_rating: { type: "string", enum: ["constant", "regular", "occasional", "rare", "other"], description: "Qualitative frequency tier when an exact count is not known" },
|
|
9043
9325
|
contributing_factors: { type: "string[]", description: "Other factors that contributed to the churn" },
|
|
9044
|
-
signal_sentiment: { type: "string", enum: ["positive", "
|
|
9326
|
+
signal_sentiment: { type: "string", enum: ["positive", "neutral", "negative", "mixed"], description: "Detected sentiment of the churn signal" },
|
|
9045
9327
|
signal_channel: { type: "string", description: "Channel through which the churn signal was received" },
|
|
9046
9328
|
signal_urgency: { type: "string", enum: ["low", "medium", "high", "critical"], description: "Urgency of the churn risk" }
|
|
9047
9329
|
},
|
|
@@ -9155,7 +9437,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9155
9437
|
publish_cadence: { type: "string", enum: ["continuous", "hourly", "daily", "weekly", "monthly", "quarterly", "yearly", "on_demand", "other"], description: "Publishing cadence (canonical `Cadence` since v0.4.0). Retyped from the legacy free-form `publish_cadence: string`. For exact rates (\"3 per week\"), set `frequency_count` + `frequency_period`. BREAKING in v0.4.0: previous string values like `\"3x/week\"` no longer type-check. Map to `'weekly'` + `frequency_count: 3` + `frequency_period: 'P7D'`." },
|
|
9156
9438
|
frequency_count: { type: "number", description: "Exact count in the period. Pairs with `frequency_period`." },
|
|
9157
9439
|
frequency_period: { type: "string", description: "Recurrence period (ISO-8601 `Duration`, e.g. `'P7D'`)" },
|
|
9158
|
-
frequency_rating: { type: "string", enum: ["
|
|
9440
|
+
frequency_rating: { type: "string", enum: ["constant", "regular", "occasional", "rare", "other"], description: "Qualitative rate tier when an exact rate is unknown" }
|
|
9159
9441
|
},
|
|
9160
9442
|
// ContentPieceProperties: Content piece.
|
|
9161
9443
|
content_piece: {
|
|
@@ -9170,7 +9452,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9170
9452
|
cadence: { type: "string", enum: ["continuous", "hourly", "daily", "weekly", "monthly", "quarterly", "yearly", "on_demand", "other"], description: "Publishing cadence (canonical `Cadence` since v0.4.0). Retyped from the legacy free-form `cadence: string` (e.g. \"2x/week\"). For exact rates, set `frequency_count` + `frequency_period`. BREAKING in v0.4.0: previous string values like `\"2x/week\"` no longer type-check. Map to `'weekly'` + `frequency_count: 2` + `frequency_period: 'P7D'`." },
|
|
9171
9453
|
frequency_count: { type: "number", description: "Exact count of publications in the period. Pairs with `frequency_period`." },
|
|
9172
9454
|
frequency_period: { type: "string", description: "Recurrence period (ISO-8601 `Duration`, e.g. `'P7D'`)" },
|
|
9173
|
-
frequency_rating: { type: "string", enum: ["
|
|
9455
|
+
frequency_rating: { type: "string", enum: ["constant", "regular", "occasional", "rare", "other"], description: "Qualitative rate tier when an exact rate is unknown" }
|
|
9174
9456
|
},
|
|
9175
9457
|
// ContentThemeProperties: Content theme.
|
|
9176
9458
|
content_theme: {
|
|
@@ -9195,13 +9477,14 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9195
9477
|
clause_text: { type: "string", description: "Full text of the clause" },
|
|
9196
9478
|
is_negotiable: { type: "boolean", description: "Whether this clause is open to negotiation" },
|
|
9197
9479
|
risk_level: {
|
|
9198
|
-
type: "
|
|
9480
|
+
type: "assessment",
|
|
9481
|
+
scale_id: "severity_5",
|
|
9199
9482
|
description: "Risk level if the clause is accepted as-is (1 = negligible, 5 = severe exposure)",
|
|
9200
9483
|
properties: {
|
|
9201
9484
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9202
9485
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9203
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9204
|
-
normalized: { type: "number", description: "Normalized 0
|
|
9486
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
9487
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9205
9488
|
},
|
|
9206
9489
|
required: ["value", "label"]
|
|
9207
9490
|
}
|
|
@@ -9220,9 +9503,9 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9220
9503
|
// CustomerFeedbackProperties: Customer feedback.
|
|
9221
9504
|
customer_feedback: {
|
|
9222
9505
|
feedback_type: { type: "string", enum: ["survey", "interview", "review", "nps"], description: "How the feedback was collected" },
|
|
9223
|
-
sentiment: { type: "string", enum: ["positive", "neutral", "negative"], description: "Overall sentiment of the feedback" },
|
|
9506
|
+
sentiment: { type: "string", enum: ["positive", "neutral", "negative", "mixed"], description: "Overall sentiment of the feedback" },
|
|
9224
9507
|
verbatim: { type: "string", description: "Exact words from the customer" },
|
|
9225
|
-
signal_sentiment: { type: "string", enum: ["positive", "
|
|
9508
|
+
signal_sentiment: { type: "string", enum: ["positive", "neutral", "negative", "mixed"], description: "Detected sentiment of the underlying signal" },
|
|
9226
9509
|
signal_channel: { type: "string", description: "Channel through which the signal was received" },
|
|
9227
9510
|
signal_urgency: { type: "string", enum: ["low", "medium", "high", "critical"], description: "Perceived urgency of the feedback" }
|
|
9228
9511
|
},
|
|
@@ -9251,7 +9534,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9251
9534
|
url: { type: "string", description: "URL to the live dashboard" },
|
|
9252
9535
|
audience: { type: "string", description: "Intended audience for this dashboard" },
|
|
9253
9536
|
element_count: { type: "number", description: "Number of widgets or panels on the dashboard" },
|
|
9254
|
-
refresh_cadence: { type: "string", description: "How often the dashboard data refreshes" },
|
|
9537
|
+
refresh_cadence: { type: "string", enum: ["continuous", "hourly", "daily", "weekly", "monthly", "quarterly", "yearly", "on_demand", "other"], description: "How often the dashboard data refreshes. Uses the shared `Cadence` scale." },
|
|
9255
9538
|
filter_count: { type: "number", description: "Number of user-configurable filters" }
|
|
9256
9539
|
},
|
|
9257
9540
|
// DataClassificationProperties: Data classification.
|
|
@@ -9311,7 +9594,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9311
9594
|
},
|
|
9312
9595
|
// DataProductProperties: DataProduct entity.
|
|
9313
9596
|
data_product: {
|
|
9314
|
-
data_product_type: { type: "string", description:
|
|
9597
|
+
data_product_type: { type: "string", enum: ["report", "dataset", "stream", "api", "ml_feature", "other"], description: "Classification of the data product (UPG-579 Option B)." },
|
|
9315
9598
|
sla_freshness: { type: "string", description: 'Freshness SLA commitment (e.g. "< 1 hour")' }
|
|
9316
9599
|
},
|
|
9317
9600
|
// DataQualityRuleProperties: DataQualityRule entity.
|
|
@@ -9328,7 +9611,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9328
9611
|
data_source: {
|
|
9329
9612
|
source_type: { type: "string", enum: ["database", "api", "event_stream", "warehouse"], description: "Kind of data source" },
|
|
9330
9613
|
connection_status: { type: "string", enum: ["connected", "disconnected", "error"], description: "Current connection health" },
|
|
9331
|
-
refresh_cadence: { type: "string", description:
|
|
9614
|
+
refresh_cadence: { type: "string", enum: ["continuous", "hourly", "daily", "weekly", "monthly", "quarterly", "yearly", "on_demand", "other"], description: "How often the data is refreshed. Uses the shared `Cadence` scale." }
|
|
9332
9615
|
},
|
|
9333
9616
|
// DatabaseSchemaProperties: Database schema.
|
|
9334
9617
|
database_schema: {
|
|
@@ -9359,7 +9642,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9359
9642
|
},
|
|
9360
9643
|
// DeliverableProperties: Deliverable.
|
|
9361
9644
|
deliverable: {
|
|
9362
|
-
deliverable_type: { type: "string",
|
|
9645
|
+
deliverable_type: { type: "string", enum: ["document", "prototype", "release", "design", "report", "other"], description: "Kind of deliverable (UPG-579 Option B)." },
|
|
9363
9646
|
due_date: { type: "string", description: "Due date for the deliverable (ISO format)" },
|
|
9364
9647
|
deliverable_status: { type: "string", enum: ["not_started", "in_progress", "in_review", "accepted", "rejected"], description: "Current progress status" },
|
|
9365
9648
|
acceptance_criteria: { type: "string", description: "Criteria that must be met for the deliverable to be accepted" }
|
|
@@ -9437,7 +9720,18 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9437
9720
|
target_domain: { type: "string", enum: ["ux", "visual", "interaction", "content", "accessibility", "other"], description: "Target design discipline" },
|
|
9438
9721
|
framing: { type: "string", enum: ["how_might_we", "what_if", "why_do", "how_do", "what_prevents", "other"], description: "Question framing template" },
|
|
9439
9722
|
priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Importance against other backlog questions" },
|
|
9440
|
-
confidence: {
|
|
9723
|
+
confidence: {
|
|
9724
|
+
type: "assessment",
|
|
9725
|
+
scale_id: "confidence_5",
|
|
9726
|
+
description: "Confidence the question is well-framed (UPGAssessment on `confidence_5`). Distinct from confidence in any answer.",
|
|
9727
|
+
properties: {
|
|
9728
|
+
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9729
|
+
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9730
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
9731
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9732
|
+
},
|
|
9733
|
+
required: ["value", "label"]
|
|
9734
|
+
},
|
|
9441
9735
|
assumptions: { type: "string[]", description: "Underlying assumptions. Surfaced explicitly so they can be challenged or validated." },
|
|
9442
9736
|
validation_method: { type: "string", enum: ["interview", "survey", "usability_test", "analytics", "a_b_test", "prototype_test", "literature_review", "other"], description: "Primary validation method" }
|
|
9443
9737
|
},
|
|
@@ -9464,24 +9758,26 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9464
9758
|
desired_outcome: {
|
|
9465
9759
|
statement: { type: "string", description: "Outcome statement in the user's words" },
|
|
9466
9760
|
importance: {
|
|
9467
|
-
type: "
|
|
9761
|
+
type: "assessment",
|
|
9762
|
+
scale_id: "importance_5",
|
|
9468
9763
|
description: "How important this outcome is to the user (1 = low, 5 = critical)",
|
|
9469
9764
|
properties: {
|
|
9470
9765
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9471
9766
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9472
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9473
|
-
normalized: { type: "number", description: "Normalized 0
|
|
9767
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
9768
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9474
9769
|
},
|
|
9475
9770
|
required: ["value", "label"]
|
|
9476
9771
|
},
|
|
9477
9772
|
current_satisfaction: {
|
|
9478
|
-
type: "
|
|
9773
|
+
type: "assessment",
|
|
9774
|
+
scale_id: "satisfaction_5",
|
|
9479
9775
|
description: "How satisfied the user currently is with this outcome (1 = very unsatisfied, 5 = fully satisfied)",
|
|
9480
9776
|
properties: {
|
|
9481
9777
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9482
9778
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9483
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9484
|
-
normalized: { type: "number", description: "Normalized 0
|
|
9779
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
9780
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9485
9781
|
},
|
|
9486
9782
|
required: ["value", "label"]
|
|
9487
9783
|
}
|
|
@@ -9599,20 +9895,20 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9599
9895
|
evidence_source: { type: "string", enum: ["experiment_run", "observation", "quote", "metric_change", "market_data", "interview"], description: "Origin type. Drives renderer + filter UI; the provenance edge (`derived_from_*`) carries the actual source node reference." },
|
|
9600
9896
|
direction: { type: "string", enum: ["supports", "refutes", "neutral"], description: "Direction relative to the parent hypothesis." },
|
|
9601
9897
|
weight: {
|
|
9602
|
-
type: "
|
|
9603
|
-
|
|
9898
|
+
type: "assessment",
|
|
9899
|
+
scale_id: "importance_5",
|
|
9900
|
+
description: "Strength (UPGAssessment, scale `scale_5`).",
|
|
9604
9901
|
properties: {
|
|
9605
9902
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9606
9903
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9607
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9608
|
-
normalized: { type: "number", description: "Normalized 0
|
|
9904
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
9905
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9609
9906
|
},
|
|
9610
9907
|
required: ["value", "label"]
|
|
9611
9908
|
},
|
|
9612
9909
|
summary: { type: "string", description: "Plain-English summary." },
|
|
9613
9910
|
observed_at: { type: "string", description: "ISO date observed." },
|
|
9614
|
-
source: { type: "string", description: "Free-text provenance note" }
|
|
9615
|
-
strength: { type: "string", enum: ["strong", "moderate", "weak"], description: "@deprecated since v0.4.0. Use `weight: UPGAssessment`. Simple enum replaced by structured assessment to align with UPG scoring patterns." }
|
|
9911
|
+
source: { type: "string", description: "Free-text provenance note" }
|
|
9616
9912
|
},
|
|
9617
9913
|
// ExperimentProperties: A structured activity designed to test a hypothesis.
|
|
9618
9914
|
experiment: {
|
|
@@ -9629,46 +9925,50 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9629
9925
|
method: { type: "string", enum: ["a_b_test", "multivariate", "qual_interview", "prototype_test", "fake_door", "wizard_of_oz", "longitudinal"], description: "Experimental method. Drives renderer and analysis tooling." },
|
|
9630
9926
|
success_criteria: { type: "string", description: 'Plain-English description of "passing"' },
|
|
9631
9927
|
projected_reach: {
|
|
9632
|
-
type: "
|
|
9928
|
+
type: "assessment",
|
|
9929
|
+
scale_id: "reach_5",
|
|
9633
9930
|
description: "Projected reach: how many people the run is expected to touch (UPGAssessment)",
|
|
9634
9931
|
properties: {
|
|
9635
9932
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9636
9933
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9637
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9638
|
-
normalized: { type: "number", description: "Normalized 0
|
|
9934
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
9935
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9639
9936
|
},
|
|
9640
9937
|
required: ["value", "label"]
|
|
9641
9938
|
},
|
|
9642
9939
|
projected_impact: {
|
|
9643
|
-
type: "
|
|
9940
|
+
type: "assessment",
|
|
9941
|
+
scale_id: "impact_5",
|
|
9644
9942
|
description: "Projected impact on the target metric (UPGAssessment)",
|
|
9645
9943
|
properties: {
|
|
9646
9944
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9647
9945
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9648
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9649
|
-
normalized: { type: "number", description: "Normalized 0
|
|
9946
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
9947
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9650
9948
|
},
|
|
9651
9949
|
required: ["value", "label"]
|
|
9652
9950
|
},
|
|
9653
9951
|
confidence: {
|
|
9654
|
-
type: "
|
|
9655
|
-
|
|
9952
|
+
type: "assessment",
|
|
9953
|
+
scale_id: "confidence_5",
|
|
9954
|
+
description: "Team confidence at plan-time (UPGAssessment, scale `confidence_5`)",
|
|
9656
9955
|
properties: {
|
|
9657
9956
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9658
9957
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9659
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9660
|
-
normalized: { type: "number", description: "Normalized 0
|
|
9958
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
9959
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9661
9960
|
},
|
|
9662
9961
|
required: ["value", "label"]
|
|
9663
9962
|
},
|
|
9664
9963
|
cost_estimate: {
|
|
9665
|
-
type: "
|
|
9964
|
+
type: "assessment",
|
|
9965
|
+
scale_id: "effort_5",
|
|
9666
9966
|
description: "Cost estimate at plan-time (UPGAssessment)",
|
|
9667
9967
|
properties: {
|
|
9668
9968
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9669
9969
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9670
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9671
|
-
normalized: { type: "number", description: "Normalized 0
|
|
9970
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
9971
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9672
9972
|
},
|
|
9673
9973
|
required: ["value", "label"]
|
|
9674
9974
|
},
|
|
@@ -9682,13 +9982,14 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9682
9982
|
actual_reach: { type: "number", description: "Observed reach: how many people the run actually touched" },
|
|
9683
9983
|
outcome_summary: { type: "string", description: "Plain-English outcome" },
|
|
9684
9984
|
severity_of_finding: {
|
|
9685
|
-
type: "
|
|
9985
|
+
type: "assessment",
|
|
9986
|
+
scale_id: "severity_5",
|
|
9686
9987
|
description: "Severity / strength of the finding (UPGAssessment)",
|
|
9687
9988
|
properties: {
|
|
9688
9989
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9689
9990
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9690
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9691
|
-
normalized: { type: "number", description: "Normalized 0
|
|
9991
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
9992
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9692
9993
|
},
|
|
9693
9994
|
required: ["value", "label"]
|
|
9694
9995
|
},
|
|
@@ -9707,7 +10008,18 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9707
10008
|
feasibility_study: {
|
|
9708
10009
|
study_type: { type: "string", enum: ["technical", "business", "market", "resource"], description: 'Type of feasibility being assessed. @example "technical" for assessing engineering viability' },
|
|
9709
10010
|
conclusion: { type: "string", enum: ["feasible", "not_feasible", "conditional", "needs_more_data"], description: "Outcome conclusion of the study" },
|
|
9710
|
-
confidence: {
|
|
10011
|
+
confidence: {
|
|
10012
|
+
type: "assessment",
|
|
10013
|
+
scale_id: "confidence_5",
|
|
10014
|
+
description: "Confidence in the conclusion (UPGAssessment on `confidence_5`).",
|
|
10015
|
+
properties: {
|
|
10016
|
+
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10017
|
+
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10018
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10019
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10020
|
+
},
|
|
10021
|
+
required: ["value", "label"]
|
|
10022
|
+
}
|
|
9711
10023
|
},
|
|
9712
10024
|
// FeatureProperties: A discrete, user-facing capability of the product.
|
|
9713
10025
|
feature: {
|
|
@@ -9742,28 +10054,30 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9742
10054
|
feature_request: {
|
|
9743
10055
|
request_source: { type: "string", enum: ["customer", "internal", "prospect", "support", "community"], description: "Where the request originated" },
|
|
9744
10056
|
vote_count: { type: "number", description: "Number of votes or upvotes from users" },
|
|
9745
|
-
signal_sentiment: { type: "string", enum: ["positive", "
|
|
10057
|
+
signal_sentiment: { type: "string", enum: ["positive", "neutral", "negative", "mixed"], description: "Detected sentiment of the request" },
|
|
9746
10058
|
signal_channel: { type: "string", description: "Channel through which the request was received" },
|
|
9747
10059
|
signal_urgency: { type: "string", enum: ["low", "medium", "high", "critical"], description: "Perceived urgency of the request" },
|
|
9748
10060
|
revenue_impact: {
|
|
9749
|
-
type: "
|
|
10061
|
+
type: "assessment",
|
|
10062
|
+
scale_id: "impact_5",
|
|
9750
10063
|
description: "Estimated revenue impact if implemented (1-5)",
|
|
9751
10064
|
properties: {
|
|
9752
10065
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9753
10066
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9754
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9755
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10067
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10068
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9756
10069
|
},
|
|
9757
10070
|
required: ["value", "label"]
|
|
9758
10071
|
},
|
|
9759
10072
|
effort_estimate: {
|
|
9760
|
-
type: "
|
|
10073
|
+
type: "assessment",
|
|
10074
|
+
scale_id: "effort_5",
|
|
9761
10075
|
description: "Estimated implementation effort (1-5)",
|
|
9762
10076
|
properties: {
|
|
9763
10077
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9764
10078
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9765
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9766
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10079
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10080
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9767
10081
|
},
|
|
9768
10082
|
required: ["value", "label"]
|
|
9769
10083
|
},
|
|
@@ -9780,13 +10094,14 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9780
10094
|
sentiment: { type: "string", enum: ["positive", "neutral", "negative", "mixed"], description: "Overall sentiment across mentions" },
|
|
9781
10095
|
actionable: { type: "boolean", description: "Whether this theme can be acted upon" },
|
|
9782
10096
|
frequency: {
|
|
9783
|
-
type: "
|
|
10097
|
+
type: "assessment",
|
|
10098
|
+
scale_id: "frequency_5",
|
|
9784
10099
|
description: "How often the theme is mentioned (1-5)",
|
|
9785
10100
|
properties: {
|
|
9786
10101
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9787
10102
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9788
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9789
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10103
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10104
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9790
10105
|
},
|
|
9791
10106
|
required: ["value", "label"]
|
|
9792
10107
|
},
|
|
@@ -9804,7 +10119,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9804
10119
|
fix_type: { type: "string", enum: ["hotfix", "permanent", "workaround", "configuration", "process_change"], description: "Kind of fix. `hotfix` = urgent patch. `permanent` = proper structural fix. `workaround` = mitigates symptom without addressing root cause; should track a follow-up." },
|
|
9805
10120
|
commit: { type: "string", description: "Git commit SHA" },
|
|
9806
10121
|
files_changed: { type: "string[]", description: "Files changed" },
|
|
9807
|
-
deployed_at: { type: "string", description: "ISO timestamp landed in the target environment.
|
|
10122
|
+
deployed_at: { type: "string", description: "ISO timestamp landed in the target environment." },
|
|
9808
10123
|
fixed_date: { type: "string", description: "Application date (ISO date). Coarser-grained complement to `deployed_at`." },
|
|
9809
10124
|
verified: { type: "boolean", description: "Verified in production" },
|
|
9810
10125
|
verified_by_test: { type: "boolean", description: "Validated by an automated regression or integration test. Distinct from `verified` (human judgment)." }
|
|
@@ -9814,13 +10129,14 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9814
10129
|
forecast_period: { type: "string", description: 'Time period the forecast covers (e.g. "Q2 2026")' },
|
|
9815
10130
|
predicted_revenue: { type: "number", description: "Predicted revenue amount" },
|
|
9816
10131
|
confidence: {
|
|
9817
|
-
type: "
|
|
10132
|
+
type: "assessment",
|
|
10133
|
+
scale_id: "confidence_5",
|
|
9818
10134
|
description: "Confidence in the prediction (1 = speculative, 5 = high conviction)",
|
|
9819
10135
|
properties: {
|
|
9820
10136
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9821
10137
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9822
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9823
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10138
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10139
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9824
10140
|
},
|
|
9825
10141
|
required: ["value", "label"]
|
|
9826
10142
|
},
|
|
@@ -9872,13 +10188,14 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9872
10188
|
hallucination_report: {
|
|
9873
10189
|
report_type: { type: "string", enum: ["factual", "logical", "fabrication", "inconsistency"], description: "Classification" },
|
|
9874
10190
|
severity: {
|
|
9875
|
-
type: "
|
|
10191
|
+
type: "assessment",
|
|
10192
|
+
scale_id: "severity_5",
|
|
9876
10193
|
description: "Impact severity (1 = trivial, 5 = dangerous misinformation)",
|
|
9877
10194
|
properties: {
|
|
9878
10195
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9879
10196
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9880
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9881
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10197
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10198
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9882
10199
|
},
|
|
9883
10200
|
required: ["value", "label"]
|
|
9884
10201
|
},
|
|
@@ -9900,13 +10217,14 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9900
10217
|
we_know_when: { type: "string", description: "The measurable signal that confirms or refutes the claim." },
|
|
9901
10218
|
risk_if_wrong: { type: "string", description: "Risk surface for prioritisation if the claim turns out wrong." },
|
|
9902
10219
|
current_confidence: {
|
|
9903
|
-
type: "
|
|
10220
|
+
type: "assessment",
|
|
10221
|
+
scale_id: "confidence_5",
|
|
9904
10222
|
description: "Team confidence at the current point in time. Derived from the weighted sum of attached `hypothesis_evidence` rows (formula spec'd separately). Authors may set explicitly; loaders may overwrite from derivation.",
|
|
9905
10223
|
properties: {
|
|
9906
10224
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9907
10225
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9908
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9909
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10226
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10227
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9910
10228
|
},
|
|
9911
10229
|
required: ["value", "label"]
|
|
9912
10230
|
}
|
|
@@ -9916,13 +10234,14 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9916
10234
|
evidence_type: { type: "string", enum: ["experiment_run", "observation", "quote", "metric_change", "market_data", "interview"], description: "Kind of evidence. Drives renderer + filter UI. The provenance edge (`derived_from_*`) carries the actual source node reference per P14; this enum is typing/UI metadata." },
|
|
9917
10235
|
direction: { type: "string", enum: ["supports", "refutes", "neutral"], description: "Direction relative to the parent claim. Canonical direction axis aligned to `Evidence.direction` so every direction-of-evidence property uses the same vocab. `supports` = paired with the `supports` edge. `refutes` = paired with the `refutes` edge. `neutral` = data insufficient or noisy. BREAKING in v0.4.0: legacy `'confirms'`, `'disconfirms'`, `'inconclusive'` no longer type-check. Migration: `confirms \u2192 supports`, `disconfirms \u2192 refutes`, `inconclusive \u2192 neutral`." },
|
|
9918
10236
|
weight: {
|
|
9919
|
-
type: "
|
|
9920
|
-
|
|
10237
|
+
type: "assessment",
|
|
10238
|
+
scale_id: "importance_5",
|
|
10239
|
+
description: "Strength of the evidence (UPGAssessment, scale `scale_5`).",
|
|
9921
10240
|
properties: {
|
|
9922
10241
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
9923
10242
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
9924
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
9925
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10243
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10244
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
9926
10245
|
},
|
|
9927
10246
|
required: ["value", "label"]
|
|
9928
10247
|
},
|
|
@@ -9940,8 +10259,8 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9940
10259
|
// IncidentProperties: Incident.
|
|
9941
10260
|
incident: {
|
|
9942
10261
|
incident_type: { type: "string", enum: ["operational", "security", "data_breach", "performance", "dependency", "other"], description: 'Discriminator. Absorbs the deprecated `security_incident` type. When `incident_type === \'security\'`, this node replaces the former `security_incident`. @example "security" for a data breach, "operational" for a service outage, "performance" for degradation' },
|
|
9943
|
-
severity_level: { type: "string", enum: ["sev1", "sev2", "sev3", "sev4"], description: '
|
|
9944
|
-
urgency: { type: "string", enum: ["high", "
|
|
10262
|
+
severity_level: { type: "string", enum: ["sev1", "sev2", "sev3", "sev4"], description: 'Incident severity tier (paging classification). `sev1` = critical/system down. `sev2` = major impact. `sev3` = minor impact. `sev4` = minimal. Uses the `IncidentSeverity` scale; distinct from user-impact `severity_5`. @example "sev1" for complete service unavailability' },
|
|
10263
|
+
urgency: { type: "string", enum: ["low", "medium", "high", "critical"], description: "Notification urgency. Independent of severity. Uses the shared `SignalUrgency` scale (`low` | `medium` | `high` | `critical`); higher tiers escalate the notification channel." },
|
|
9945
10264
|
started_at: { type: "string", description: "ISO timestamp the incident started or was first detected." },
|
|
9946
10265
|
acknowledged_at: { type: "string", description: "ISO timestamp first acknowledged by a responder. Used to compute time-to-acknowledge." },
|
|
9947
10266
|
contained_at: { type: "string", description: "ISO timestamp contained. Blast radius limited, bleeding stopped. Containment precedes full resolution, especially for security incidents." },
|
|
@@ -9967,7 +10286,18 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9967
10286
|
// InsightProperties: Unified insight, synthesised from evidence and observations.
|
|
9968
10287
|
insight: {
|
|
9969
10288
|
insight_level: { type: "string", enum: ["pattern", "finding", "actionable", "strategic"], description: "Maturity level. `pattern` = recurring observation, not yet interpreted. `finding` = interpreted pattern with a clear meaning. `actionable` = finding with a clear next step. `strategic` = finding that affects product direction." },
|
|
9970
|
-
confidence: {
|
|
10289
|
+
confidence: {
|
|
10290
|
+
type: "assessment",
|
|
10291
|
+
scale_id: "confidence_5",
|
|
10292
|
+
description: "Confidence (UPGAssessment on `confidence_5`). Reflects the strength and diversity of supporting evidence.",
|
|
10293
|
+
properties: {
|
|
10294
|
+
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10295
|
+
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10296
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10297
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10298
|
+
},
|
|
10299
|
+
required: ["value", "label"]
|
|
10300
|
+
},
|
|
9971
10301
|
evidence_count: { type: "number", description: "Supporting observations, quotes, or evidence items. Higher counts increase confidence." },
|
|
9972
10302
|
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." },
|
|
9973
10303
|
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." },
|
|
@@ -10005,20 +10335,21 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10005
10335
|
// InvestigationProperties: Active thread of inquiry: debugging, architecture exploration, RCA.
|
|
10006
10336
|
investigation: {
|
|
10007
10337
|
severity: {
|
|
10008
|
-
type: "
|
|
10338
|
+
type: "assessment",
|
|
10339
|
+
scale_id: "severity_5",
|
|
10009
10340
|
description: "Believed severity of the underlying issue. Drives prioritisation across investigations. Canonicalised in v0.4.0: the ad-hoc `'low' | 'medium' | 'high' | 'critical'` shape was replaced by `UPGAssessment` so every \"severity\" property reports on the same axis. Migration: `low \u2192 2`, `medium \u2192 3`, `high \u2192 4`, `critical \u2192 5`.",
|
|
10010
10341
|
properties: {
|
|
10011
10342
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10012
10343
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10013
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10014
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10344
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10345
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10015
10346
|
},
|
|
10016
10347
|
required: ["value", "label"]
|
|
10017
10348
|
},
|
|
10018
10349
|
hypothesis: { type: "string", description: "Working hypothesis about the root cause" },
|
|
10019
10350
|
findings: { type: "string", description: "Findings discovered so far" },
|
|
10020
10351
|
started_at: { type: "string", description: "ISO timestamp the investigation began" },
|
|
10021
|
-
resolved_at: { type: "string", description: "ISO timestamp the investigation was concluded. Pairs with `
|
|
10352
|
+
resolved_at: { type: "string", description: "ISO timestamp the investigation was concluded. Pairs with `status === 'resolved' | 'abandoned'`." },
|
|
10022
10353
|
lead_investigator: { type: "string", description: "Lead investigator (email or handle). Distinct from the team owning the affected service." },
|
|
10023
10354
|
session_id: { type: "string", description: "Originating session" },
|
|
10024
10355
|
category: { type: "string", enum: ["performance", "security", "data_quality", "reliability", "cost", "compliance", "other"], description: "Kind of issue under investigation. Distinct from `RootCauseProperties.cause_category`, which captures *why something went wrong*." }
|
|
@@ -10044,24 +10375,26 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10044
10375
|
statement: { type: "string", description: 'Job statement: "When I... I want to... So I can..."' },
|
|
10045
10376
|
job_type: { type: "string", enum: ["functional", "emotional", "social", "supporting"], description: "Classification by motivation dimension" },
|
|
10046
10377
|
importance: {
|
|
10047
|
-
type: "
|
|
10378
|
+
type: "assessment",
|
|
10379
|
+
scale_id: "importance_5",
|
|
10048
10380
|
description: "Importance to the user (1 = low, 5 = critical)",
|
|
10049
10381
|
properties: {
|
|
10050
10382
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10051
10383
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10052
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10053
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10384
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10385
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10054
10386
|
},
|
|
10055
10387
|
required: ["value", "label"]
|
|
10056
10388
|
},
|
|
10057
10389
|
current_satisfaction: {
|
|
10058
|
-
type: "
|
|
10390
|
+
type: "assessment",
|
|
10391
|
+
scale_id: "satisfaction_5",
|
|
10059
10392
|
description: "Current satisfaction with how this job gets done (1 = very unsatisfied, 5 = fully satisfied)",
|
|
10060
10393
|
properties: {
|
|
10061
10394
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10062
10395
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10063
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10064
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10396
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10397
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10065
10398
|
},
|
|
10066
10399
|
required: ["value", "label"]
|
|
10067
10400
|
},
|
|
@@ -10079,24 +10412,26 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10079
10412
|
action_description: { type: "string", description: "Plain-language description. Primary content of the action." },
|
|
10080
10413
|
channel: { type: "string", enum: ["in-app", "email", "web", "mobile", "phone", "in-person", "sms", "social", "other"], description: "Channel or surface. Keeps service-blueprint columns consistent across the journey." },
|
|
10081
10414
|
pain_score: {
|
|
10082
|
-
type: "
|
|
10415
|
+
type: "assessment",
|
|
10416
|
+
scale_id: "pain_5",
|
|
10083
10417
|
description: "Pain (1 = effortless, 5 = very painful). Drives opportunity discovery.",
|
|
10084
10418
|
properties: {
|
|
10085
10419
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10086
10420
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10087
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10088
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10421
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10422
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10089
10423
|
},
|
|
10090
10424
|
required: ["value", "label"]
|
|
10091
10425
|
},
|
|
10092
10426
|
opportunity_score: {
|
|
10093
|
-
type: "
|
|
10427
|
+
type: "assessment",
|
|
10428
|
+
scale_id: "impact_5",
|
|
10094
10429
|
description: "Opportunity (1 = low leverage, 5 = high leverage). Pairs with `pain_score` to rank investment.",
|
|
10095
10430
|
properties: {
|
|
10096
10431
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10097
10432
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10098
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10099
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10433
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10434
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10100
10435
|
},
|
|
10101
10436
|
required: ["value", "label"]
|
|
10102
10437
|
},
|
|
@@ -10120,24 +10455,26 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10120
10455
|
touchpoint: { type: "string", description: "Interaction touchpoint" },
|
|
10121
10456
|
channel: { type: "string", description: 'Channel (e.g. "web", "email", "in-store")' },
|
|
10122
10457
|
emotion_score: {
|
|
10123
|
-
type: "
|
|
10458
|
+
type: "assessment",
|
|
10459
|
+
scale_id: "satisfaction_5",
|
|
10124
10460
|
description: "User emotion (1 = very negative, 5 = very positive)",
|
|
10125
10461
|
properties: {
|
|
10126
10462
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10127
10463
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10128
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10129
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10464
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10465
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10130
10466
|
},
|
|
10131
10467
|
required: ["value", "label"]
|
|
10132
10468
|
},
|
|
10133
10469
|
friction_score: {
|
|
10134
|
-
type: "
|
|
10470
|
+
type: "assessment",
|
|
10471
|
+
scale_id: "pain_5",
|
|
10135
10472
|
description: "Friction (1 = effortless, 5 = very painful)",
|
|
10136
10473
|
properties: {
|
|
10137
10474
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10138
10475
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10139
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10140
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10476
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10477
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10141
10478
|
},
|
|
10142
10479
|
required: ["value", "label"]
|
|
10143
10480
|
},
|
|
@@ -10150,7 +10487,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10150
10487
|
cadence: { type: "string", enum: ["continuous", "hourly", "daily", "weekly", "monthly", "quarterly", "yearly", "on_demand", "other"], description: 'Canonical `Cadence`. Replaces the legacy free-form `frequency: string` in v0.4.0. For exact rates (e.g. "3 times per week") set `frequency_count` + `frequency_period`. For qualitative tiers ("rare" \u2192 "constant") use `frequency_rating`.' },
|
|
10151
10488
|
frequency_count: { type: "number", description: "Exact count of runs in the period. Pairs with `frequency_period`." },
|
|
10152
10489
|
frequency_period: { type: "string", description: "Recurrence period (ISO-8601 `Duration`, e.g. `'P7D'`)" },
|
|
10153
|
-
frequency_rating: { type: "string", enum: ["
|
|
10490
|
+
frequency_rating: { type: "string", enum: ["constant", "regular", "occasional", "rare", "other"], description: "Qualitative tier. Use when an exact rate is unknown." },
|
|
10154
10491
|
operational_owner: { type: "string", description: "Operationally accountable team or individual" },
|
|
10155
10492
|
capacity_constraint: { type: "string", description: "Bottleneck or scaling constraint" },
|
|
10156
10493
|
automation_level: { type: "string", enum: ["manual", "assisted", "automated"], description: "How much runs without human intervention" }
|
|
@@ -10161,13 +10498,14 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10161
10498
|
criticality: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Criticality to the business model" },
|
|
10162
10499
|
owner: { type: "string", description: "Accountable person or team" },
|
|
10163
10500
|
scarcity_risk: {
|
|
10164
|
-
type: "
|
|
10501
|
+
type: "assessment",
|
|
10502
|
+
scale_id: "severity_5",
|
|
10165
10503
|
description: "Replacement difficulty",
|
|
10166
10504
|
properties: {
|
|
10167
10505
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10168
10506
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10169
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10170
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10507
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10508
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10171
10509
|
},
|
|
10172
10510
|
required: ["value", "label"]
|
|
10173
10511
|
},
|
|
@@ -10201,7 +10539,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10201
10539
|
// LearningProperties: Result of an experiment. Evidence that updates a hypothesis.
|
|
10202
10540
|
learning: {
|
|
10203
10541
|
result: { type: "string", description: "Summary" },
|
|
10204
|
-
metric: { type: "string", description: 'Observed metric. @deprecated since="0.4.0" removeIn="0.5.0". Use the canonical edge `learning_observed_on_metric` to link to the metric structurally. Free-text was the wrong shape: a metric is a queryable graph entity.' },
|
|
10205
10542
|
result_value: { type: "number", description: "Measured value of the result" },
|
|
10206
10543
|
result_unit: { type: "string", description: 'Unit (e.g. "%" or "ms")' },
|
|
10207
10544
|
result_direction: { type: "string", enum: ["supports", "refutes", "neutral"], description: "Direction relative to the parent hypothesis. Canonical direction axis. BREAKING in v0.4.0: legacy `'positive'`, `'negative'`, `'neutral'` are replaced by `'supports'`, `'refutes'`, `'neutral'` to align with `Evidence.direction` and `HypothesisEvidence.direction`. Migration: `positive \u2192 supports`, `negative \u2192 refutes`, `neutral \u2192 neutral`." },
|
|
@@ -10257,25 +10594,27 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10257
10594
|
// MarketTrendProperties: Market trend.
|
|
10258
10595
|
market_trend: {
|
|
10259
10596
|
relevance: {
|
|
10260
|
-
type: "
|
|
10597
|
+
type: "assessment",
|
|
10598
|
+
scale_id: "importance_5",
|
|
10261
10599
|
description: "Relevance to our product (1 = low, 5 = critical).",
|
|
10262
10600
|
properties: {
|
|
10263
10601
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10264
10602
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10265
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10266
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10603
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10604
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10267
10605
|
},
|
|
10268
10606
|
required: ["value", "label"]
|
|
10269
10607
|
},
|
|
10270
10608
|
timeframe: { type: "string", description: 'Expected peak or mainstream window. @example "12-18 months", "2027"' },
|
|
10271
10609
|
impact: {
|
|
10272
|
-
type: "
|
|
10610
|
+
type: "assessment",
|
|
10611
|
+
scale_id: "impact_5",
|
|
10273
10612
|
description: "Expected impact on our market or category.",
|
|
10274
10613
|
properties: {
|
|
10275
10614
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10276
10615
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10277
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10278
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10616
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10617
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10279
10618
|
},
|
|
10280
10619
|
required: ["value", "label"]
|
|
10281
10620
|
},
|
|
@@ -10386,35 +10725,38 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10386
10725
|
valence: { type: "string", enum: ["pain", "gap", "constraint"], description: "What kind of experience: pain (friction), gap (unmet), constraint (limitation)" },
|
|
10387
10726
|
maturity: { type: "string", enum: ["raw", "validated", "prioritized"], description: "How mature is this need in our understanding" },
|
|
10388
10727
|
frequency: {
|
|
10389
|
-
type: "
|
|
10728
|
+
type: "assessment",
|
|
10729
|
+
scale_id: "frequency_5",
|
|
10390
10730
|
description: "How often the user encounters this need (1 = rarely, 5 = constantly)",
|
|
10391
10731
|
properties: {
|
|
10392
10732
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10393
10733
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10394
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10395
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10734
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10735
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10396
10736
|
},
|
|
10397
10737
|
required: ["value", "label"]
|
|
10398
10738
|
},
|
|
10399
10739
|
severity: {
|
|
10400
|
-
type: "
|
|
10740
|
+
type: "assessment",
|
|
10741
|
+
scale_id: "severity_5",
|
|
10401
10742
|
description: "How painful or disruptive the need is when unaddressed (1 = minor, 5 = critical)",
|
|
10402
10743
|
properties: {
|
|
10403
10744
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10404
10745
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10405
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10406
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10746
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10747
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10407
10748
|
},
|
|
10408
10749
|
required: ["value", "label"]
|
|
10409
10750
|
},
|
|
10410
10751
|
importance: {
|
|
10411
|
-
type: "
|
|
10752
|
+
type: "assessment",
|
|
10753
|
+
scale_id: "importance_5",
|
|
10412
10754
|
description: "How important resolving this need is to the user (1 = low, 5 = critical)",
|
|
10413
10755
|
properties: {
|
|
10414
10756
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10415
10757
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10416
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10417
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10758
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10759
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10418
10760
|
},
|
|
10419
10761
|
required: ["value", "label"]
|
|
10420
10762
|
},
|
|
@@ -10435,13 +10777,14 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10435
10777
|
statement: { type: "string", description: "The objection as stated by the source" },
|
|
10436
10778
|
source_type: { type: "string", enum: ["prospect", "competitor", "internal", "market"], description: "Where this objection originated" },
|
|
10437
10779
|
severity: {
|
|
10438
|
-
type: "
|
|
10780
|
+
type: "assessment",
|
|
10781
|
+
scale_id: "severity_5",
|
|
10439
10782
|
description: "How frequently or strongly this objection comes up (1-5)",
|
|
10440
10783
|
properties: {
|
|
10441
10784
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10442
10785
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10443
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10444
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10786
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10787
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10445
10788
|
},
|
|
10446
10789
|
required: ["value", "label"]
|
|
10447
10790
|
},
|
|
@@ -10460,7 +10803,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10460
10803
|
session_ref: { type: "string", description: "Capturing session reference. Convenience field; the canonical relationship to study/session is an edge per P14. Retained as a lightweight context anchor for AI inference." },
|
|
10461
10804
|
is_highlighted: { type: "boolean", description: "Flagged as a highlight. Absorbed from the deprecated Highlight entity." },
|
|
10462
10805
|
highlight_tag: { type: "string", description: 'Free-form highlight type tag. @example "pain", "delight", "behaviour", "moment of clarity"' },
|
|
10463
|
-
sentiment: { type: "string", enum: ["positive", "
|
|
10806
|
+
sentiment: { type: "string", enum: ["positive", "neutral", "negative", "mixed"], description: "Structured sentiment. Tools like Dovetail and EnjoyHQ converge on these four values. More precise than `highlight_tag` for aggregation." }
|
|
10464
10807
|
},
|
|
10465
10808
|
// OnCallRotationProperties: On-call rotation.
|
|
10466
10809
|
on_call_rotation: {
|
|
@@ -10472,35 +10815,38 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10472
10815
|
// OpportunityProperties: A problem worth solving, grounded in user need and business value
|
|
10473
10816
|
opportunity: {
|
|
10474
10817
|
reach: {
|
|
10475
|
-
type: "
|
|
10818
|
+
type: "assessment",
|
|
10819
|
+
scale_id: "reach_5",
|
|
10476
10820
|
description: "How many users experience this problem",
|
|
10477
10821
|
properties: {
|
|
10478
10822
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10479
10823
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10480
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10481
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10824
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10825
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10482
10826
|
},
|
|
10483
10827
|
required: ["value", "label"]
|
|
10484
10828
|
},
|
|
10485
10829
|
frequency: {
|
|
10486
|
-
type: "
|
|
10830
|
+
type: "assessment",
|
|
10831
|
+
scale_id: "frequency_5",
|
|
10487
10832
|
description: "How often users experience this problem",
|
|
10488
10833
|
properties: {
|
|
10489
10834
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10490
10835
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10491
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10492
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10836
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10837
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10493
10838
|
},
|
|
10494
10839
|
required: ["value", "label"]
|
|
10495
10840
|
},
|
|
10496
10841
|
pain: {
|
|
10497
|
-
type: "
|
|
10842
|
+
type: "assessment",
|
|
10843
|
+
scale_id: "pain_5",
|
|
10498
10844
|
description: "How painful it is when unaddressed",
|
|
10499
10845
|
properties: {
|
|
10500
10846
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10501
10847
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10502
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10503
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10848
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10849
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10504
10850
|
},
|
|
10505
10851
|
required: ["value", "label"]
|
|
10506
10852
|
},
|
|
@@ -10521,17 +10867,18 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10521
10867
|
current_state: { type: "string", description: "Baseline or latest read" },
|
|
10522
10868
|
evidence_summary: { type: "string", description: "Evidence gathered so far (quotes, metrics, studies)" },
|
|
10523
10869
|
confidence: {
|
|
10524
|
-
type: "
|
|
10870
|
+
type: "assessment",
|
|
10871
|
+
scale_id: "confidence_5",
|
|
10525
10872
|
description: "Confidence this is the right outcome to pursue",
|
|
10526
10873
|
properties: {
|
|
10527
10874
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10528
10875
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10529
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10530
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10876
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10877
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10531
10878
|
},
|
|
10532
10879
|
required: ["value", "label"]
|
|
10533
10880
|
},
|
|
10534
|
-
outcome_status: { type: "string", description: "Current lifecycle phase
|
|
10881
|
+
outcome_status: { type: "string", enum: ["identified", "measuring", "achieved", "abandoned"], description: "Current lifecycle phase, mirroring the `outcome` lifecycle in `grammar/lifecycles.ts` (UPG-579 Option B): `identified` -> `measuring` -> `achieved` | `abandoned`." }
|
|
10535
10882
|
},
|
|
10536
10883
|
// ParticipantProperties: Research participant.
|
|
10537
10884
|
participant: {
|
|
@@ -10562,13 +10909,14 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10562
10909
|
value_exchange: { type: "string", description: "What each party gives and receives" },
|
|
10563
10910
|
partnership_tier: { type: "string", enum: ["strategic", "preferred", "standard", "trial"], description: "Commercial significance. Drives attention and exec sponsorship." },
|
|
10564
10911
|
risk_level: {
|
|
10565
|
-
type: "
|
|
10912
|
+
type: "assessment",
|
|
10913
|
+
scale_id: "severity_5",
|
|
10566
10914
|
description: "Exposure if the partnership fails (concentration risk, IP risk, etc.)",
|
|
10567
10915
|
properties: {
|
|
10568
10916
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10569
10917
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10570
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10571
|
-
normalized: { type: "number", description: "Normalized 0
|
|
10918
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
10919
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10572
10920
|
},
|
|
10573
10921
|
required: ["value", "label"]
|
|
10574
10922
|
},
|
|
@@ -10609,7 +10957,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10609
10957
|
},
|
|
10610
10958
|
// PipelineSalesProperties: Sales pipeline.
|
|
10611
10959
|
pipeline_sales: {
|
|
10612
|
-
pipeline_type: { type: "string", description:
|
|
10960
|
+
pipeline_type: { type: "string", enum: ["new_business", "expansion", "renewal", "partner", "other"], description: "Classification of the pipeline (UPG-579 Option B)." },
|
|
10613
10961
|
avg_cycle_days: { type: "number", description: "Average days from opportunity creation to close" }
|
|
10614
10962
|
},
|
|
10615
10963
|
// PipelineStageProperties: Pipeline stage.
|
|
@@ -10651,7 +10999,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10651
10999
|
// PricingStrategyProperties: Pricing strategy.
|
|
10652
11000
|
pricing_strategy: {
|
|
10653
11001
|
strategy_type: { type: "string", enum: ["value_based", "cost_plus", "competitor_based", "penetration", "freemium"], description: "Pricing methodology used" },
|
|
10654
|
-
review_cadence: { type: "string", description: "How often pricing is reviewed" },
|
|
11002
|
+
review_cadence: { type: "string", enum: ["continuous", "hourly", "daily", "weekly", "monthly", "quarterly", "yearly", "on_demand", "other"], description: "How often pricing is reviewed. Uses the shared `Cadence` scale." },
|
|
10655
11003
|
last_change: { type: "string", description: "Date of the last pricing change (ISO format)" }
|
|
10656
11004
|
},
|
|
10657
11005
|
// PricingTierProperties: PricingTier: the central pricing concept (the plan a customer buys).
|
|
@@ -10760,13 +11108,14 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10760
11108
|
rebuttal: {
|
|
10761
11109
|
statement: { type: "string", description: "The counter-argument or response to an objection" },
|
|
10762
11110
|
strength: {
|
|
10763
|
-
type: "
|
|
11111
|
+
type: "assessment",
|
|
11112
|
+
scale_id: "scale_5",
|
|
10764
11113
|
description: "How convincing this rebuttal is (1-5)",
|
|
10765
11114
|
properties: {
|
|
10766
11115
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10767
11116
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10768
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10769
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11117
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11118
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10770
11119
|
},
|
|
10771
11120
|
required: ["value", "label"]
|
|
10772
11121
|
},
|
|
@@ -10859,24 +11208,26 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10859
11208
|
risk: {
|
|
10860
11209
|
risk_type: { type: "string", enum: ["technical", "business", "legal", "security", "operational"], description: "Domain the risk belongs to" },
|
|
10861
11210
|
probability: {
|
|
10862
|
-
type: "
|
|
11211
|
+
type: "assessment",
|
|
11212
|
+
scale_id: "confidence_5",
|
|
10863
11213
|
description: "How likely this risk is to materialise (1 = unlikely, 5 = near certain)",
|
|
10864
11214
|
properties: {
|
|
10865
11215
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10866
11216
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10867
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10868
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11217
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11218
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10869
11219
|
},
|
|
10870
11220
|
required: ["value", "label"]
|
|
10871
11221
|
},
|
|
10872
11222
|
impact: {
|
|
10873
|
-
type: "
|
|
11223
|
+
type: "assessment",
|
|
11224
|
+
scale_id: "impact_5",
|
|
10874
11225
|
description: "Severity of consequences if the risk materialises (1 = negligible, 5 = catastrophic)",
|
|
10875
11226
|
properties: {
|
|
10876
11227
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10877
11228
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10878
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10879
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11229
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11230
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10880
11231
|
},
|
|
10881
11232
|
required: ["value", "label"]
|
|
10882
11233
|
},
|
|
@@ -10897,7 +11248,18 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10897
11248
|
quarter: { type: "string", description: 'Planning quarter (e.g. "Q2 2026"). Pair with `start_date`/`target_date` for precise scheduling.' },
|
|
10898
11249
|
priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Importance against other items" },
|
|
10899
11250
|
item_status: { type: "string", enum: ["planned", "in_progress", "shipped", "deferred"], description: "Status. `deferred` = explicitly pushed to a later period." },
|
|
10900
|
-
confidence: {
|
|
11251
|
+
confidence: {
|
|
11252
|
+
type: "assessment",
|
|
11253
|
+
scale_id: "confidence_5",
|
|
11254
|
+
description: "Delivery confidence within the planned period (UPGAssessment on `confidence_5`).",
|
|
11255
|
+
properties: {
|
|
11256
|
+
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11257
|
+
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11258
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11259
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11260
|
+
},
|
|
11261
|
+
required: ["value", "label"]
|
|
11262
|
+
},
|
|
10901
11263
|
start_date: { type: "string", description: "ISO date work begins. More precise than `quarter` for continuous planning." },
|
|
10902
11264
|
target_date: { type: "string", description: "ISO date completion is expected. For shipped items, the actual completion date." }
|
|
10903
11265
|
},
|
|
@@ -10911,13 +11273,14 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10911
11273
|
// RootCauseProperties: Underlying architectural or systemic issue.
|
|
10912
11274
|
root_cause: {
|
|
10913
11275
|
severity: {
|
|
10914
|
-
type: "
|
|
11276
|
+
type: "assessment",
|
|
11277
|
+
scale_id: "severity_5",
|
|
10915
11278
|
description: "Severity (1 = minor, 5 = critical)",
|
|
10916
11279
|
properties: {
|
|
10917
11280
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10918
11281
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10919
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10920
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11282
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11283
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10921
11284
|
},
|
|
10922
11285
|
required: ["value", "label"]
|
|
10923
11286
|
},
|
|
@@ -10967,13 +11330,14 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10967
11330
|
security_control: {
|
|
10968
11331
|
control_type: { type: "string", enum: ["preventive", "detective", "corrective", "compensating"], description: "Functional role. `preventive` = stops attacks (MFA, input validation). `detective` = identifies attacks in progress (intrusion detection, audit logs). `corrective` = reduces impact after an attack (incident response, backup restore). `compensating` = alternative when primary isn't feasible." },
|
|
10969
11332
|
effectiveness: {
|
|
10970
|
-
type: "
|
|
11333
|
+
type: "assessment",
|
|
11334
|
+
scale_id: "impact_5",
|
|
10971
11335
|
description: "Mitigation effectiveness (1 = minimal, 5 = fully effective)",
|
|
10972
11336
|
properties: {
|
|
10973
11337
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
10974
11338
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
10975
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
10976
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11339
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11340
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
10977
11341
|
},
|
|
10978
11342
|
required: ["value", "label"]
|
|
10979
11343
|
},
|
|
@@ -10984,7 +11348,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10984
11348
|
// SecurityPolicyProperties: Security policy.
|
|
10985
11349
|
security_policy: {
|
|
10986
11350
|
scope: { type: "string", description: "Systems or processes covered" },
|
|
10987
|
-
review_cadence: { type: "string", description:
|
|
11351
|
+
review_cadence: { type: "string", enum: ["continuous", "hourly", "daily", "weekly", "monthly", "quarterly", "yearly", "on_demand", "other"], description: "Review cadence (e.g. `yearly`, `quarterly`). Uses the shared `Cadence` scale." },
|
|
10988
11352
|
version: { type: "string", description: "Version" },
|
|
10989
11353
|
effective_date: { type: "string", description: "ISO effective date" },
|
|
10990
11354
|
url: { type: "string", description: "Policy document URL" },
|
|
@@ -11055,17 +11419,18 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11055
11419
|
},
|
|
11056
11420
|
// SkillProperties: Skill entity.
|
|
11057
11421
|
skill: {
|
|
11058
|
-
skill_category: { type: "string",
|
|
11422
|
+
skill_category: { type: "string", enum: ["technical", "leadership", "design", "product", "business", "operations", "other"], description: "Category of the skill (UPG-579 Option B)." },
|
|
11059
11423
|
proficiency_levels: { type: "string[]", description: "Description of proficiency levels for this skill" },
|
|
11060
11424
|
domain: { type: "string", description: 'Problem domain the skill applies to (e.g. "payments", "accessibility")' },
|
|
11061
11425
|
rarity: {
|
|
11062
|
-
type: "
|
|
11426
|
+
type: "assessment",
|
|
11427
|
+
scale_id: "scale_5",
|
|
11063
11428
|
description: "How scarce this skill is in the labour market this team hires from",
|
|
11064
11429
|
properties: {
|
|
11065
11430
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11066
11431
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11067
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
11068
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11432
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11433
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11069
11434
|
},
|
|
11070
11435
|
required: ["value", "label"]
|
|
11071
11436
|
},
|
|
@@ -11081,46 +11446,50 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11081
11446
|
solution: {
|
|
11082
11447
|
timeline: { type: "string", description: "Estimated delivery or target timeline" },
|
|
11083
11448
|
reach: {
|
|
11084
|
-
type: "
|
|
11449
|
+
type: "assessment",
|
|
11450
|
+
scale_id: "reach_5",
|
|
11085
11451
|
description: "How many users this solution reaches (1 = few, 5 = most)",
|
|
11086
11452
|
properties: {
|
|
11087
11453
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11088
11454
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11089
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
11090
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11455
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11456
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11091
11457
|
},
|
|
11092
11458
|
required: ["value", "label"]
|
|
11093
11459
|
},
|
|
11094
11460
|
impact: {
|
|
11095
|
-
type: "
|
|
11461
|
+
type: "assessment",
|
|
11462
|
+
scale_id: "impact_5",
|
|
11096
11463
|
description: "Expected impact on the target outcome (1 = minimal, 5 = transformative)",
|
|
11097
11464
|
properties: {
|
|
11098
11465
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11099
11466
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11100
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
11101
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11467
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11468
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11102
11469
|
},
|
|
11103
11470
|
required: ["value", "label"]
|
|
11104
11471
|
},
|
|
11105
11472
|
confidence: {
|
|
11106
|
-
type: "
|
|
11473
|
+
type: "assessment",
|
|
11474
|
+
scale_id: "confidence_5",
|
|
11107
11475
|
description: "How confident the team is in this solution (1 = speculative, 5 = proven)",
|
|
11108
11476
|
properties: {
|
|
11109
11477
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11110
11478
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11111
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
11112
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11479
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11480
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11113
11481
|
},
|
|
11114
11482
|
required: ["value", "label"]
|
|
11115
11483
|
},
|
|
11116
11484
|
effort: {
|
|
11117
|
-
type: "
|
|
11485
|
+
type: "assessment",
|
|
11486
|
+
scale_id: "effort_5",
|
|
11118
11487
|
description: "Level of effort required to implement (1 = trivial, 5 = very large)",
|
|
11119
11488
|
properties: {
|
|
11120
11489
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11121
11490
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11122
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
11123
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11491
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11492
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11124
11493
|
},
|
|
11125
11494
|
required: ["value", "label"]
|
|
11126
11495
|
},
|
|
@@ -11130,24 +11499,26 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11130
11499
|
stakeholder: {
|
|
11131
11500
|
stakeholder_type: { type: "string", enum: ["internal", "external", "investor", "regulator"], description: "Relationship of the stakeholder to the organisation" },
|
|
11132
11501
|
influence: {
|
|
11133
|
-
type: "
|
|
11502
|
+
type: "assessment",
|
|
11503
|
+
scale_id: "importance_5",
|
|
11134
11504
|
description: "How much influence this stakeholder has over decisions (1 = minimal, 5 = decisive)",
|
|
11135
11505
|
properties: {
|
|
11136
11506
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11137
11507
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11138
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
11139
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11508
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11509
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11140
11510
|
},
|
|
11141
11511
|
required: ["value", "label"]
|
|
11142
11512
|
},
|
|
11143
11513
|
interest: {
|
|
11144
|
-
type: "
|
|
11514
|
+
type: "assessment",
|
|
11515
|
+
scale_id: "importance_5",
|
|
11145
11516
|
description: "How much interest this stakeholder has in the outcome (1 = passive, 5 = deeply invested)",
|
|
11146
11517
|
properties: {
|
|
11147
11518
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11148
11519
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11149
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
11150
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11520
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11521
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11151
11522
|
},
|
|
11152
11523
|
required: ["value", "label"]
|
|
11153
11524
|
}
|
|
@@ -11159,19 +11530,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11159
11530
|
risks_flagged: { type: "number", description: "Number of risks flagged in this report" },
|
|
11160
11531
|
blockers: { type: "string", description: "Description of current blockers" }
|
|
11161
11532
|
},
|
|
11162
|
-
// UserStoryProperties: "As X, I want Y so Z" templated promise, a user story (UCS pattern P5).
|
|
11163
|
-
user_story: {
|
|
11164
|
-
as_a: { type: "string", description: '"As a [persona], \u2026". Free-text persona name or slug ref.' },
|
|
11165
|
-
i_want_to: { type: "string", description: "Capability or action the persona wants." },
|
|
11166
|
-
so_that: { type: "string", description: "Benefit or outcome the persona expects." },
|
|
11167
|
-
text: { type: "string", description: "Free-form story text. Used as a single-line rendered view." }
|
|
11168
|
-
},
|
|
11169
|
-
// StoryTaskProperties
|
|
11170
|
-
story_task: {
|
|
11171
|
-
estimate: { type: "string", description: "@deprecated Use TaskProperties.estimate" },
|
|
11172
|
-
effort: { type: "number", description: "@deprecated Use TaskProperties.effort (string form)" },
|
|
11173
|
-
priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "@deprecated Use TaskProperties.priority" }
|
|
11174
|
-
},
|
|
11175
11533
|
// StrategicPillarProperties: StrategicPillar entity. Durable multi-year direction the product commits to.
|
|
11176
11534
|
strategic_pillar: {
|
|
11177
11535
|
owner: { type: "string", description: "Owning person or team" },
|
|
@@ -11205,19 +11563,20 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11205
11563
|
support_ticket: {
|
|
11206
11564
|
ticket_type: { type: "string", enum: ["bug", "question", "feature_request"], description: "Classification of the ticket" },
|
|
11207
11565
|
severity: {
|
|
11208
|
-
type: "
|
|
11566
|
+
type: "assessment",
|
|
11567
|
+
scale_id: "severity_5",
|
|
11209
11568
|
description: "Impact severity of the issue (1 = cosmetic, 5 = service down)",
|
|
11210
11569
|
properties: {
|
|
11211
11570
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11212
11571
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11213
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
11214
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11572
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11573
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11215
11574
|
},
|
|
11216
11575
|
required: ["value", "label"]
|
|
11217
11576
|
},
|
|
11218
11577
|
resolution: { type: "string", description: "Description of how the ticket was resolved" },
|
|
11219
11578
|
source: { type: "string", description: 'Where the ticket originated (e.g. "email", "in-app", "chat")' },
|
|
11220
|
-
signal_sentiment: { type: "string", enum: ["positive", "
|
|
11579
|
+
signal_sentiment: { type: "string", enum: ["positive", "neutral", "negative", "mixed"], description: "Detected sentiment of the customer's message" },
|
|
11221
11580
|
signal_channel: { type: "string", description: "Channel through which the signal was received" },
|
|
11222
11581
|
signal_urgency: { type: "string", enum: ["low", "medium", "high", "critical"], description: "Perceived urgency of the customer's request" }
|
|
11223
11582
|
},
|
|
@@ -11238,19 +11597,20 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11238
11597
|
symptom_description: { type: "string", description: "Plain-language description of observed behaviour. Primary content of the entity." },
|
|
11239
11598
|
first_observed_at: { type: "string", description: "ISO timestamp first observed in the wild. Pairs with `frequency_rating` and `reproducibility` for triage." },
|
|
11240
11599
|
severity: {
|
|
11241
|
-
type: "
|
|
11600
|
+
type: "assessment",
|
|
11601
|
+
scale_id: "severity_5",
|
|
11242
11602
|
description: "Severity for affected users. Independent of how widespread the symptom is. Canonicalised in v0.4.0: the ad-hoc `'low' | 'medium' | 'high' | 'critical'` shape was replaced by `UPGAssessment`.",
|
|
11243
11603
|
properties: {
|
|
11244
11604
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11245
11605
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11246
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
11247
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11606
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11607
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11248
11608
|
},
|
|
11249
11609
|
required: ["value", "label"]
|
|
11250
11610
|
},
|
|
11251
11611
|
frequency_count: { type: "number", description: "Exact observation count in the period. Pairs with `frequency_period` for a precise rate." },
|
|
11252
11612
|
frequency_period: { type: "string", description: "Recurrence period (ISO-8601 `Duration`). @example 'P7D' (per week), 'P1D' (per day), 'PT1H' (per hour)" },
|
|
11253
|
-
frequency_rating: { type: "string", enum: ["
|
|
11613
|
+
frequency_rating: { type: "string", enum: ["constant", "regular", "occasional", "rare", "other"], description: "Qualitative frequency tier. Canonical replacement for the legacy `'once' | 'sporadic' | 'frequent' | 'constant' | string` shape. Use when an exact rate is unknown. Migration: `once \u2192 rare`, `sporadic \u2192 occasional`, `frequent \u2192 regular`, `constant \u2192 constant`." },
|
|
11254
11614
|
affected_users_estimate: { type: "number", description: "Approximate count of users affected. Snapshot estimate." },
|
|
11255
11615
|
reproducibility: { type: "string", enum: ["always", "frequent", "intermittent", "rare", "once"], description: "Reproduction reliability" },
|
|
11256
11616
|
steps_to_reproduce: { type: "string", description: "Steps to reproduce" }
|
|
@@ -11263,7 +11623,6 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11263
11623
|
},
|
|
11264
11624
|
// TaskProperties: Task: a discrete unit of work, smaller than a story.
|
|
11265
11625
|
task: {
|
|
11266
|
-
task_status: { type: "string", enum: ["todo", "in_progress", "in_review", "done"], description: "@deprecated since v0.4.0. Use top-level `UPGBaseNode.status`. Values map identically: todo | in_progress | in_review | done. Migration: `UPG_PROPERTY_MIGRATIONS['0.4.0']` lifts this to `status`." },
|
|
11267
11626
|
assignee: { type: "string", description: "Assigned person" },
|
|
11268
11627
|
effort: { type: "string", description: 'Effort estimate (e.g. "2h", "1d", "3 points"). Use a consistent unit within your team.' },
|
|
11269
11628
|
priority: { type: "string", enum: ["urgent", "high", "medium", "low", "none"], description: "Relative importance against other tasks" },
|
|
@@ -11288,24 +11647,26 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11288
11647
|
technical_debt_item: {
|
|
11289
11648
|
debt_type: { type: "string", enum: ["code", "architecture", "security", "test", "docs", "dependency"], description: "Type of debt. `code` = quality issues. `architecture` = structural problems. `security` = unpatched vulnerabilities. `test` = missing/flaky tests. `docs` = missing or stale documentation. `dependency` = outdated packages." },
|
|
11290
11649
|
severity: {
|
|
11291
|
-
type: "
|
|
11650
|
+
type: "assessment",
|
|
11651
|
+
scale_id: "severity_5",
|
|
11292
11652
|
description: "Severity on system or team. Requires human evaluation.",
|
|
11293
11653
|
properties: {
|
|
11294
11654
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11295
11655
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11296
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
11297
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11656
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11657
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11298
11658
|
},
|
|
11299
11659
|
required: ["value", "label"]
|
|
11300
11660
|
},
|
|
11301
11661
|
effort_to_fix: {
|
|
11302
|
-
type: "
|
|
11662
|
+
type: "assessment",
|
|
11663
|
+
scale_id: "effort_5",
|
|
11303
11664
|
description: "Estimated effort to resolve. Requires team knowledge of the codebase.",
|
|
11304
11665
|
properties: {
|
|
11305
11666
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11306
11667
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11307
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
11308
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11668
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11669
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11309
11670
|
},
|
|
11310
11671
|
required: ["value", "label"]
|
|
11311
11672
|
},
|
|
@@ -11388,24 +11749,26 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11388
11749
|
threat: {
|
|
11389
11750
|
category: { type: "string", description: 'Attack or threat scenario. @example "injection", "misconfiguration", "social engineering", "supply chain"' },
|
|
11390
11751
|
likelihood: {
|
|
11391
|
-
type: "
|
|
11752
|
+
type: "assessment",
|
|
11753
|
+
scale_id: "confidence_5",
|
|
11392
11754
|
description: "Likelihood (1 = theoretical, 5 = actively exploited). @example value 5 for a known, exploitable, commonly targeted pattern",
|
|
11393
11755
|
properties: {
|
|
11394
11756
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11395
11757
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11396
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
11397
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11758
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11759
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11398
11760
|
},
|
|
11399
11761
|
required: ["value", "label"]
|
|
11400
11762
|
},
|
|
11401
11763
|
impact: {
|
|
11402
|
-
type: "
|
|
11764
|
+
type: "assessment",
|
|
11765
|
+
scale_id: "impact_5",
|
|
11403
11766
|
description: "Impact (1 = minimal, 5 = catastrophic). @example value 5 for threats that expose PII or cause complete service compromise",
|
|
11404
11767
|
properties: {
|
|
11405
11768
|
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11406
11769
|
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11407
|
-
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)" },
|
|
11408
|
-
normalized: { type: "number", description: "Normalized 0
|
|
11770
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11771
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11409
11772
|
},
|
|
11410
11773
|
required: ["value", "label"]
|
|
11411
11774
|
},
|
|
@@ -11463,7 +11826,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11463
11826
|
// UserAdvisoryBoardProperties: User advisory board.
|
|
11464
11827
|
user_advisory_board: {
|
|
11465
11828
|
member_count: { type: "number", description: "Number of members on the board" },
|
|
11466
|
-
meeting_cadence: { type: "string", description:
|
|
11829
|
+
meeting_cadence: { type: "string", enum: ["continuous", "hourly", "daily", "weekly", "monthly", "quarterly", "yearly", "on_demand", "other"], description: "How often the board meets. Uses the shared `Cadence` scale." },
|
|
11467
11830
|
board_focus: { type: "string", description: "Primary topic or area the board advises on" }
|
|
11468
11831
|
},
|
|
11469
11832
|
// UserFlowProperties: User flow.
|
|
@@ -11479,6 +11842,13 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11479
11842
|
journey_type: { type: "string", enum: ["current_state", "future_state", "day_in_the_life", "service_blueprint"], description: "Maps current or future state" },
|
|
11480
11843
|
scenario: { type: "string", description: "Scenario context" }
|
|
11481
11844
|
},
|
|
11845
|
+
// UserStoryProperties: "As X, I want Y so Z" templated promise on a user story (UCS pattern P5).
|
|
11846
|
+
user_story: {
|
|
11847
|
+
as_a: { type: "string", description: '"As a [persona], \u2026". Free-text persona name or slug ref.' },
|
|
11848
|
+
i_want_to: { type: "string", description: "Capability or action the persona wants." },
|
|
11849
|
+
so_that: { type: "string", description: "Benefit or outcome the persona expects." },
|
|
11850
|
+
text: { type: "string", description: "Free-form story text. Used as a single-line rendered view." }
|
|
11851
|
+
},
|
|
11482
11852
|
// ValueObjectProperties: DDD value object.
|
|
11483
11853
|
value_object: {
|
|
11484
11854
|
immutable: { type: "boolean", description: "Whether immutable" },
|
|
@@ -11493,7 +11863,7 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11493
11863
|
},
|
|
11494
11864
|
// ValueStreamProperties: ValueStream entity.
|
|
11495
11865
|
value_stream: {
|
|
11496
|
-
stream_stage: { type: "string", description: "Current stage in the value delivery pipeline" },
|
|
11866
|
+
stream_stage: { type: "string", enum: ["discovery", "definition", "build", "delivery", "operation", "other"], description: "Current stage in the value delivery pipeline (UPG-579 Option B)." },
|
|
11497
11867
|
lead_time: { type: "string", description: 'End-to-end lead time. @example "2 weeks"' },
|
|
11498
11868
|
throughput: { type: "string", description: 'Throughput measure. @example "5 features/sprint"' }
|
|
11499
11869
|
},
|
|
@@ -11513,7 +11883,18 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
11513
11883
|
vulnerability: {
|
|
11514
11884
|
cve_id: { type: "string", description: 'CVE identifier from the National Vulnerability Database. @example "CVE-2024-1234"' },
|
|
11515
11885
|
cvss_score: { type: "number", description: "CVSS numeric score (0.0\u201310.0). Computed from the CVSS vector. Distinct from the categorical `severity`. @example 9.8 (critical), 6.5 (medium), 3.7 (low)" },
|
|
11516
|
-
severity: {
|
|
11886
|
+
severity: {
|
|
11887
|
+
type: "assessment",
|
|
11888
|
+
scale_id: "severity_5",
|
|
11889
|
+
description: "Categorical severity derived from CVSS. Impact severity (UPGAssessment on the `severity_5` scale). Score alone is insufficient for triage; severity drives filtering and prioritisation. Migrated from the inline `critical|high|medium|low|informational` enum (UPG-579 Option C): map `critical` -> 5, `high` -> 4, `medium` -> 3, `low` -> 2, `informational` -> 1; carry the old word in `label`. @example value 5, label 'Critical', scale_id 'severity_5' (a remotely exploitable, no-auth vuln)",
|
|
11890
|
+
properties: {
|
|
11891
|
+
value: { type: "number", description: "The numeric value, used for computation." },
|
|
11892
|
+
label: { type: "string", description: "The qualitative label (what the assessor meant)." },
|
|
11893
|
+
scale_id: { type: "string", description: "Which assessment scale this was rated on (optional)." },
|
|
11894
|
+
normalized: { type: "number", description: "Normalized 0-1 value for cross-tool comparison (optional)." }
|
|
11895
|
+
},
|
|
11896
|
+
required: ["value", "label"]
|
|
11897
|
+
},
|
|
11517
11898
|
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' },
|
|
11518
11899
|
affected_component: { type: "string", description: 'Affected component, library, or system. @example "lodash", "openssl", "login service"' },
|
|
11519
11900
|
affected_package: { type: "string", description: 'Affected package with version. More precise than `affected_component`. @example "lodash@4.17.20", "openssl@1.1.1q"' },
|
|
@@ -12821,26 +13202,6 @@ var UPG_FRAMEWORKS = [
|
|
|
12821
13202
|
"label": "Items to score",
|
|
12822
13203
|
"entityTypeId": "feature",
|
|
12823
13204
|
"description": "Features, opportunities, or solutions being evaluated"
|
|
12824
|
-
},
|
|
12825
|
-
{
|
|
12826
|
-
"label": "Reach",
|
|
12827
|
-
"entityTypeId": "feature",
|
|
12828
|
-
"description": "How many users does this affect per quarter?"
|
|
12829
|
-
},
|
|
12830
|
-
{
|
|
12831
|
-
"label": "Impact",
|
|
12832
|
-
"entityTypeId": "feature",
|
|
12833
|
-
"description": "How much does this move the target outcome?"
|
|
12834
|
-
},
|
|
12835
|
-
{
|
|
12836
|
-
"label": "Confidence",
|
|
12837
|
-
"entityTypeId": "feature",
|
|
12838
|
-
"description": "How sure are we about these estimates?"
|
|
12839
|
-
},
|
|
12840
|
-
{
|
|
12841
|
-
"label": "Effort",
|
|
12842
|
-
"entityTypeId": "feature",
|
|
12843
|
-
"description": "How many person-months to build?"
|
|
12844
13205
|
}
|
|
12845
13206
|
],
|
|
12846
13207
|
"data": {
|
|
@@ -12854,31 +13215,35 @@ var UPG_FRAMEWORKS = [
|
|
|
12854
13215
|
"feature": [
|
|
12855
13216
|
{
|
|
12856
13217
|
"property": "reach",
|
|
12857
|
-
"type": "
|
|
13218
|
+
"type": "assessment",
|
|
13219
|
+
"scale_id": "reach_5",
|
|
12858
13220
|
"required": true,
|
|
12859
13221
|
"label": "Reach",
|
|
12860
13222
|
"description": "How many users will this impact per quarter?"
|
|
12861
13223
|
},
|
|
12862
13224
|
{
|
|
12863
13225
|
"property": "impact",
|
|
12864
|
-
"type": "
|
|
13226
|
+
"type": "assessment",
|
|
13227
|
+
"scale_id": "impact_5",
|
|
12865
13228
|
"required": true,
|
|
12866
13229
|
"label": "Impact",
|
|
12867
|
-
"description": "How much will this impact each user
|
|
13230
|
+
"description": "How much will this impact each user, on the impact scale?"
|
|
12868
13231
|
},
|
|
12869
13232
|
{
|
|
12870
13233
|
"property": "confidence",
|
|
12871
|
-
"type": "
|
|
13234
|
+
"type": "assessment",
|
|
13235
|
+
"scale_id": "confidence_5",
|
|
12872
13236
|
"required": true,
|
|
12873
13237
|
"label": "Confidence",
|
|
12874
|
-
"description": "How confident are you in the
|
|
13238
|
+
"description": "How confident are you in the reach, impact, and effort estimates?"
|
|
12875
13239
|
},
|
|
12876
13240
|
{
|
|
12877
13241
|
"property": "effort",
|
|
12878
|
-
"type": "
|
|
13242
|
+
"type": "assessment",
|
|
13243
|
+
"scale_id": "effort_5",
|
|
12879
13244
|
"required": true,
|
|
12880
13245
|
"label": "Effort",
|
|
12881
|
-
"description": "
|
|
13246
|
+
"description": "How much work is required to build and ship this, on the effort scale?"
|
|
12882
13247
|
}
|
|
12883
13248
|
]
|
|
12884
13249
|
},
|
|
@@ -13072,7 +13437,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13072
13437
|
{
|
|
13073
13438
|
"label": "Performance",
|
|
13074
13439
|
"entityTypeId": "feature",
|
|
13075
|
-
"description": "More is better
|
|
13440
|
+
"description": "More is better: linear satisfaction increase"
|
|
13076
13441
|
},
|
|
13077
13442
|
{
|
|
13078
13443
|
"label": "Delighters",
|
|
@@ -13321,24 +13686,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13321
13686
|
],
|
|
13322
13687
|
"slots": [
|
|
13323
13688
|
{
|
|
13324
|
-
"label": "
|
|
13325
|
-
"entityTypeId": "feature",
|
|
13326
|
-
"description": "Non-negotiable requirements for this release"
|
|
13327
|
-
},
|
|
13328
|
-
{
|
|
13329
|
-
"label": "Should Have",
|
|
13330
|
-
"entityTypeId": "feature",
|
|
13331
|
-
"description": "Important but not critical; a workaround exists"
|
|
13332
|
-
},
|
|
13333
|
-
{
|
|
13334
|
-
"label": "Could Have",
|
|
13689
|
+
"label": "Requirements to categorise",
|
|
13335
13690
|
"entityTypeId": "feature",
|
|
13336
|
-
"description": "
|
|
13337
|
-
},
|
|
13338
|
-
{
|
|
13339
|
-
"label": "Won't Have",
|
|
13340
|
-
"entityTypeId": "feature",
|
|
13341
|
-
"description": "Explicitly out of scope for now"
|
|
13691
|
+
"description": "Features or requirements sorted into the four MoSCoW buckets"
|
|
13342
13692
|
}
|
|
13343
13693
|
],
|
|
13344
13694
|
"data": {
|
|
@@ -13348,7 +13698,23 @@ var UPG_FRAMEWORKS = [
|
|
|
13348
13698
|
"role": "scored_item"
|
|
13349
13699
|
}
|
|
13350
13700
|
],
|
|
13351
|
-
"required_properties": {
|
|
13701
|
+
"required_properties": {
|
|
13702
|
+
"feature": [
|
|
13703
|
+
{
|
|
13704
|
+
"property": "moscow",
|
|
13705
|
+
"type": "enum",
|
|
13706
|
+
"required": true,
|
|
13707
|
+
"label": "MoSCoW priority",
|
|
13708
|
+
"description": "Which scope bucket this requirement falls into for the current release",
|
|
13709
|
+
"enum_values": [
|
|
13710
|
+
"must",
|
|
13711
|
+
"should",
|
|
13712
|
+
"could",
|
|
13713
|
+
"wont"
|
|
13714
|
+
]
|
|
13715
|
+
}
|
|
13716
|
+
]
|
|
13717
|
+
},
|
|
13352
13718
|
"computed_properties": [
|
|
13353
13719
|
{
|
|
13354
13720
|
"property": "must_have_ratio",
|
|
@@ -13368,28 +13734,19 @@ var UPG_FRAMEWORKS = [
|
|
|
13368
13734
|
"columns": [
|
|
13369
13735
|
{
|
|
13370
13736
|
"property": "title",
|
|
13371
|
-
"label": "
|
|
13737
|
+
"label": "Requirement",
|
|
13372
13738
|
"sortable": true
|
|
13373
13739
|
},
|
|
13374
13740
|
{
|
|
13375
|
-
"property": "
|
|
13376
|
-
"label": "
|
|
13377
|
-
"sortable": true
|
|
13378
|
-
|
|
13379
|
-
{
|
|
13380
|
-
"property": "title",
|
|
13381
|
-
"label": "Could Have",
|
|
13382
|
-
"sortable": true
|
|
13383
|
-
},
|
|
13384
|
-
{
|
|
13385
|
-
"property": "title",
|
|
13386
|
-
"label": "Won't Have",
|
|
13387
|
-
"sortable": true
|
|
13741
|
+
"property": "moscow",
|
|
13742
|
+
"label": "Priority",
|
|
13743
|
+
"sortable": true,
|
|
13744
|
+
"format": "badge"
|
|
13388
13745
|
}
|
|
13389
13746
|
]
|
|
13390
13747
|
},
|
|
13391
13748
|
"sort_by": {
|
|
13392
|
-
"property": "
|
|
13749
|
+
"property": "moscow",
|
|
13393
13750
|
"direction": "asc"
|
|
13394
13751
|
},
|
|
13395
13752
|
"colour_by": "type",
|
|
@@ -13940,24 +14297,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13940
14297
|
],
|
|
13941
14298
|
"slots": [
|
|
13942
14299
|
{
|
|
13943
|
-
"label": "
|
|
14300
|
+
"label": "Delivery metric",
|
|
13944
14301
|
"entityTypeId": "metric",
|
|
13945
|
-
"description": "
|
|
13946
|
-
},
|
|
13947
|
-
{
|
|
13948
|
-
"label": "Lead Time for Changes",
|
|
13949
|
-
"entityTypeId": "metric",
|
|
13950
|
-
"description": "Time from commit to production"
|
|
13951
|
-
},
|
|
13952
|
-
{
|
|
13953
|
-
"label": "Change Failure Rate",
|
|
13954
|
-
"entityTypeId": "metric",
|
|
13955
|
-
"description": "Percentage of deployments causing failures"
|
|
13956
|
-
},
|
|
13957
|
-
{
|
|
13958
|
-
"label": "Time to Restore",
|
|
13959
|
-
"entityTypeId": "metric",
|
|
13960
|
-
"description": "How long to recover from a failure"
|
|
14302
|
+
"description": "One of the four DORA software-delivery performance metrics"
|
|
13961
14303
|
}
|
|
13962
14304
|
],
|
|
13963
14305
|
"data": {
|
|
@@ -13967,7 +14309,36 @@ var UPG_FRAMEWORKS = [
|
|
|
13967
14309
|
"role": "item"
|
|
13968
14310
|
}
|
|
13969
14311
|
],
|
|
13970
|
-
"required_properties": {
|
|
14312
|
+
"required_properties": {
|
|
14313
|
+
"metric": [
|
|
14314
|
+
{
|
|
14315
|
+
"property": "dora_metric",
|
|
14316
|
+
"type": "enum",
|
|
14317
|
+
"required": true,
|
|
14318
|
+
"label": "DORA metric",
|
|
14319
|
+
"description": "Which of the four DORA metrics this measures",
|
|
14320
|
+
"enum_values": [
|
|
14321
|
+
"deployment_frequency",
|
|
14322
|
+
"lead_time_for_changes",
|
|
14323
|
+
"change_failure_rate",
|
|
14324
|
+
"time_to_restore"
|
|
14325
|
+
]
|
|
14326
|
+
},
|
|
14327
|
+
{
|
|
14328
|
+
"property": "performance_tier",
|
|
14329
|
+
"type": "enum",
|
|
14330
|
+
"required": false,
|
|
14331
|
+
"label": "Performance tier",
|
|
14332
|
+
"description": "Where this metric sits on the DORA elite-to-low benchmark",
|
|
14333
|
+
"enum_values": [
|
|
14334
|
+
"elite",
|
|
14335
|
+
"high",
|
|
14336
|
+
"medium",
|
|
14337
|
+
"low"
|
|
14338
|
+
]
|
|
14339
|
+
}
|
|
14340
|
+
]
|
|
14341
|
+
},
|
|
13971
14342
|
"computed_properties": [
|
|
13972
14343
|
{
|
|
13973
14344
|
"property": "stability_index",
|
|
@@ -14123,29 +14494,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14123
14494
|
],
|
|
14124
14495
|
"slots": [
|
|
14125
14496
|
{
|
|
14126
|
-
"label": "
|
|
14127
|
-
"entityTypeId": "metric",
|
|
14128
|
-
"description": "How do users find you?"
|
|
14129
|
-
},
|
|
14130
|
-
{
|
|
14131
|
-
"label": "Activation",
|
|
14132
|
-
"entityTypeId": "metric",
|
|
14133
|
-
"description": "Do users have a great first experience?"
|
|
14134
|
-
},
|
|
14135
|
-
{
|
|
14136
|
-
"label": "Retention",
|
|
14137
|
-
"entityTypeId": "metric",
|
|
14138
|
-
"description": "Do users come back?"
|
|
14139
|
-
},
|
|
14140
|
-
{
|
|
14141
|
-
"label": "Revenue",
|
|
14497
|
+
"label": "Lifecycle metric",
|
|
14142
14498
|
"entityTypeId": "metric",
|
|
14143
|
-
"description": "
|
|
14144
|
-
},
|
|
14145
|
-
{
|
|
14146
|
-
"label": "Referral",
|
|
14147
|
-
"entityTypeId": "metric",
|
|
14148
|
-
"description": "Do users tell others?"
|
|
14499
|
+
"description": "A metric tracking one stage of the customer lifecycle funnel"
|
|
14149
14500
|
}
|
|
14150
14501
|
],
|
|
14151
14502
|
"data": {
|
|
@@ -14155,7 +14506,24 @@ var UPG_FRAMEWORKS = [
|
|
|
14155
14506
|
"role": "item"
|
|
14156
14507
|
}
|
|
14157
14508
|
],
|
|
14158
|
-
"required_properties": {
|
|
14509
|
+
"required_properties": {
|
|
14510
|
+
"metric": [
|
|
14511
|
+
{
|
|
14512
|
+
"property": "lifecycle_stage",
|
|
14513
|
+
"type": "enum",
|
|
14514
|
+
"required": true,
|
|
14515
|
+
"label": "Lifecycle stage",
|
|
14516
|
+
"description": "Which AARRR funnel stage this metric measures",
|
|
14517
|
+
"enum_values": [
|
|
14518
|
+
"acquisition",
|
|
14519
|
+
"activation",
|
|
14520
|
+
"retention",
|
|
14521
|
+
"revenue",
|
|
14522
|
+
"referral"
|
|
14523
|
+
]
|
|
14524
|
+
}
|
|
14525
|
+
]
|
|
14526
|
+
},
|
|
14159
14527
|
"computed_properties": [
|
|
14160
14528
|
{
|
|
14161
14529
|
"property": "conversion_rate",
|
|
@@ -14167,7 +14535,39 @@ var UPG_FRAMEWORKS = [
|
|
|
14167
14535
|
]
|
|
14168
14536
|
},
|
|
14169
14537
|
"structure": {
|
|
14170
|
-
"pattern": "funnel"
|
|
14538
|
+
"pattern": "funnel",
|
|
14539
|
+
"stages": [
|
|
14540
|
+
{
|
|
14541
|
+
"id": "acquisition",
|
|
14542
|
+
"label": "Acquisition",
|
|
14543
|
+
"order": 0,
|
|
14544
|
+
"entity_type": "metric"
|
|
14545
|
+
},
|
|
14546
|
+
{
|
|
14547
|
+
"id": "activation",
|
|
14548
|
+
"label": "Activation",
|
|
14549
|
+
"order": 1,
|
|
14550
|
+
"entity_type": "metric"
|
|
14551
|
+
},
|
|
14552
|
+
{
|
|
14553
|
+
"id": "retention",
|
|
14554
|
+
"label": "Retention",
|
|
14555
|
+
"order": 2,
|
|
14556
|
+
"entity_type": "metric"
|
|
14557
|
+
},
|
|
14558
|
+
{
|
|
14559
|
+
"id": "revenue",
|
|
14560
|
+
"label": "Revenue",
|
|
14561
|
+
"order": 3,
|
|
14562
|
+
"entity_type": "metric"
|
|
14563
|
+
},
|
|
14564
|
+
{
|
|
14565
|
+
"id": "referral",
|
|
14566
|
+
"label": "Referral",
|
|
14567
|
+
"order": 4,
|
|
14568
|
+
"entity_type": "metric"
|
|
14569
|
+
}
|
|
14570
|
+
]
|
|
14171
14571
|
},
|
|
14172
14572
|
"presentation": {
|
|
14173
14573
|
"layout": {
|
|
@@ -14214,24 +14614,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14214
14614
|
],
|
|
14215
14615
|
"slots": [
|
|
14216
14616
|
{
|
|
14217
|
-
"label": "
|
|
14218
|
-
"entityTypeId": "metric",
|
|
14219
|
-
"description": "The single metric reflecting core value delivered"
|
|
14220
|
-
},
|
|
14221
|
-
{
|
|
14222
|
-
"label": "Input Metric 1",
|
|
14223
|
-
"entityTypeId": "metric",
|
|
14224
|
-
"description": "A driver metric you can directly influence"
|
|
14225
|
-
},
|
|
14226
|
-
{
|
|
14227
|
-
"label": "Input Metric 2",
|
|
14228
|
-
"entityTypeId": "metric",
|
|
14229
|
-
"description": "A driver metric you can directly influence"
|
|
14230
|
-
},
|
|
14231
|
-
{
|
|
14232
|
-
"label": "Input Metric 3",
|
|
14617
|
+
"label": "Metric",
|
|
14233
14618
|
"entityTypeId": "metric",
|
|
14234
|
-
"description": "
|
|
14619
|
+
"description": "The North Star metric or one of its 3-5 input (driver) metrics"
|
|
14235
14620
|
}
|
|
14236
14621
|
],
|
|
14237
14622
|
"data": {
|
|
@@ -14241,7 +14626,28 @@ var UPG_FRAMEWORKS = [
|
|
|
14241
14626
|
"role": "item"
|
|
14242
14627
|
}
|
|
14243
14628
|
],
|
|
14244
|
-
"required_properties": {
|
|
14629
|
+
"required_properties": {
|
|
14630
|
+
"metric": [
|
|
14631
|
+
{
|
|
14632
|
+
"property": "metric_role",
|
|
14633
|
+
"type": "enum",
|
|
14634
|
+
"required": true,
|
|
14635
|
+
"label": "Metric role",
|
|
14636
|
+
"description": "Whether this is the single North Star or a driver that feeds it",
|
|
14637
|
+
"enum_values": [
|
|
14638
|
+
"north_star",
|
|
14639
|
+
"input"
|
|
14640
|
+
]
|
|
14641
|
+
},
|
|
14642
|
+
{
|
|
14643
|
+
"property": "leverage",
|
|
14644
|
+
"type": "number",
|
|
14645
|
+
"required": false,
|
|
14646
|
+
"label": "Leverage",
|
|
14647
|
+
"description": "How strongly this input metric moves the North Star (input metrics only)"
|
|
14648
|
+
}
|
|
14649
|
+
]
|
|
14650
|
+
},
|
|
14245
14651
|
"computed_properties": [
|
|
14246
14652
|
{
|
|
14247
14653
|
"property": "nsm_impact",
|
|
@@ -14541,7 +14947,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14541
14947
|
]
|
|
14542
14948
|
},
|
|
14543
14949
|
"education": {
|
|
14544
|
-
"purpose": "Design the product itself as the primary growth driver (free tier, self-serve onboarding, in-product virality)
|
|
14950
|
+
"purpose": "Design the product itself as the primary growth driver (free tier, self-serve onboarding, in-product virality) to reduce dependence on sales-led acquisition.",
|
|
14545
14951
|
"core_question": "Can our product acquire, activate, and expand users without human intervention, and where in the loop do we still need sales?",
|
|
14546
14952
|
"when_to_use": [
|
|
14547
14953
|
"You are launching a new product, feature, or entering a new market",
|
|
@@ -14951,7 +15357,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14951
15357
|
{
|
|
14952
15358
|
"label": "Team",
|
|
14953
15359
|
"entityTypeId": "team",
|
|
14954
|
-
"description": "Team conducting the health check
|
|
15360
|
+
"description": "Team conducting the health check; all members vote anonymously on each dimension"
|
|
14955
15361
|
},
|
|
14956
15362
|
{
|
|
14957
15363
|
"label": "Retrospective",
|
|
@@ -15040,7 +15446,7 @@ var UPG_FRAMEWORKS = [
|
|
|
15040
15446
|
},
|
|
15041
15447
|
"education": {
|
|
15042
15448
|
"purpose": "Regularly assess team health across dimensions (psychological safety, autonomy, mission clarity, fun, speed, learning) to catch problems early and celebrate strengths.",
|
|
15043
|
-
"core_question": "How is the team really doing
|
|
15449
|
+
"core_question": "How is the team really doing: where do they feel strong, where do they feel stuck, and what has changed since last check?",
|
|
15044
15450
|
"when_to_use": [
|
|
15045
15451
|
"You need to improve team collaboration, clarity, or effectiveness",
|
|
15046
15452
|
"Roles and responsibilities are unclear or causing friction",
|
|
@@ -15056,7 +15462,7 @@ var UPG_FRAMEWORKS = [
|
|
|
15056
15462
|
"id": "raid-log",
|
|
15057
15463
|
"name": "RAID Log",
|
|
15058
15464
|
"version": "1.0.0",
|
|
15059
|
-
"description": "A project management register tracking Risks, Assumptions, Issues, and Dependencies
|
|
15465
|
+
"description": "A project management register tracking Risks, Assumptions, Issues, and Dependencies, the four categories most likely to derail a project if left unmanaged.",
|
|
15060
15466
|
"category": "program_mgmt",
|
|
15061
15467
|
"origin": {
|
|
15062
15468
|
"type": "practitioner",
|
|
@@ -16130,6 +16536,7 @@ var STRATEGY_OUTCOMES_PLAYBOOK = {
|
|
|
16130
16536
|
description: "Cascade vision through themes, outcomes, objectives, key results, and the bets you are making to get there.",
|
|
16131
16537
|
region: "strategy_outcomes",
|
|
16132
16538
|
is_canonical: true,
|
|
16539
|
+
related_framework_ids: ["okr-framework", "three-horizons", "north-star-metric", "metrics-tree", "wardley-map"],
|
|
16133
16540
|
target_anchor_entity: "objective",
|
|
16134
16541
|
creation_sequence: [
|
|
16135
16542
|
seqStep(
|
|
@@ -16184,6 +16591,7 @@ var USERS_NEEDS_PLAYBOOK = {
|
|
|
16184
16591
|
description: "Bootstrap personas, jobs, needs, and desired outcomes: the user side of every product graph.",
|
|
16185
16592
|
region: "users_needs",
|
|
16186
16593
|
is_canonical: true,
|
|
16594
|
+
related_framework_ids: ["persona-canvas", "empathy-map", "value-proposition-canvas", "kano-model"],
|
|
16187
16595
|
target_anchor_entity: "persona",
|
|
16188
16596
|
creation_sequence: [
|
|
16189
16597
|
seqStep(
|
|
@@ -16237,6 +16645,7 @@ var DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK = {
|
|
|
16237
16645
|
description: "Evidence-first discovery sequence: plan \u2192 recruit \u2192 observe \u2192 synthesize \u2192 insight \u2192 opportunity \u2192 hypothesis \u2192 test.",
|
|
16238
16646
|
region: "discovery_research_validation",
|
|
16239
16647
|
is_canonical: true,
|
|
16648
|
+
related_framework_ids: ["double-diamond", "opportunity-solution-tree", "build-measure-learn", "hypothesis-board"],
|
|
16240
16649
|
target_anchor_entity: "opportunity",
|
|
16241
16650
|
creation_sequence: [
|
|
16242
16651
|
seqStep(
|
|
@@ -16313,6 +16722,7 @@ var MARKET_COMPETITIVE_PLAYBOOK = {
|
|
|
16313
16722
|
description: "Map the competitive landscape: define the market, name the alternatives, read trends, find moves.",
|
|
16314
16723
|
region: "market_competitive",
|
|
16315
16724
|
is_canonical: true,
|
|
16725
|
+
related_framework_ids: ["porter-five-forces", "swot-analysis", "value-chain-analysis", "wardley-map", "bullseye-framework"],
|
|
16316
16726
|
target_anchor_entity: "competitor",
|
|
16317
16727
|
creation_sequence: [
|
|
16318
16728
|
seqStep(
|
|
@@ -16360,6 +16770,7 @@ var EXPERIENCE_DESIGN_BRAND_PLAYBOOK = {
|
|
|
16360
16770
|
description: "Journey-first design sequence: research \u2192 personas \u2192 journeys \u2192 define \u2192 ideate \u2192 prototype \u2192 test \u2192 design system.",
|
|
16361
16771
|
region: "experience_design_brand",
|
|
16362
16772
|
is_canonical: true,
|
|
16773
|
+
related_framework_ids: ["double-diamond", "atomic-design", "story-map"],
|
|
16363
16774
|
target_anchor_entity: "user_journey",
|
|
16364
16775
|
creation_sequence: [
|
|
16365
16776
|
seqStep(
|
|
@@ -16467,6 +16878,7 @@ var PRODUCT_DELIVERY_PLAYBOOK = {
|
|
|
16467
16878
|
description: "Shape what gets built: features, epics, user stories, releases, milestones, and the dependencies between them.",
|
|
16468
16879
|
region: "product_delivery",
|
|
16469
16880
|
is_canonical: true,
|
|
16881
|
+
related_framework_ids: ["story-map", "rice-scoring", "moscow", "now-next-later", "shape-up", "kano-model"],
|
|
16470
16882
|
target_anchor_entity: "feature",
|
|
16471
16883
|
creation_sequence: [
|
|
16472
16884
|
seqStep(
|
|
@@ -16530,6 +16942,7 @@ var ENGINEERING_PLATFORM_PLAYBOOK = {
|
|
|
16530
16942
|
description: "Architecture-first engineering sequence: architecture \u2192 services \u2192 data \u2192 build \u2192 test \u2192 deploy \u2192 monitor \u2192 security.",
|
|
16531
16943
|
region: "engineering_platform",
|
|
16532
16944
|
is_canonical: true,
|
|
16945
|
+
related_framework_ids: ["c4-model", "adr-log", "dora-metrics"],
|
|
16533
16946
|
target_anchor_entity: "service",
|
|
16534
16947
|
creation_sequence: [
|
|
16535
16948
|
seqStep(
|
|
@@ -16604,6 +17017,7 @@ var BUSINESS_GTM_GROWTH_PLAYBOOK = {
|
|
|
16604
17017
|
description: "Viability-first business sequence: value prop \u2192 customer \u2192 revenue \u2192 costs \u2192 unit economics \u2192 GTM \u2192 competitive advantage.",
|
|
16605
17018
|
region: "business_gtm_growth",
|
|
16606
17019
|
is_canonical: true,
|
|
17020
|
+
related_framework_ids: ["business-model-canvas", "pirate-metrics-aarrr", "north-star-metric", "product-led-growth-framework", "marketing-mix-4ps"],
|
|
16607
17021
|
target_anchor_entity: "value_proposition",
|
|
16608
17022
|
creation_sequence: [
|
|
16609
17023
|
seqStep(
|
|
@@ -16823,6 +17237,7 @@ var ANALYTICS_DATA_PLAYBOOK = {
|
|
|
16823
17237
|
description: "Bootstrap the measurement plane: sources, schemas, pipelines, metrics, dashboards, and the rules that keep them honest.",
|
|
16824
17238
|
region: "analytics_data",
|
|
16825
17239
|
is_canonical: true,
|
|
17240
|
+
related_framework_ids: ["metrics-tree", "north-star-metric", "pirate-metrics-aarrr", "dora-metrics"],
|
|
16826
17241
|
target_anchor_entity: "metric",
|
|
16827
17242
|
creation_sequence: [
|
|
16828
17243
|
seqStep(
|
|
@@ -16870,6 +17285,7 @@ var OPERATIONS_QUALITY_PLAYBOOK = {
|
|
|
16870
17285
|
description: "The operational backbone: pipelines, monitoring, incident response, security, quality gates, compliance, support. Specialised playbooks cover team rituals.",
|
|
16871
17286
|
region: "operations_quality",
|
|
16872
17287
|
is_canonical: true,
|
|
17288
|
+
related_framework_ids: ["raci-matrix", "retrospective", "team-health-check", "raid-log"],
|
|
16873
17289
|
target_anchor_entity: "incident",
|
|
16874
17290
|
creation_sequence: [
|
|
16875
17291
|
seqStep(
|
|
@@ -23507,8 +23923,275 @@ function validateExpression(expr) {
|
|
|
23507
23923
|
return null;
|
|
23508
23924
|
}
|
|
23509
23925
|
|
|
23926
|
+
// src/format/canonical.ts
|
|
23927
|
+
var import_node_crypto = require("crypto");
|
|
23928
|
+
var UPG_CANONICAL_FORMAT_VERSION = "1.0.0";
|
|
23929
|
+
var INTEGRITY_HASH_PRIMITIVE = "sha256";
|
|
23930
|
+
var INTEGRITY_DIGEST_HEX = 32;
|
|
23931
|
+
var INTEGRITY_ALGORITHM = "sha256-128";
|
|
23932
|
+
function canonicalizeOpen(value) {
|
|
23933
|
+
if (Array.isArray(value)) return value.map(canonicalizeOpen);
|
|
23934
|
+
if (value !== null && typeof value === "object") {
|
|
23935
|
+
const out = {};
|
|
23936
|
+
for (const key of Object.keys(value).sort(byCodeUnit)) {
|
|
23937
|
+
out[key] = canonicalizeOpen(value[key]);
|
|
23938
|
+
}
|
|
23939
|
+
return out;
|
|
23940
|
+
}
|
|
23941
|
+
return value;
|
|
23942
|
+
}
|
|
23943
|
+
function byCodeUnit(a, b) {
|
|
23944
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
23945
|
+
}
|
|
23946
|
+
function isEmpty(value) {
|
|
23947
|
+
if (value === null || value === void 0) return true;
|
|
23948
|
+
if (typeof value === "string") return value.length === 0;
|
|
23949
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
23950
|
+
if (typeof value === "object") return Object.keys(value).length === 0;
|
|
23951
|
+
return false;
|
|
23952
|
+
}
|
|
23953
|
+
function orderedObject(source, keyOrder, opts = {}) {
|
|
23954
|
+
const force = new Set(opts.forceKeys ?? []);
|
|
23955
|
+
const open = new Set(opts.openKeys ?? []);
|
|
23956
|
+
const out = {};
|
|
23957
|
+
const emit = (key) => {
|
|
23958
|
+
if (!(key in source)) return;
|
|
23959
|
+
const raw = source[key];
|
|
23960
|
+
if (!force.has(key) && isEmpty(raw)) return;
|
|
23961
|
+
out[key] = open.has(key) ? canonicalizeOpen(raw) : raw;
|
|
23962
|
+
};
|
|
23963
|
+
for (const key of keyOrder) emit(key);
|
|
23964
|
+
for (const key of Object.keys(source).sort(byCodeUnit)) {
|
|
23965
|
+
if (!keyOrder.includes(key)) emit(key);
|
|
23966
|
+
}
|
|
23967
|
+
return out;
|
|
23968
|
+
}
|
|
23969
|
+
function repairNodeDrift(node) {
|
|
23970
|
+
const out = { ...node };
|
|
23971
|
+
if (typeof out.properties === "string") {
|
|
23972
|
+
out.properties = parseDriftString(out.properties, "object", `node ${node.id}.properties`);
|
|
23973
|
+
}
|
|
23974
|
+
if (typeof out.tags === "string") {
|
|
23975
|
+
out.tags = parseDriftString(out.tags, "array", `node ${node.id}.tags`);
|
|
23976
|
+
}
|
|
23977
|
+
return out;
|
|
23978
|
+
}
|
|
23979
|
+
function parseDriftString(raw, expect, where) {
|
|
23980
|
+
let parsed;
|
|
23981
|
+
try {
|
|
23982
|
+
parsed = JSON.parse(raw);
|
|
23983
|
+
} catch {
|
|
23984
|
+
throw new Error(`[upg fmt] ${where} is a string that is not valid JSON: ${truncate(raw)}`);
|
|
23985
|
+
}
|
|
23986
|
+
const ok = expect === "array" ? Array.isArray(parsed) : parsed !== null && typeof parsed === "object" && !Array.isArray(parsed);
|
|
23987
|
+
if (!ok) throw new Error(`[upg fmt] ${where} is a string that does not parse to a JSON ${expect}: ${truncate(raw)}`);
|
|
23988
|
+
return parsed;
|
|
23989
|
+
}
|
|
23990
|
+
function truncate(s) {
|
|
23991
|
+
return s.length > 60 ? s.slice(0, 57) + "..." : s;
|
|
23992
|
+
}
|
|
23993
|
+
function deriveSummary(description) {
|
|
23994
|
+
if (!description) return void 0;
|
|
23995
|
+
const firstLine = description.split("\n").map((l) => l.trim()).find((l) => l.length > 0);
|
|
23996
|
+
if (!firstLine) return void 0;
|
|
23997
|
+
return firstLine.length > 200 ? firstLine.slice(0, 197) + "..." : firstLine;
|
|
23998
|
+
}
|
|
23999
|
+
function sortNodes(nodes) {
|
|
24000
|
+
return [...nodes].sort(
|
|
24001
|
+
(a, b) => byCodeUnit(a.type ?? "", b.type ?? "") || byCodeUnit(a.slug ?? a.title ?? "", b.slug ?? b.title ?? "") || byCodeUnit(a.id ?? "", b.id ?? "")
|
|
24002
|
+
);
|
|
24003
|
+
}
|
|
24004
|
+
function sortEdges(edges) {
|
|
24005
|
+
return [...edges].sort(
|
|
24006
|
+
(a, b) => byCodeUnit(a.source ?? "", b.source ?? "") || byCodeUnit(a.target ?? "", b.target ?? "") || byCodeUnit(a.type ?? "", b.type ?? "") || byCodeUnit(a.id ?? "", b.id ?? "")
|
|
24007
|
+
);
|
|
24008
|
+
}
|
|
24009
|
+
var NODE_KEY_ORDER = [
|
|
24010
|
+
"id",
|
|
24011
|
+
"type",
|
|
24012
|
+
"title",
|
|
24013
|
+
"slug",
|
|
24014
|
+
"aliases",
|
|
24015
|
+
"description",
|
|
24016
|
+
"tags",
|
|
24017
|
+
"status",
|
|
24018
|
+
"lifecycle_status",
|
|
24019
|
+
"source_id",
|
|
24020
|
+
"source_type",
|
|
24021
|
+
"mapping_confidence",
|
|
24022
|
+
"external_tool",
|
|
24023
|
+
"external_ref",
|
|
24024
|
+
"external_id",
|
|
24025
|
+
"sort_order",
|
|
24026
|
+
"properties"
|
|
24027
|
+
];
|
|
24028
|
+
var EDGE_KEY_ORDER = ["id", "source", "target", "type", "mapping_confidence"];
|
|
24029
|
+
var CROSS_EDGE_KEY_ORDER = ["id", "source", "target", "type", "source_product_id", "target_product_id", "mapping_confidence"];
|
|
24030
|
+
var PRODUCT_KEY_ORDER = ["id", "title", "description", "stage", "properties"];
|
|
24031
|
+
function canonicalNode(node) {
|
|
24032
|
+
const repaired = repairNodeDrift(node);
|
|
24033
|
+
if (Array.isArray(repaired.tags)) {
|
|
24034
|
+
repaired.tags = [...new Set(repaired.tags)].sort(byCodeUnit);
|
|
24035
|
+
}
|
|
24036
|
+
return orderedObject(repaired, NODE_KEY_ORDER, { forceKeys: ["id", "type", "title"], openKeys: ["properties"] });
|
|
24037
|
+
}
|
|
24038
|
+
function canonicalEdge(edge) {
|
|
24039
|
+
return orderedObject(edge, EDGE_KEY_ORDER, {
|
|
24040
|
+
forceKeys: ["id", "source", "target", "type"]
|
|
24041
|
+
});
|
|
24042
|
+
}
|
|
24043
|
+
function canonicalCrossEdge(edge) {
|
|
24044
|
+
return orderedObject(edge, CROSS_EDGE_KEY_ORDER, {
|
|
24045
|
+
forceKeys: ["id", "source", "target", "type"]
|
|
24046
|
+
});
|
|
24047
|
+
}
|
|
24048
|
+
function canonicalProduct(product) {
|
|
24049
|
+
return orderedObject(product, PRODUCT_KEY_ORDER, { forceKeys: ["id", "title"], openKeys: ["properties"] });
|
|
24050
|
+
}
|
|
24051
|
+
function singleBody(doc) {
|
|
24052
|
+
return {
|
|
24053
|
+
product: canonicalProduct(doc.product),
|
|
24054
|
+
nodes: sortNodes(doc.nodes ?? []).map(canonicalNode),
|
|
24055
|
+
edges: sortEdges(doc.edges ?? []).map(canonicalEdge)
|
|
24056
|
+
};
|
|
24057
|
+
}
|
|
24058
|
+
function portfolioBody(doc) {
|
|
24059
|
+
const products = [...doc.products ?? []].sort((a, b) => byCodeUnit(a.id ?? "", b.id ?? "")).map((p) => {
|
|
24060
|
+
const { nodes, edges, ...rest } = p;
|
|
24061
|
+
return {
|
|
24062
|
+
...canonicalProduct(rest),
|
|
24063
|
+
nodes: sortNodes(nodes ?? []).map(canonicalNode),
|
|
24064
|
+
edges: sortEdges(edges ?? []).map(canonicalEdge)
|
|
24065
|
+
};
|
|
24066
|
+
});
|
|
24067
|
+
return {
|
|
24068
|
+
organization: orderedObject(doc.organization, ["id", "title", "description", "logo_url", "industry"], { forceKeys: ["id", "title"] }),
|
|
24069
|
+
product_areas: [...doc.product_areas ?? []].sort((a, b) => byCodeUnit(a.id ?? "", b.id ?? "")).map((a) => orderedObject(a, ["id", "title", "description", "parent_area_id", "strategic_priority", "products"], { forceKeys: ["id", "title"] })),
|
|
24070
|
+
portfolios: [...doc.portfolios ?? []].sort((a, b) => byCodeUnit(a.id ?? "", b.id ?? "")).map((p) => orderedObject(p, ["id", "title", "description", "parent_portfolio_id", "hierarchy_model", "products"], { forceKeys: ["id", "title"] })),
|
|
24071
|
+
products,
|
|
24072
|
+
cross_edges: sortEdges(doc.cross_edges ?? []).map(canonicalCrossEdge)
|
|
24073
|
+
};
|
|
24074
|
+
}
|
|
24075
|
+
function computeBodyChecksum(doc) {
|
|
24076
|
+
const body = isPortfolio(doc) ? portfolioBody(doc) : singleBody(doc);
|
|
24077
|
+
const content = JSON.stringify(body);
|
|
24078
|
+
return (0, import_node_crypto.createHash)(INTEGRITY_HASH_PRIMITIVE).update(content).digest("hex").slice(0, INTEGRITY_DIGEST_HEX);
|
|
24079
|
+
}
|
|
24080
|
+
function isPortfolio(doc) {
|
|
24081
|
+
return doc.type === "portfolio" || "cross_edges" in doc;
|
|
24082
|
+
}
|
|
24083
|
+
function serializeCanonical(doc, opts = {}) {
|
|
24084
|
+
if (isPortfolio(doc)) return serializePortfolioWithHeader(doc, opts);
|
|
24085
|
+
return serializeSingleWithHeader(doc, opts);
|
|
24086
|
+
}
|
|
24087
|
+
function buildProvenance(doc, opts) {
|
|
24088
|
+
const source = opts.source ?? doc.source ?? { tool: "unknown" };
|
|
24089
|
+
return orderedObject(
|
|
24090
|
+
{
|
|
24091
|
+
tool: source.tool,
|
|
24092
|
+
tool_version: source.tool_version,
|
|
24093
|
+
workspace_id: source.workspace_id,
|
|
24094
|
+
exported_at: opts.exportedAt ?? doc.exported_at
|
|
24095
|
+
},
|
|
24096
|
+
["tool", "tool_version", "workspace_id", "exported_at"],
|
|
24097
|
+
{ forceKeys: ["tool"] }
|
|
24098
|
+
);
|
|
24099
|
+
}
|
|
24100
|
+
function serializeSingleWithHeader(doc, opts) {
|
|
24101
|
+
const body = singleBody(doc);
|
|
24102
|
+
const product = doc.product;
|
|
24103
|
+
const header = {
|
|
24104
|
+
format_version: UPG_CANONICAL_FORMAT_VERSION,
|
|
24105
|
+
spec_version: doc.upg_version,
|
|
24106
|
+
product: orderedObject(
|
|
24107
|
+
{ id: product.id, title: product.title, stage: product.stage },
|
|
24108
|
+
["id", "title", "stage"],
|
|
24109
|
+
{ forceKeys: ["id", "title"] }
|
|
24110
|
+
)
|
|
24111
|
+
};
|
|
24112
|
+
const summary = deriveSummary(product.description);
|
|
24113
|
+
if (summary) header.summary = summary;
|
|
24114
|
+
header.counts = { nodes: doc.nodes?.length ?? 0, edges: doc.edges?.length ?? 0 };
|
|
24115
|
+
header.provenance = buildProvenance(doc, opts);
|
|
24116
|
+
header.integrity = { algorithm: INTEGRITY_ALGORITHM, body: computeBodyChecksum(doc) };
|
|
24117
|
+
return JSON.stringify({ $upg: header, ...body }, null, 2) + "\n";
|
|
24118
|
+
}
|
|
24119
|
+
function serializePortfolioWithHeader(doc, opts) {
|
|
24120
|
+
const body = portfolioBody(doc);
|
|
24121
|
+
const org = doc.organization;
|
|
24122
|
+
const header = {
|
|
24123
|
+
format_version: UPG_CANONICAL_FORMAT_VERSION,
|
|
24124
|
+
spec_version: doc.upg_version,
|
|
24125
|
+
kind: "portfolio",
|
|
24126
|
+
organization: orderedObject(
|
|
24127
|
+
{ id: org.id, title: org.title },
|
|
24128
|
+
["id", "title"],
|
|
24129
|
+
{ forceKeys: ["id", "title"] }
|
|
24130
|
+
)
|
|
24131
|
+
};
|
|
24132
|
+
const summary = deriveSummary(org.description);
|
|
24133
|
+
if (summary) header.summary = summary;
|
|
24134
|
+
header.counts = {
|
|
24135
|
+
products: doc.products?.length ?? 0,
|
|
24136
|
+
product_areas: doc.product_areas?.length ?? 0,
|
|
24137
|
+
portfolios: doc.portfolios?.length ?? 0,
|
|
24138
|
+
cross_edges: doc.cross_edges?.length ?? 0
|
|
24139
|
+
};
|
|
24140
|
+
header.provenance = buildProvenance(doc, opts);
|
|
24141
|
+
header.integrity = { algorithm: INTEGRITY_ALGORITHM, body: computeBodyChecksum(doc) };
|
|
24142
|
+
return JSON.stringify({ $upg: header, ...body }, null, 2) + "\n";
|
|
24143
|
+
}
|
|
24144
|
+
function parseUpg(text) {
|
|
24145
|
+
return normalizeDocument(JSON.parse(text));
|
|
24146
|
+
}
|
|
24147
|
+
function normalizeDocument(obj) {
|
|
24148
|
+
const raw = obj;
|
|
24149
|
+
const header = raw.$upg;
|
|
24150
|
+
const upg_version = header?.spec_version ?? raw.upg_version;
|
|
24151
|
+
const provenance = header?.provenance;
|
|
24152
|
+
const exported_at = provenance?.exported_at ?? raw.exported_at;
|
|
24153
|
+
const source = provenance ? { tool: provenance.tool, tool_version: provenance.tool_version, workspace_id: provenance.workspace_id } : raw.source;
|
|
24154
|
+
const _integrity = header ? void 0 : raw._integrity;
|
|
24155
|
+
const isPortfolioDoc = raw.type === "portfolio" || header?.kind === "portfolio" || "cross_edges" in raw;
|
|
24156
|
+
if (isPortfolioDoc) {
|
|
24157
|
+
const out2 = {
|
|
24158
|
+
upg_version,
|
|
24159
|
+
type: "portfolio",
|
|
24160
|
+
exported_at: exported_at ?? "",
|
|
24161
|
+
source: source ?? { tool: "unknown" },
|
|
24162
|
+
organization: raw.organization,
|
|
24163
|
+
product_areas: raw.product_areas ?? [],
|
|
24164
|
+
portfolios: raw.portfolios ?? [],
|
|
24165
|
+
products: (raw.products ?? []).map((p) => ({
|
|
24166
|
+
...p,
|
|
24167
|
+
nodes: (p.nodes ?? []).map((n) => repairNodeDrift(n)),
|
|
24168
|
+
edges: p.edges ?? []
|
|
24169
|
+
})),
|
|
24170
|
+
cross_edges: raw.cross_edges ?? []
|
|
24171
|
+
};
|
|
24172
|
+
return out2;
|
|
24173
|
+
}
|
|
24174
|
+
const out = {
|
|
24175
|
+
upg_version,
|
|
24176
|
+
exported_at: exported_at ?? "",
|
|
24177
|
+
source: source ?? { tool: "unknown" },
|
|
24178
|
+
product: raw.product,
|
|
24179
|
+
nodes: (raw.nodes ?? []).map((n) => repairNodeDrift(n)),
|
|
24180
|
+
edges: raw.edges ?? []
|
|
24181
|
+
};
|
|
24182
|
+
if (_integrity) out._integrity = _integrity;
|
|
24183
|
+
return out;
|
|
24184
|
+
}
|
|
24185
|
+
function formatUpgText(text, opts = {}) {
|
|
24186
|
+
return serializeCanonical(parseUpg(text), opts);
|
|
24187
|
+
}
|
|
24188
|
+
function isCanonical(text) {
|
|
24189
|
+
const parsed = parseUpg(text);
|
|
24190
|
+
return text === serializeCanonical(parsed);
|
|
24191
|
+
}
|
|
24192
|
+
|
|
23510
24193
|
// src/index.ts
|
|
23511
|
-
var UPG_VERSION = "0.
|
|
24194
|
+
var UPG_VERSION = "0.8.0";
|
|
23512
24195
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
23513
24196
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
23514
24197
|
var UPG_TYPES = getTypes();
|
|
@@ -23596,12 +24279,14 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
23596
24279
|
OPERATIONS_TEAM_RITUALS_PLAYBOOK,
|
|
23597
24280
|
PRODUCT_DELIVERY_PLAYBOOK,
|
|
23598
24281
|
PRODUCT_FEEDBACK_SYNTHESIS_PLAYBOOK,
|
|
24282
|
+
PROPERTY_SCALE_MAP,
|
|
23599
24283
|
REFLECT_MODES,
|
|
23600
24284
|
STRATEGY_OUTCOMES_PLAYBOOK,
|
|
23601
24285
|
UPG_ACTIVE_TYPES,
|
|
23602
24286
|
UPG_ANTI_PATTERNS,
|
|
23603
24287
|
UPG_APPROACHES,
|
|
23604
24288
|
UPG_APPROACHES_BY_ID,
|
|
24289
|
+
UPG_CANONICAL_FORMAT_VERSION,
|
|
23605
24290
|
UPG_CONTAINMENT_FREE_TYPES,
|
|
23606
24291
|
UPG_COUNT_BENCHMARKS,
|
|
23607
24292
|
UPG_CROSS_EDGE_TYPES,
|
|
@@ -23665,8 +24350,10 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
23665
24350
|
coerceProductStage,
|
|
23666
24351
|
collectSlugsForType,
|
|
23667
24352
|
compareVersions,
|
|
24353
|
+
computeBodyChecksum,
|
|
23668
24354
|
evaluateAntiPatterns,
|
|
23669
24355
|
findInvalidStatusMigrationTargets,
|
|
24356
|
+
formatUpgText,
|
|
23670
24357
|
generateSlug,
|
|
23671
24358
|
getAnchorEntity,
|
|
23672
24359
|
getAntiPatternById,
|
|
@@ -23693,6 +24380,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
23693
24380
|
getMigrationMap,
|
|
23694
24381
|
getPlaybookById,
|
|
23695
24382
|
getPlaybooksForRegion,
|
|
24383
|
+
getPropertiesForScale,
|
|
23696
24384
|
getPropertyDefaultScale,
|
|
23697
24385
|
getPropertyMigrations,
|
|
23698
24386
|
getPropertySchema,
|
|
@@ -23709,6 +24397,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
23709
24397
|
getValidChildren,
|
|
23710
24398
|
getVisibleTypes,
|
|
23711
24399
|
hasStatusMigration,
|
|
24400
|
+
isCanonical,
|
|
23712
24401
|
isCanonicalProductStage,
|
|
23713
24402
|
isContainmentFreeType,
|
|
23714
24403
|
isDeprecatedType,
|
|
@@ -23719,6 +24408,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
23719
24408
|
isLifecycleFreeType,
|
|
23720
24409
|
isLifecyclePlannedType,
|
|
23721
24410
|
isPolymorphicEdge,
|
|
24411
|
+
isPortfolio,
|
|
23722
24412
|
isRegisteredPolymorphicEdge,
|
|
23723
24413
|
isSubSequenceStep,
|
|
23724
24414
|
isUPGDocument,
|
|
@@ -23728,6 +24418,8 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
23728
24418
|
migrateNodeProperties,
|
|
23729
24419
|
migrateProductStage,
|
|
23730
24420
|
migrateStatusValue,
|
|
24421
|
+
normalizeDocument,
|
|
24422
|
+
parseUpg,
|
|
23731
24423
|
pickCanonicalEdge,
|
|
23732
24424
|
resolveAllEdges,
|
|
23733
24425
|
resolveContainmentEdge,
|
|
@@ -23735,6 +24427,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
23735
24427
|
resolveLabel,
|
|
23736
24428
|
resolveSlugCollision,
|
|
23737
24429
|
rotateSlug,
|
|
24430
|
+
serializeCanonical,
|
|
23738
24431
|
validateProductStageStrict,
|
|
23739
24432
|
validateUPGDocument,
|
|
23740
24433
|
validateUPGFramework,
|