@unified-product-graph/core 0.8.1 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/index.cjs +1252 -245
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +147 -22
- package/dist/index.d.ts +147 -22
- package/dist/index.js +1251 -245
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -104,6 +104,7 @@ __export(index_exports, {
|
|
|
104
104
|
collectSlugsForType: () => collectSlugsForType,
|
|
105
105
|
compareVersions: () => compareVersions,
|
|
106
106
|
computeBodyChecksum: () => computeBodyChecksum,
|
|
107
|
+
edgeCarriesProperties: () => edgeCarriesProperties,
|
|
107
108
|
evaluateAntiPatterns: () => evaluateAntiPatterns,
|
|
108
109
|
findInvalidStatusMigrationTargets: () => findInvalidStatusMigrationTargets,
|
|
109
110
|
formatUpgText: () => formatUpgText,
|
|
@@ -676,8 +677,8 @@ var UPG_DOMAINS = [
|
|
|
676
677
|
{
|
|
677
678
|
id: "workspace",
|
|
678
679
|
label: "Workspace",
|
|
679
|
-
description: "Spatial thinking spaces for arranging entities, debating decisions, and committing to the graph. Workspaces are transient canvases that sit alongside all other domains, letting you compose and explore relationships before they become permanent graph structure.",
|
|
680
|
-
types: ["workspace"]
|
|
680
|
+
description: "Spatial thinking spaces for arranging entities, debating decisions, and committing to the graph. Workspaces are transient canvases that sit alongside all other domains, letting you compose and explore relationships before they become permanent graph structure. A framework exercise is a structured workspace: one run of a framework (MoSCoW, RICE, Kano, \u2026) applied to a chosen set of entities, with each entity's result recorded on the exercise-to-entity edge rather than the entity itself.",
|
|
681
|
+
types: ["workspace", "framework_exercise"]
|
|
681
682
|
}
|
|
682
683
|
];
|
|
683
684
|
var UPG_ENTITY_TO_DOMAIN = Object.freeze(
|
|
@@ -1103,7 +1104,8 @@ var UPG_ENTITY_META = [
|
|
|
1103
1104
|
{ name: "integration_partner", type_id: "ent_311", maturity: "stable", since: "0.1.0" },
|
|
1104
1105
|
{ name: "partner_revenue_share", type_id: "ent_312", maturity: "stable", since: "0.1.0" },
|
|
1105
1106
|
// ── Workspace ──
|
|
1106
|
-
{ name: "workspace", type_id: "ent_328", maturity: "proposed", since: "0.2.0" }
|
|
1107
|
+
{ name: "workspace", type_id: "ent_328", maturity: "proposed", since: "0.2.0" },
|
|
1108
|
+
{ name: "framework_exercise", type_id: "ent_350", maturity: "proposed", since: "0.8.4" }
|
|
1107
1109
|
];
|
|
1108
1110
|
var UPG_ENTITY_META_BY_NAME = new Map(
|
|
1109
1111
|
UPG_ENTITY_META.map((m) => [m.name, m])
|
|
@@ -1136,7 +1138,7 @@ var UPG_EDGE_CATALOG = {
|
|
|
1136
1138
|
// product → persona is the most fundamental relationship in the
|
|
1137
1139
|
// user domain ("who is this product for?") and was the only way to
|
|
1138
1140
|
// anchor a fresh persona to its product before this edge existed. Without
|
|
1139
|
-
// it, the natural agent path through `/upg-persona` produced an orphan
|
|
1141
|
+
// it, the natural agent path through `/upg-new-persona` produced an orphan
|
|
1140
1142
|
// persona only attached laterally via `ideal_customer_profile_maps_to_persona`
|
|
1141
1143
|
// or `positioning_resonates_with_persona`. Semantic, not hierarchy: a
|
|
1142
1144
|
// product doesn't "contain" personas; it targets them.
|
|
@@ -2256,6 +2258,18 @@ var UPG_EDGE_CATALOG = {
|
|
|
2256
2258
|
// universal across the DDD type family. Verbs follow DDD literature:
|
|
2257
2259
|
// aggregate belongs_to context, context contains aggregates.
|
|
2258
2260
|
node_belongs_to_bounded_context: { forward_verb: "belongs_to", reverse_verb: "contains", classification: "cross-domain", source_type: "node", target_type: "bounded_context" },
|
|
2261
|
+
// ── Cross-domain: Framework exercises ────────────────────────────────────────
|
|
2262
|
+
// A framework_exercise is one run of a framework (MoSCoW, RICE, Kano, …) over a
|
|
2263
|
+
// set of entities. It `includes` each entity it touches; the framework's
|
|
2264
|
+
// per-entity result — a MoSCoW bucket, a RICE score, a canvas slot, a funnel
|
|
2265
|
+
// stage — rides on this edge's `properties`, NOT on the entity node. A value
|
|
2266
|
+
// that exists only within a specific exercise is a fact about the relationship,
|
|
2267
|
+
// not the entity, so it lives on the edge (same principle as owner-as-edge).
|
|
2268
|
+
// Polymorphic (`target_type: 'node'`): an exercise can include any entity type,
|
|
2269
|
+
// which closes the feature-only limitation structurally. `carries_properties`
|
|
2270
|
+
// opts this edge into the gated edge-property model. See ADR
|
|
2271
|
+
// 2026-06-02-framework-exercises.
|
|
2272
|
+
framework_exercise_includes_node: { forward_verb: "includes", reverse_verb: "included_in", classification: "cross-domain", source_type: "framework_exercise", target_type: "node", carries_properties: true },
|
|
2259
2273
|
// ── New edges replacing deleted string properties ────────────────────
|
|
2260
2274
|
// Marketing
|
|
2261
2275
|
marketing_strategy_pursues_outcome: { forward_verb: "pursues", reverse_verb: "pursued_by", classification: "cross-domain", source_type: "marketing_strategy", target_type: "outcome" },
|
|
@@ -2351,6 +2365,13 @@ var UPG_EDGE_CATALOG = {
|
|
|
2351
2365
|
// release strategy to the concrete deployments it governs.
|
|
2352
2366
|
incident_affects_feature: { forward_verb: "affects", reverse_verb: "affected_by", classification: "cross-domain", source_type: "incident", target_type: "feature" },
|
|
2353
2367
|
release_strategy_used_by_deployment: { forward_verb: "used_by", reverse_verb: "uses", classification: "cross-domain", source_type: "release_strategy", target_type: "deployment" },
|
|
2368
|
+
// v0.8.2 (UPG-615): ITIL/ITSM incident management explicitly links an incident
|
|
2369
|
+
// to the customer-facing support tickets/cases it spawns — when a service
|
|
2370
|
+
// breaks, customers raise tickets; the incident is the cause, the ticket the
|
|
2371
|
+
// effect. Closes the otherwise-unmediated "Customer Support" island in
|
|
2372
|
+
// `playbook:operations-quality`, binding `support_ticket` to the incident/ops
|
|
2373
|
+
// spine. Source: ITIL v4 incident management; DORA/SRE customer-facing impact.
|
|
2374
|
+
incident_generates_support_ticket: { forward_verb: "generates", reverse_verb: "generated_by", classification: "cross-domain", source_type: "incident", target_type: "support_ticket" },
|
|
2354
2375
|
// Cluster C: User Research linkage matrix.
|
|
2355
2376
|
// research_study → {participant, research_question, survey_response,
|
|
2356
2377
|
// interview_guide} containment edges already exist (49/49 in Wave 4).
|
|
@@ -2878,7 +2899,9 @@ var UPG_POLYMORPHIC_EDGE_KEYS = [
|
|
|
2878
2899
|
"node_owned_by_department",
|
|
2879
2900
|
"node_owned_by_person",
|
|
2880
2901
|
// Universal architecture references
|
|
2881
|
-
"node_belongs_to_bounded_context"
|
|
2902
|
+
"node_belongs_to_bounded_context",
|
|
2903
|
+
// Framework exercises (an exercise can include any entity type)
|
|
2904
|
+
"framework_exercise_includes_node"
|
|
2882
2905
|
];
|
|
2883
2906
|
var _POLY_KEY_SET = new Set(UPG_POLYMORPHIC_EDGE_KEYS);
|
|
2884
2907
|
function isPolymorphicEdge(key) {
|
|
@@ -2888,6 +2911,10 @@ function isPolymorphicEdge(key) {
|
|
|
2888
2911
|
function isRegisteredPolymorphicEdge(key) {
|
|
2889
2912
|
return _POLY_KEY_SET.has(key);
|
|
2890
2913
|
}
|
|
2914
|
+
function edgeCarriesProperties(type) {
|
|
2915
|
+
const def = UPG_EDGE_CATALOG[type];
|
|
2916
|
+
return def?.carries_properties === true;
|
|
2917
|
+
}
|
|
2891
2918
|
|
|
2892
2919
|
// src/catalog/legacy-product-stages.ts
|
|
2893
2920
|
var LEGACY_PRODUCT_STAGES = Object.freeze({
|
|
@@ -3539,7 +3566,13 @@ function canBeChildOf(childType, parentType) {
|
|
|
3539
3566
|
return getValidChildren(parentType).includes(childType);
|
|
3540
3567
|
}
|
|
3541
3568
|
var UPG_CONTAINMENT_FREE_TYPES = /* @__PURE__ */ new Set([
|
|
3542
|
-
"person"
|
|
3569
|
+
"person",
|
|
3570
|
+
// A framework_exercise has no structural parent: it anchors to the entities
|
|
3571
|
+
// it scores via the `framework_exercise_includes_node` edge, not by
|
|
3572
|
+
// containment. Modelling it as a product child would force a containment edge
|
|
3573
|
+
// and read against the whole point of the exercise model (relational, not
|
|
3574
|
+
// hierarchical). Same posture as `person`. See ADR 2026-06-02-framework-exercises.
|
|
3575
|
+
"framework_exercise"
|
|
3543
3576
|
]);
|
|
3544
3577
|
function isContainmentFreeType(entityType) {
|
|
3545
3578
|
return UPG_CONTAINMENT_FREE_TYPES.has(entityType);
|
|
@@ -5841,6 +5874,31 @@ var TEMPLATE_LIFECYCLES = [
|
|
|
5841
5874
|
// ── Phase B: SALES_DEAL (qualified → proposal → negotiation → won/lost) ─────
|
|
5842
5875
|
fromTemplate("deal", SALES_DEAL_TEMPLATE)
|
|
5843
5876
|
];
|
|
5877
|
+
var FRAMEWORK_EXERCISE_LIFECYCLE = {
|
|
5878
|
+
entity_type: "framework_exercise",
|
|
5879
|
+
initial_phase: "draft",
|
|
5880
|
+
terminal_phases: ["archived"],
|
|
5881
|
+
phases: [
|
|
5882
|
+
{
|
|
5883
|
+
id: "draft",
|
|
5884
|
+
label: "Draft",
|
|
5885
|
+
description: "The exercise has been created and entities pulled into scope, but the framework's inputs have not all been filled in yet.",
|
|
5886
|
+
transitions_to: ["active", "archived"]
|
|
5887
|
+
},
|
|
5888
|
+
{
|
|
5889
|
+
id: "active",
|
|
5890
|
+
label: "Active",
|
|
5891
|
+
description: "The current, authoritative run of its framework. Its include edges carry the live results consumers read, rank, and render by.",
|
|
5892
|
+
transitions_to: ["archived"]
|
|
5893
|
+
},
|
|
5894
|
+
{
|
|
5895
|
+
id: "archived",
|
|
5896
|
+
label: "Archived",
|
|
5897
|
+
description: "A past run, retained for provenance. Still queryable but superseded by a newer exercise and hidden from default views. Can be revived to active.",
|
|
5898
|
+
transitions_to: ["active"]
|
|
5899
|
+
}
|
|
5900
|
+
]
|
|
5901
|
+
};
|
|
5844
5902
|
var UPG_LIFECYCLES = [
|
|
5845
5903
|
// Product (root)
|
|
5846
5904
|
PRODUCT_LIFECYCLE,
|
|
@@ -5942,6 +6000,8 @@ var UPG_LIFECYCLES = [
|
|
|
5942
6000
|
// Product & Growth
|
|
5943
6001
|
VARIANT_LIFECYCLE,
|
|
5944
6002
|
GROWTH_CAMPAIGN_LIFECYCLE,
|
|
6003
|
+
// Workspace
|
|
6004
|
+
FRAMEWORK_EXERCISE_LIFECYCLE,
|
|
5945
6005
|
// ── Template-generated lifecycles ─────────────────────────────────
|
|
5946
6006
|
...TEMPLATE_LIFECYCLES
|
|
5947
6007
|
];
|
|
@@ -10131,6 +10191,11 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
10131
10191
|
},
|
|
10132
10192
|
methodology: { type: "string", description: "Forecasting methodology used" }
|
|
10133
10193
|
},
|
|
10194
|
+
// FrameworkExerciseProperties: Framework exercise: one run of a framework over a set of entities.
|
|
10195
|
+
framework_exercise: {
|
|
10196
|
+
framework_id: { type: "string", description: "Which framework this exercise runs: a framework id (e.g. 'moscow', 'rice-scoring', 'kano-model'). Resolves against the framework catalog." },
|
|
10197
|
+
inputs_snapshot: { type: "object", description: "Optional frozen copy of the framework's input spec at apply time, so a historical exercise still renders correctly if the framework definition later evolves (inputs added, removed, or rescaled)." }
|
|
10198
|
+
},
|
|
10134
10199
|
// FunnelProperties: Funnel entity.
|
|
10135
10200
|
funnel: {
|
|
10136
10201
|
funnel_type: { type: "string", enum: ["acquisition", "activation", "retention", "revenue", "referral", "custom"], description: "Which stage of the customer lifecycle this funnel measures" },
|
|
@@ -12158,6 +12223,9 @@ var UPG_FRAMEWORKS = [
|
|
|
12158
12223
|
},
|
|
12159
12224
|
{
|
|
12160
12225
|
"id": "value-proposition-canvas",
|
|
12226
|
+
"approach_ids": [
|
|
12227
|
+
"trace"
|
|
12228
|
+
],
|
|
12161
12229
|
"name": "Value Proposition Canvas",
|
|
12162
12230
|
"version": "1.0.0",
|
|
12163
12231
|
"description": "Map customer jobs, pains, and gains on one side, then align product features, pain relievers, and gain creators on the other to achieve product-market fit.",
|
|
@@ -12262,6 +12330,9 @@ var UPG_FRAMEWORKS = [
|
|
|
12262
12330
|
},
|
|
12263
12331
|
{
|
|
12264
12332
|
"id": "persona-canvas",
|
|
12333
|
+
"approach_ids": [
|
|
12334
|
+
"trace"
|
|
12335
|
+
],
|
|
12265
12336
|
"name": "Persona Canvas",
|
|
12266
12337
|
"version": "1.0.0",
|
|
12267
12338
|
"description": "Demographics, goals, frustrations, JTBD: a structured template for creating research-backed personas.",
|
|
@@ -12374,6 +12445,9 @@ var UPG_FRAMEWORKS = [
|
|
|
12374
12445
|
},
|
|
12375
12446
|
{
|
|
12376
12447
|
"id": "empathy-map",
|
|
12448
|
+
"approach_ids": [
|
|
12449
|
+
"trace"
|
|
12450
|
+
],
|
|
12377
12451
|
"name": "Empathy Map",
|
|
12378
12452
|
"version": "1.0.0",
|
|
12379
12453
|
"description": "Visualise what a user says, thinks, does, and feels to build deeper empathy and uncover hidden needs.",
|
|
@@ -12534,6 +12608,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12534
12608
|
"property": "evolution_stage",
|
|
12535
12609
|
"type": "enum",
|
|
12536
12610
|
"required": true,
|
|
12611
|
+
"scope": "framework",
|
|
12537
12612
|
"label": "Evolution Stage",
|
|
12538
12613
|
"description": "Where this component sits on the evolution axis",
|
|
12539
12614
|
"enum_values": [
|
|
@@ -12547,6 +12622,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12547
12622
|
"property": "visibility",
|
|
12548
12623
|
"type": "number",
|
|
12549
12624
|
"required": true,
|
|
12625
|
+
"scope": "framework",
|
|
12550
12626
|
"label": "Visibility",
|
|
12551
12627
|
"description": "Y-axis position (0=infrastructure, 1=anchor/user)"
|
|
12552
12628
|
}
|
|
@@ -12556,6 +12632,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12556
12632
|
"property": "evolution_stage",
|
|
12557
12633
|
"type": "enum",
|
|
12558
12634
|
"required": true,
|
|
12635
|
+
"scope": "framework",
|
|
12559
12636
|
"label": "Evolution Stage",
|
|
12560
12637
|
"description": "Where this component sits on the evolution axis",
|
|
12561
12638
|
"enum_values": [
|
|
@@ -12569,6 +12646,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12569
12646
|
"property": "visibility",
|
|
12570
12647
|
"type": "number",
|
|
12571
12648
|
"required": true,
|
|
12649
|
+
"scope": "framework",
|
|
12572
12650
|
"label": "Visibility",
|
|
12573
12651
|
"description": "Y-axis position (0=infrastructure, 1=anchor/user)"
|
|
12574
12652
|
}
|
|
@@ -12578,6 +12656,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12578
12656
|
"property": "evolution_stage",
|
|
12579
12657
|
"type": "enum",
|
|
12580
12658
|
"required": true,
|
|
12659
|
+
"scope": "framework",
|
|
12581
12660
|
"label": "Evolution Stage",
|
|
12582
12661
|
"description": "Where this component sits on the evolution axis",
|
|
12583
12662
|
"enum_values": [
|
|
@@ -12591,6 +12670,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12591
12670
|
"property": "visibility",
|
|
12592
12671
|
"type": "number",
|
|
12593
12672
|
"required": true,
|
|
12673
|
+
"scope": "framework",
|
|
12594
12674
|
"label": "Visibility",
|
|
12595
12675
|
"description": "Y-axis position (0=infrastructure, 1=anchor/user)"
|
|
12596
12676
|
}
|
|
@@ -12600,6 +12680,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12600
12680
|
"property": "evolution_stage",
|
|
12601
12681
|
"type": "enum",
|
|
12602
12682
|
"required": true,
|
|
12683
|
+
"scope": "framework",
|
|
12603
12684
|
"label": "Evolution Stage",
|
|
12604
12685
|
"description": 'Where this component sits on the evolution axis (need anchor is usually at "product" or "commodity")',
|
|
12605
12686
|
"enum_values": [
|
|
@@ -12613,6 +12694,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12613
12694
|
"property": "visibility",
|
|
12614
12695
|
"type": "number",
|
|
12615
12696
|
"required": true,
|
|
12697
|
+
"scope": "framework",
|
|
12616
12698
|
"label": "Visibility",
|
|
12617
12699
|
"description": "Y-axis position (0=infrastructure, 1=anchor/user); needs sit at 1.0"
|
|
12618
12700
|
}
|
|
@@ -12653,6 +12735,9 @@ var UPG_FRAMEWORKS = [
|
|
|
12653
12735
|
},
|
|
12654
12736
|
{
|
|
12655
12737
|
"id": "business-model-canvas",
|
|
12738
|
+
"approach_ids": [
|
|
12739
|
+
"plan"
|
|
12740
|
+
],
|
|
12656
12741
|
"name": "Business Model Canvas",
|
|
12657
12742
|
"version": "1.0.0",
|
|
12658
12743
|
"description": "Nine building blocks that describe how an organisation creates, delivers, and captures value.",
|
|
@@ -12792,6 +12877,9 @@ var UPG_FRAMEWORKS = [
|
|
|
12792
12877
|
},
|
|
12793
12878
|
{
|
|
12794
12879
|
"id": "porter-five-forces",
|
|
12880
|
+
"approach_ids": [
|
|
12881
|
+
"inspect"
|
|
12882
|
+
],
|
|
12795
12883
|
"name": "Porter Five Forces",
|
|
12796
12884
|
"version": "1.0.0",
|
|
12797
12885
|
"description": "Analyse industry competitiveness through five forces: rivalry, new entrants, substitutes, buyer power, and supplier power.",
|
|
@@ -12881,6 +12969,9 @@ var UPG_FRAMEWORKS = [
|
|
|
12881
12969
|
},
|
|
12882
12970
|
{
|
|
12883
12971
|
"id": "swot-analysis",
|
|
12972
|
+
"approach_ids": [
|
|
12973
|
+
"inspect"
|
|
12974
|
+
],
|
|
12884
12975
|
"name": "SWOT Analysis",
|
|
12885
12976
|
"version": "1.0.0",
|
|
12886
12977
|
"description": "Map Strengths, Weaknesses, Opportunities, and Threats in a 2x2 grid. Internal vs external, helpful vs harmful.",
|
|
@@ -13207,6 +13298,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13207
13298
|
"type": "assessment",
|
|
13208
13299
|
"scale_id": "reach_5",
|
|
13209
13300
|
"required": true,
|
|
13301
|
+
"scope": "framework",
|
|
13210
13302
|
"label": "Reach",
|
|
13211
13303
|
"description": "How many users will this impact per quarter?"
|
|
13212
13304
|
},
|
|
@@ -13215,6 +13307,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13215
13307
|
"type": "assessment",
|
|
13216
13308
|
"scale_id": "impact_5",
|
|
13217
13309
|
"required": true,
|
|
13310
|
+
"scope": "framework",
|
|
13218
13311
|
"label": "Impact",
|
|
13219
13312
|
"description": "How much will this impact each user, on the impact scale?"
|
|
13220
13313
|
},
|
|
@@ -13223,6 +13316,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13223
13316
|
"type": "assessment",
|
|
13224
13317
|
"scale_id": "confidence_5",
|
|
13225
13318
|
"required": true,
|
|
13319
|
+
"scope": "framework",
|
|
13226
13320
|
"label": "Confidence",
|
|
13227
13321
|
"description": "How confident are you in the reach, impact, and effort estimates?"
|
|
13228
13322
|
},
|
|
@@ -13231,6 +13325,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13231
13325
|
"type": "assessment",
|
|
13232
13326
|
"scale_id": "effort_5",
|
|
13233
13327
|
"required": true,
|
|
13328
|
+
"scope": "framework",
|
|
13234
13329
|
"label": "Effort",
|
|
13235
13330
|
"description": "How much work is required to build and ship this, on the effort scale?"
|
|
13236
13331
|
}
|
|
@@ -13317,6 +13412,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13317
13412
|
},
|
|
13318
13413
|
{
|
|
13319
13414
|
"id": "build-measure-learn",
|
|
13415
|
+
"approach_ids": [
|
|
13416
|
+
"reflect"
|
|
13417
|
+
],
|
|
13320
13418
|
"name": "Build-Measure-Learn",
|
|
13321
13419
|
"version": "1.0.0",
|
|
13322
13420
|
"description": "The core Lean Startup feedback loop: build a minimum viable product, measure its impact with actionable metrics, and learn whether to pivot or persevere.",
|
|
@@ -13452,6 +13550,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13452
13550
|
"property": "functional_response",
|
|
13453
13551
|
"type": "enum",
|
|
13454
13552
|
"required": true,
|
|
13553
|
+
"scope": "framework",
|
|
13455
13554
|
"label": "Functional Response",
|
|
13456
13555
|
"description": "How users feel when the feature IS present",
|
|
13457
13556
|
"enum_values": [
|
|
@@ -13466,6 +13565,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13466
13565
|
"property": "dysfunctional_response",
|
|
13467
13566
|
"type": "enum",
|
|
13468
13567
|
"required": true,
|
|
13568
|
+
"scope": "framework",
|
|
13469
13569
|
"label": "Dysfunctional Response",
|
|
13470
13570
|
"description": "How users feel when the feature IS NOT present",
|
|
13471
13571
|
"enum_values": [
|
|
@@ -13480,6 +13580,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13480
13580
|
"property": "delighter_count",
|
|
13481
13581
|
"type": "number",
|
|
13482
13582
|
"required": false,
|
|
13583
|
+
"scope": "framework",
|
|
13483
13584
|
"label": "Delighter classifications",
|
|
13484
13585
|
"description": "Count of survey responses classifying this feature as a delighter (attractive)"
|
|
13485
13586
|
},
|
|
@@ -13487,6 +13588,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13487
13588
|
"property": "performance_count",
|
|
13488
13589
|
"type": "number",
|
|
13489
13590
|
"required": false,
|
|
13591
|
+
"scope": "framework",
|
|
13490
13592
|
"label": "Performance classifications",
|
|
13491
13593
|
"description": "Count of survey responses classifying this feature as performance (one-dimensional)"
|
|
13492
13594
|
},
|
|
@@ -13494,6 +13596,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13494
13596
|
"property": "must_be_count",
|
|
13495
13597
|
"type": "number",
|
|
13496
13598
|
"required": false,
|
|
13599
|
+
"scope": "framework",
|
|
13497
13600
|
"label": "Must-be classifications",
|
|
13498
13601
|
"description": "Count of survey responses classifying this feature as must-be (basic)"
|
|
13499
13602
|
},
|
|
@@ -13501,6 +13604,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13501
13604
|
"property": "indifferent_count",
|
|
13502
13605
|
"type": "number",
|
|
13503
13606
|
"required": false,
|
|
13607
|
+
"scope": "framework",
|
|
13504
13608
|
"label": "Indifferent classifications",
|
|
13505
13609
|
"description": "Count of survey responses classifying this feature as indifferent"
|
|
13506
13610
|
}
|
|
@@ -13693,6 +13797,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13693
13797
|
"property": "moscow",
|
|
13694
13798
|
"type": "enum",
|
|
13695
13799
|
"required": true,
|
|
13800
|
+
"scope": "framework",
|
|
13696
13801
|
"label": "MoSCoW priority",
|
|
13697
13802
|
"description": "Which scope bucket this requirement falls into for the current release",
|
|
13698
13803
|
"enum_values": [
|
|
@@ -13703,16 +13808,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13703
13808
|
]
|
|
13704
13809
|
}
|
|
13705
13810
|
]
|
|
13706
|
-
}
|
|
13707
|
-
"computed_properties": [
|
|
13708
|
-
{
|
|
13709
|
-
"property": "must_have_ratio",
|
|
13710
|
-
"expression": "must_count / total_count",
|
|
13711
|
-
"entity_type": "feature",
|
|
13712
|
-
"label": "Must-have Ratio",
|
|
13713
|
-
"format": "percentage"
|
|
13714
|
-
}
|
|
13715
|
-
]
|
|
13811
|
+
}
|
|
13716
13812
|
},
|
|
13717
13813
|
"structure": {
|
|
13718
13814
|
"pattern": "table"
|
|
@@ -13876,6 +13972,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13876
13972
|
},
|
|
13877
13973
|
{
|
|
13878
13974
|
"id": "c4-model",
|
|
13975
|
+
"approach_ids": [
|
|
13976
|
+
"trace"
|
|
13977
|
+
],
|
|
13879
13978
|
"name": "C4 Model",
|
|
13880
13979
|
"version": "1.0.0",
|
|
13881
13980
|
"description": "Visualise software architecture at four levels of abstraction: System Context, Container, Component, and Code. Each level zooms in to reveal more detail.",
|
|
@@ -13968,6 +14067,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13968
14067
|
},
|
|
13969
14068
|
{
|
|
13970
14069
|
"id": "adr-log",
|
|
14070
|
+
"approach_ids": [
|
|
14071
|
+
"inspect"
|
|
14072
|
+
],
|
|
13971
14073
|
"name": "ADR Log",
|
|
13972
14074
|
"version": "1.0.0",
|
|
13973
14075
|
"description": "Architecture Decision Records: log decisions with context, options, and rationale.",
|
|
@@ -14081,6 +14183,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14081
14183
|
},
|
|
14082
14184
|
{
|
|
14083
14185
|
"id": "atomic-design",
|
|
14186
|
+
"approach_ids": [
|
|
14187
|
+
"trace"
|
|
14188
|
+
],
|
|
14084
14189
|
"name": "Atomic Design",
|
|
14085
14190
|
"version": "1.0.0",
|
|
14086
14191
|
"description": "Atoms, Molecules, Organisms, Templates, Pages: a methodology for creating design systems from the smallest elements up.",
|
|
@@ -14178,6 +14283,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14178
14283
|
},
|
|
14179
14284
|
{
|
|
14180
14285
|
"id": "double-diamond",
|
|
14286
|
+
"approach_ids": [
|
|
14287
|
+
"plan"
|
|
14288
|
+
],
|
|
14181
14289
|
"name": "Double Diamond",
|
|
14182
14290
|
"version": "1.0.0",
|
|
14183
14291
|
"description": "Discover, Define, Develop, Deliver: a four-phase divergent/convergent design process.",
|
|
@@ -14268,6 +14376,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14268
14376
|
},
|
|
14269
14377
|
{
|
|
14270
14378
|
"id": "dora-metrics",
|
|
14379
|
+
"approach_ids": [
|
|
14380
|
+
"inspect"
|
|
14381
|
+
],
|
|
14271
14382
|
"name": "DORA Metrics",
|
|
14272
14383
|
"version": "1.0.0",
|
|
14273
14384
|
"description": "Four key metrics for software delivery performance: deployment frequency, lead time, change failure rate, and time to restore.",
|
|
@@ -14327,16 +14438,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14327
14438
|
]
|
|
14328
14439
|
}
|
|
14329
14440
|
]
|
|
14330
|
-
}
|
|
14331
|
-
"computed_properties": [
|
|
14332
|
-
{
|
|
14333
|
-
"property": "stability_index",
|
|
14334
|
-
"expression": "change_failure_rate * mean_time_to_recovery",
|
|
14335
|
-
"entity_type": "metric",
|
|
14336
|
-
"label": "Stability Index",
|
|
14337
|
-
"format": "number"
|
|
14338
|
-
}
|
|
14339
|
-
]
|
|
14441
|
+
}
|
|
14340
14442
|
},
|
|
14341
14443
|
"structure": {
|
|
14342
14444
|
"pattern": "collection"
|
|
@@ -14465,6 +14567,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14465
14567
|
},
|
|
14466
14568
|
{
|
|
14467
14569
|
"id": "pirate-metrics-aarrr",
|
|
14570
|
+
"approach_ids": [
|
|
14571
|
+
"trace"
|
|
14572
|
+
],
|
|
14468
14573
|
"name": "Pirate Metrics AARRR",
|
|
14469
14574
|
"version": "1.0.0",
|
|
14470
14575
|
"description": "Track user lifecycle across five stages: Acquisition, Activation, Retention, Revenue, and Referral.",
|
|
@@ -14498,7 +14603,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14498
14603
|
"required_properties": {
|
|
14499
14604
|
"metric": [
|
|
14500
14605
|
{
|
|
14501
|
-
"property": "
|
|
14606
|
+
"property": "metric_category",
|
|
14502
14607
|
"type": "enum",
|
|
14503
14608
|
"required": true,
|
|
14504
14609
|
"label": "Lifecycle stage",
|
|
@@ -14512,16 +14617,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14512
14617
|
]
|
|
14513
14618
|
}
|
|
14514
14619
|
]
|
|
14515
|
-
}
|
|
14516
|
-
"computed_properties": [
|
|
14517
|
-
{
|
|
14518
|
-
"property": "conversion_rate",
|
|
14519
|
-
"expression": "(stage_exits / stage_entries) * 100",
|
|
14520
|
-
"entity_type": "metric",
|
|
14521
|
-
"label": "Stage Conversion",
|
|
14522
|
-
"format": "percentage"
|
|
14523
|
-
}
|
|
14524
|
-
]
|
|
14620
|
+
}
|
|
14525
14621
|
},
|
|
14526
14622
|
"structure": {
|
|
14527
14623
|
"pattern": "funnel",
|
|
@@ -14585,6 +14681,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14585
14681
|
},
|
|
14586
14682
|
{
|
|
14587
14683
|
"id": "north-star-metric",
|
|
14684
|
+
"approach_ids": [
|
|
14685
|
+
"plan"
|
|
14686
|
+
],
|
|
14588
14687
|
"name": "North Star Metric",
|
|
14589
14688
|
"version": "1.0.0",
|
|
14590
14689
|
"description": "One metric that best captures the core value you deliver. Supported by 3-5 input metrics that drive it.",
|
|
@@ -14618,7 +14717,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14618
14717
|
"required_properties": {
|
|
14619
14718
|
"metric": [
|
|
14620
14719
|
{
|
|
14621
|
-
"property": "
|
|
14720
|
+
"property": "designation",
|
|
14622
14721
|
"type": "enum",
|
|
14623
14722
|
"required": true,
|
|
14624
14723
|
"label": "Metric role",
|
|
@@ -14636,16 +14735,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14636
14735
|
"description": "How strongly this input metric moves the North Star (input metrics only)"
|
|
14637
14736
|
}
|
|
14638
14737
|
]
|
|
14639
|
-
}
|
|
14640
|
-
"computed_properties": [
|
|
14641
|
-
{
|
|
14642
|
-
"property": "nsm_impact",
|
|
14643
|
-
"expression": "input_metric_value * leverage",
|
|
14644
|
-
"entity_type": "metric",
|
|
14645
|
-
"label": "NSM Impact",
|
|
14646
|
-
"format": "number"
|
|
14647
|
-
}
|
|
14648
|
-
]
|
|
14738
|
+
}
|
|
14649
14739
|
},
|
|
14650
14740
|
"structure": {
|
|
14651
14741
|
"pattern": "collection"
|
|
@@ -14681,6 +14771,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14681
14771
|
},
|
|
14682
14772
|
{
|
|
14683
14773
|
"id": "marketing-mix-4ps",
|
|
14774
|
+
"approach_ids": [
|
|
14775
|
+
"plan"
|
|
14776
|
+
],
|
|
14684
14777
|
"name": "Marketing Mix 4Ps",
|
|
14685
14778
|
"version": "1.0.0",
|
|
14686
14779
|
"description": "The foundational marketing framework. Every marketing strategy must address four decisions: what to sell (Product), what to charge (Price), where to sell (Place), and how to promote (Promotion).",
|
|
@@ -14774,6 +14867,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14774
14867
|
},
|
|
14775
14868
|
{
|
|
14776
14869
|
"id": "bullseye-framework",
|
|
14870
|
+
"approach_ids": [
|
|
14871
|
+
"plan"
|
|
14872
|
+
],
|
|
14777
14873
|
"name": "Bullseye Framework",
|
|
14778
14874
|
"version": "1.0.0",
|
|
14779
14875
|
"description": "Test 19 traction channels systematically. Start with the outer ring (what's possible), narrow to the middle ring (what's probable), then focus on the inner ring (what's working). Run cheap tests across all channels to find your bullseye.",
|
|
@@ -14860,6 +14956,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14860
14956
|
},
|
|
14861
14957
|
{
|
|
14862
14958
|
"id": "product-led-growth-framework",
|
|
14959
|
+
"approach_ids": [
|
|
14960
|
+
"plan"
|
|
14961
|
+
],
|
|
14863
14962
|
"name": "PLG Framework",
|
|
14864
14963
|
"version": "1.0.0",
|
|
14865
14964
|
"description": "Product-led go-to-market motion. Free entry gives users access, the aha moment hooks them, they expand usage within their team, and monetisation captures value from power users.",
|
|
@@ -15042,6 +15141,9 @@ var UPG_FRAMEWORKS = [
|
|
|
15042
15141
|
},
|
|
15043
15142
|
{
|
|
15044
15143
|
"id": "raci-matrix",
|
|
15144
|
+
"approach_ids": [
|
|
15145
|
+
"inspect"
|
|
15146
|
+
],
|
|
15045
15147
|
"name": "RACI Matrix",
|
|
15046
15148
|
"version": "1.0.0",
|
|
15047
15149
|
"description": "Assign roles: Responsible, Accountable, Consulted, Informed for each activity.",
|
|
@@ -15093,16 +15195,7 @@ var UPG_FRAMEWORKS = [
|
|
|
15093
15195
|
"role": "item"
|
|
15094
15196
|
}
|
|
15095
15197
|
],
|
|
15096
|
-
"required_properties": {}
|
|
15097
|
-
"computed_properties": [
|
|
15098
|
-
{
|
|
15099
|
-
"property": "coverage_score",
|
|
15100
|
-
"expression": "assigned_count / total_activities",
|
|
15101
|
-
"entity_type": "team",
|
|
15102
|
-
"label": "RACI Coverage",
|
|
15103
|
-
"format": "percentage"
|
|
15104
|
-
}
|
|
15105
|
-
]
|
|
15198
|
+
"required_properties": {}
|
|
15106
15199
|
},
|
|
15107
15200
|
"structure": {
|
|
15108
15201
|
"pattern": "matrix"
|
|
@@ -15326,6 +15419,9 @@ var UPG_FRAMEWORKS = [
|
|
|
15326
15419
|
},
|
|
15327
15420
|
{
|
|
15328
15421
|
"id": "team-health-check",
|
|
15422
|
+
"approach_ids": [
|
|
15423
|
+
"inspect"
|
|
15424
|
+
],
|
|
15329
15425
|
"name": "Team Health Check",
|
|
15330
15426
|
"version": "1.0.0",
|
|
15331
15427
|
"description": "A facilitated team self-assessment across dimensions like mission, fun, learning, speed, and support, using traffic-light voting to surface strengths and improvement areas in a safe format.",
|
|
@@ -15383,16 +15479,7 @@ var UPG_FRAMEWORKS = [
|
|
|
15383
15479
|
"role": "item"
|
|
15384
15480
|
}
|
|
15385
15481
|
],
|
|
15386
|
-
"required_properties": {}
|
|
15387
|
-
"computed_properties": [
|
|
15388
|
-
{
|
|
15389
|
-
"property": "health_index",
|
|
15390
|
-
"expression": "(green_count - red_count) / total_indicators",
|
|
15391
|
-
"entity_type": "team",
|
|
15392
|
-
"label": "Health Index",
|
|
15393
|
-
"format": "number"
|
|
15394
|
-
}
|
|
15395
|
-
]
|
|
15482
|
+
"required_properties": {}
|
|
15396
15483
|
},
|
|
15397
15484
|
"structure": {
|
|
15398
15485
|
"pattern": "table"
|
|
@@ -15449,6 +15536,9 @@ var UPG_FRAMEWORKS = [
|
|
|
15449
15536
|
},
|
|
15450
15537
|
{
|
|
15451
15538
|
"id": "raid-log",
|
|
15539
|
+
"approach_ids": [
|
|
15540
|
+
"inspect"
|
|
15541
|
+
],
|
|
15452
15542
|
"name": "RAID Log",
|
|
15453
15543
|
"version": "1.0.0",
|
|
15454
15544
|
"description": "A project management register tracking Risks, Assumptions, Issues, and Dependencies, the four categories most likely to derail a project if left unmanaged.",
|
|
@@ -15468,6 +15558,11 @@ var UPG_FRAMEWORKS = [
|
|
|
15468
15558
|
"entityTypeId": "risk_register",
|
|
15469
15559
|
"description": "Risk or assumption logged with likelihood, impact, owner, and mitigation strategy"
|
|
15470
15560
|
},
|
|
15561
|
+
{
|
|
15562
|
+
"label": "Risk",
|
|
15563
|
+
"entityTypeId": "risk",
|
|
15564
|
+
"description": "Individual risk scored by probability and impact; severity = probability * impact"
|
|
15565
|
+
},
|
|
15471
15566
|
{
|
|
15472
15567
|
"label": "Dependency",
|
|
15473
15568
|
"entityTypeId": "dependency",
|
|
@@ -15490,6 +15585,10 @@ var UPG_FRAMEWORKS = [
|
|
|
15490
15585
|
"type": "risk_register",
|
|
15491
15586
|
"role": "item"
|
|
15492
15587
|
},
|
|
15588
|
+
{
|
|
15589
|
+
"type": "risk",
|
|
15590
|
+
"role": "scored_item"
|
|
15591
|
+
},
|
|
15493
15592
|
{
|
|
15494
15593
|
"type": "dependency",
|
|
15495
15594
|
"role": "item"
|
|
@@ -15503,7 +15602,24 @@ var UPG_FRAMEWORKS = [
|
|
|
15503
15602
|
"role": "item"
|
|
15504
15603
|
}
|
|
15505
15604
|
],
|
|
15506
|
-
"required_properties": {
|
|
15605
|
+
"required_properties": {
|
|
15606
|
+
"risk": [
|
|
15607
|
+
{
|
|
15608
|
+
"property": "probability",
|
|
15609
|
+
"type": "number",
|
|
15610
|
+
"required": true,
|
|
15611
|
+
"label": "Probability",
|
|
15612
|
+
"description": "Likelihood the risk materialises (risk.probability assessment)"
|
|
15613
|
+
},
|
|
15614
|
+
{
|
|
15615
|
+
"property": "impact",
|
|
15616
|
+
"type": "number",
|
|
15617
|
+
"required": true,
|
|
15618
|
+
"label": "Impact",
|
|
15619
|
+
"description": "Consequence severity if the risk materialises (risk.impact assessment)"
|
|
15620
|
+
}
|
|
15621
|
+
]
|
|
15622
|
+
},
|
|
15507
15623
|
"computed_properties": [
|
|
15508
15624
|
{
|
|
15509
15625
|
"property": "severity",
|
|
@@ -15564,126 +15680,1028 @@ var UPG_FRAMEWORKS = [
|
|
|
15564
15680
|
"Formal programme management would create overhead without value"
|
|
15565
15681
|
]
|
|
15566
15682
|
}
|
|
15567
|
-
}
|
|
15568
|
-
];
|
|
15569
|
-
var UPG_FRAMEWORKS_BY_ID = Object.fromEntries(
|
|
15570
|
-
UPG_FRAMEWORKS.map((fw) => [fw.id, fw])
|
|
15571
|
-
);
|
|
15572
|
-
var UPG_FRAMEWORKS_BY_CATEGORY = {};
|
|
15573
|
-
for (const fw of UPG_FRAMEWORKS) {
|
|
15574
|
-
if (!UPG_FRAMEWORKS_BY_CATEGORY[fw.category]) UPG_FRAMEWORKS_BY_CATEGORY[fw.category] = [];
|
|
15575
|
-
UPG_FRAMEWORKS_BY_CATEGORY[fw.category].push(fw);
|
|
15576
|
-
}
|
|
15577
|
-
|
|
15578
|
-
// src/presentation/labels.ts
|
|
15579
|
-
var PRIORITY_LABELS = [
|
|
15580
|
-
// ── need (CONSOLIDATED: replaces pain_point + user_need) ─────────────────────
|
|
15581
|
-
{
|
|
15582
|
-
id: "need",
|
|
15583
|
-
canonical_label: "Need",
|
|
15584
|
-
alt_labels: [
|
|
15585
|
-
"pain point",
|
|
15586
|
-
"pain",
|
|
15587
|
-
"user need",
|
|
15588
|
-
"customer need",
|
|
15589
|
-
"problem",
|
|
15590
|
-
"struggle",
|
|
15591
|
-
"customer pain",
|
|
15592
|
-
"frustration",
|
|
15593
|
-
"gap",
|
|
15594
|
-
"unmet need",
|
|
15595
|
-
"user problem"
|
|
15596
|
-
],
|
|
15597
|
-
framework_labels: {
|
|
15598
|
-
lean_canvas: "Problem",
|
|
15599
|
-
design_thinking: "Pain Point",
|
|
15600
|
-
ost: "Opportunity (need)",
|
|
15601
|
-
jtbd: "Struggle",
|
|
15602
|
-
vpc: "Customer Pain"
|
|
15603
|
-
},
|
|
15604
|
-
designations: {
|
|
15605
|
-
pain: "Pain Point",
|
|
15606
|
-
gap: "Need",
|
|
15607
|
-
desire: "Desire",
|
|
15608
|
-
constraint: "Constraint"
|
|
15609
|
-
}
|
|
15610
|
-
},
|
|
15611
|
-
// ── opportunity ──────────────────────────────────────────────────────────────
|
|
15612
|
-
{
|
|
15613
|
-
id: "opportunity",
|
|
15614
|
-
canonical_label: "Opportunity",
|
|
15615
|
-
alt_labels: ["product opportunity", "market opportunity", "user opportunity"],
|
|
15616
|
-
framework_labels: {
|
|
15617
|
-
ost: "Opportunity"
|
|
15618
|
-
}
|
|
15619
|
-
},
|
|
15620
|
-
// ── solution ─────────────────────────────────────────────────────────────────
|
|
15621
|
-
{
|
|
15622
|
-
id: "solution",
|
|
15623
|
-
canonical_label: "Solution",
|
|
15624
|
-
alt_labels: ["proposed solution", "solution idea", "concept", "approach"],
|
|
15625
|
-
framework_labels: {
|
|
15626
|
-
ost: "Solution",
|
|
15627
|
-
design_thinking: "Solution",
|
|
15628
|
-
lean_canvas: "Solution",
|
|
15629
|
-
rice: "Scored Solution"
|
|
15630
|
-
}
|
|
15631
15683
|
},
|
|
15632
|
-
// ── experiment (CONSOLIDATED: absorbs ab_test, growth_experiment, pricing_experiment) ──
|
|
15633
15684
|
{
|
|
15634
|
-
id: "
|
|
15635
|
-
|
|
15636
|
-
|
|
15637
|
-
"test",
|
|
15638
|
-
"validation",
|
|
15639
|
-
"ab test",
|
|
15640
|
-
"a/b test",
|
|
15641
|
-
"split test",
|
|
15642
|
-
"growth experiment",
|
|
15643
|
-
"pricing experiment",
|
|
15644
|
-
"usability test",
|
|
15645
|
-
"discovery experiment"
|
|
15685
|
+
"id": "ice-scoring",
|
|
15686
|
+
"approach_ids": [
|
|
15687
|
+
"prioritise"
|
|
15646
15688
|
],
|
|
15647
|
-
|
|
15648
|
-
|
|
15649
|
-
|
|
15650
|
-
|
|
15689
|
+
"name": "ICE Scoring",
|
|
15690
|
+
"version": "1.0.0",
|
|
15691
|
+
"description": "Rate ideas by Impact, Confidence, and Ease on a 1-10 scale. Multiply for a composite score. Fast and lightweight.",
|
|
15692
|
+
"category": "prioritization",
|
|
15693
|
+
"origin": {
|
|
15694
|
+
"type": "practitioner",
|
|
15695
|
+
"attribution": "Sean Ellis",
|
|
15696
|
+
"description": "Created by Sean Ellis as a lightweight growth experiment scoring method. Widely adopted in growth teams.",
|
|
15697
|
+
"year": 2010,
|
|
15698
|
+
"license": "open_attribution"
|
|
15651
15699
|
},
|
|
15652
|
-
|
|
15653
|
-
|
|
15654
|
-
|
|
15655
|
-
|
|
15656
|
-
|
|
15657
|
-
|
|
15658
|
-
|
|
15659
|
-
|
|
15660
|
-
|
|
15661
|
-
|
|
15662
|
-
|
|
15663
|
-
|
|
15664
|
-
|
|
15665
|
-
|
|
15666
|
-
|
|
15667
|
-
|
|
15668
|
-
|
|
15669
|
-
|
|
15670
|
-
|
|
15671
|
-
|
|
15672
|
-
|
|
15673
|
-
|
|
15674
|
-
|
|
15675
|
-
|
|
15676
|
-
|
|
15677
|
-
|
|
15678
|
-
|
|
15679
|
-
"
|
|
15680
|
-
|
|
15681
|
-
|
|
15682
|
-
|
|
15683
|
-
|
|
15684
|
-
|
|
15685
|
-
|
|
15686
|
-
|
|
15700
|
+
"tags": [
|
|
15701
|
+
"prioritization",
|
|
15702
|
+
"table"
|
|
15703
|
+
],
|
|
15704
|
+
"slots": [
|
|
15705
|
+
{
|
|
15706
|
+
"label": "Items to score",
|
|
15707
|
+
"entityTypeId": "feature",
|
|
15708
|
+
"description": "Features or experiments being evaluated"
|
|
15709
|
+
},
|
|
15710
|
+
{
|
|
15711
|
+
"label": "Impact",
|
|
15712
|
+
"entityTypeId": "outcome",
|
|
15713
|
+
"description": "How much will this move the needle?"
|
|
15714
|
+
},
|
|
15715
|
+
{
|
|
15716
|
+
"label": "Confidence",
|
|
15717
|
+
"entityTypeId": "assumption",
|
|
15718
|
+
"description": "How sure are we about the impact?"
|
|
15719
|
+
},
|
|
15720
|
+
{
|
|
15721
|
+
"label": "Ease",
|
|
15722
|
+
"entityTypeId": "feature",
|
|
15723
|
+
"description": "How easy is this to implement?"
|
|
15724
|
+
}
|
|
15725
|
+
],
|
|
15726
|
+
"data": {
|
|
15727
|
+
"entity_types": [
|
|
15728
|
+
{
|
|
15729
|
+
"type": "feature",
|
|
15730
|
+
"role": "scored_item"
|
|
15731
|
+
},
|
|
15732
|
+
{
|
|
15733
|
+
"type": "outcome",
|
|
15734
|
+
"role": "item"
|
|
15735
|
+
},
|
|
15736
|
+
{
|
|
15737
|
+
"type": "assumption",
|
|
15738
|
+
"role": "item"
|
|
15739
|
+
}
|
|
15740
|
+
],
|
|
15741
|
+
"required_properties": {
|
|
15742
|
+
"feature": [
|
|
15743
|
+
{
|
|
15744
|
+
"property": "impact",
|
|
15745
|
+
"type": "number",
|
|
15746
|
+
"required": true,
|
|
15747
|
+
"scope": "framework",
|
|
15748
|
+
"label": "Impact",
|
|
15749
|
+
"description": "Expected impact on the target metric (1-10)"
|
|
15750
|
+
},
|
|
15751
|
+
{
|
|
15752
|
+
"property": "confidence",
|
|
15753
|
+
"type": "number",
|
|
15754
|
+
"required": true,
|
|
15755
|
+
"scope": "framework",
|
|
15756
|
+
"label": "Confidence",
|
|
15757
|
+
"description": "Confidence in the impact estimate (1-10)"
|
|
15758
|
+
},
|
|
15759
|
+
{
|
|
15760
|
+
"property": "ease",
|
|
15761
|
+
"type": "number",
|
|
15762
|
+
"required": true,
|
|
15763
|
+
"scope": "framework",
|
|
15764
|
+
"label": "Ease",
|
|
15765
|
+
"description": "Ease of implementation (1-10)"
|
|
15766
|
+
}
|
|
15767
|
+
]
|
|
15768
|
+
},
|
|
15769
|
+
"computed_properties": [
|
|
15770
|
+
{
|
|
15771
|
+
"property": "ice_score",
|
|
15772
|
+
"expression": "impact * confidence * ease",
|
|
15773
|
+
"entity_type": "feature",
|
|
15774
|
+
"label": "ICE Score",
|
|
15775
|
+
"format": "number"
|
|
15776
|
+
}
|
|
15777
|
+
]
|
|
15778
|
+
},
|
|
15779
|
+
"structure": {
|
|
15780
|
+
"pattern": "table"
|
|
15781
|
+
},
|
|
15782
|
+
"presentation": {
|
|
15783
|
+
"layout": {
|
|
15784
|
+
"type": "table",
|
|
15785
|
+
"columns": [
|
|
15786
|
+
{
|
|
15787
|
+
"property": "title",
|
|
15788
|
+
"label": "Items to score",
|
|
15789
|
+
"sortable": true
|
|
15790
|
+
},
|
|
15791
|
+
{
|
|
15792
|
+
"property": "impact",
|
|
15793
|
+
"label": "Impact",
|
|
15794
|
+
"sortable": true
|
|
15795
|
+
},
|
|
15796
|
+
{
|
|
15797
|
+
"property": "confidence",
|
|
15798
|
+
"label": "Confidence",
|
|
15799
|
+
"sortable": true
|
|
15800
|
+
},
|
|
15801
|
+
{
|
|
15802
|
+
"property": "ease",
|
|
15803
|
+
"label": "Ease",
|
|
15804
|
+
"sortable": true
|
|
15805
|
+
}
|
|
15806
|
+
]
|
|
15807
|
+
},
|
|
15808
|
+
"sort_by": {
|
|
15809
|
+
"property": "title",
|
|
15810
|
+
"direction": "asc"
|
|
15811
|
+
},
|
|
15812
|
+
"colour_by": "type",
|
|
15813
|
+
"card_fields": [
|
|
15814
|
+
"title",
|
|
15815
|
+
"description",
|
|
15816
|
+
"status"
|
|
15817
|
+
]
|
|
15818
|
+
},
|
|
15819
|
+
"education": {
|
|
15820
|
+
"purpose": "Provide a lightweight scoring model for early-stage ideas when detailed effort estimates are unavailable. Faster than RICE and useful for brainstorm triage.",
|
|
15821
|
+
"core_question": "Which ideas should we investigate further based on their potential impact, confidence in our assumptions, and implementation ease?",
|
|
15822
|
+
"when_to_use": [
|
|
15823
|
+
"You have more ideas or features than capacity to build them",
|
|
15824
|
+
"Stakeholders disagree on what to build next",
|
|
15825
|
+
"You need a transparent, defensible prioritisation process"
|
|
15826
|
+
],
|
|
15827
|
+
"when_not_to_use": [
|
|
15828
|
+
"You have a single obvious next step with no contention",
|
|
15829
|
+
"The backlog is small enough to sequence intuitively"
|
|
15830
|
+
]
|
|
15831
|
+
}
|
|
15832
|
+
},
|
|
15833
|
+
{
|
|
15834
|
+
"id": "wsjf",
|
|
15835
|
+
"approach_ids": [
|
|
15836
|
+
"prioritise"
|
|
15837
|
+
],
|
|
15838
|
+
"name": "WSJF (Weighted Shortest Job First)",
|
|
15839
|
+
"version": "1.0.0",
|
|
15840
|
+
"description": "Prioritise work by dividing Cost of Delay (user value + time criticality + risk reduction) by job duration to maximise economic throughput.",
|
|
15841
|
+
"category": "planning",
|
|
15842
|
+
"origin": {
|
|
15843
|
+
"type": "practitioner",
|
|
15844
|
+
"attribution": "Reinertsen / SAFe",
|
|
15845
|
+
"description": "Developed by Don Reinertsen and adopted as a core practice in the Scaled Agile Framework (SAFe). Combines urgency (Cost of Delay) with job size to produce an economic prioritisation sequence.",
|
|
15846
|
+
"url": "https://www.scaledagileframework.com/wsjf/",
|
|
15847
|
+
"year": 2011,
|
|
15848
|
+
"license": "open_attribution"
|
|
15849
|
+
},
|
|
15850
|
+
"tags": [
|
|
15851
|
+
"planning",
|
|
15852
|
+
"table"
|
|
15853
|
+
],
|
|
15854
|
+
"slots": [
|
|
15855
|
+
{
|
|
15856
|
+
"label": "Backlog Items",
|
|
15857
|
+
"entityTypeId": "feature",
|
|
15858
|
+
"description": "Backlog Items: feature entries to evaluate"
|
|
15859
|
+
},
|
|
15860
|
+
{
|
|
15861
|
+
"label": "User/Business Value",
|
|
15862
|
+
"entityTypeId": "metric",
|
|
15863
|
+
"description": "User/Business Value: metric entries to evaluate"
|
|
15864
|
+
},
|
|
15865
|
+
{
|
|
15866
|
+
"label": "Time Criticality",
|
|
15867
|
+
"entityTypeId": "metric",
|
|
15868
|
+
"description": "How much value decays if delivery is delayed (deadlines, competition, seasonal windows)"
|
|
15869
|
+
},
|
|
15870
|
+
{
|
|
15871
|
+
"label": "Risk Reduction / Opportunity Enablement",
|
|
15872
|
+
"entityTypeId": "metric",
|
|
15873
|
+
"description": "Risk Reduction / Opportunity Enablement: metric entries to evaluate"
|
|
15874
|
+
},
|
|
15875
|
+
{
|
|
15876
|
+
"label": "Job Size",
|
|
15877
|
+
"entityTypeId": "metric",
|
|
15878
|
+
"description": "Estimated effort (story points, t-shirt size, or person-weeks)"
|
|
15879
|
+
}
|
|
15880
|
+
],
|
|
15881
|
+
"data": {
|
|
15882
|
+
"entity_types": [
|
|
15883
|
+
{
|
|
15884
|
+
"type": "feature",
|
|
15885
|
+
"role": "scored_item"
|
|
15886
|
+
},
|
|
15887
|
+
{
|
|
15888
|
+
"type": "metric",
|
|
15889
|
+
"role": "item"
|
|
15890
|
+
}
|
|
15891
|
+
],
|
|
15892
|
+
"required_properties": {
|
|
15893
|
+
"feature": [
|
|
15894
|
+
{
|
|
15895
|
+
"property": "user_value",
|
|
15896
|
+
"type": "number",
|
|
15897
|
+
"required": true,
|
|
15898
|
+
"scope": "framework",
|
|
15899
|
+
"label": "User/Business Value",
|
|
15900
|
+
"description": "Relative value to users and the business if delivered"
|
|
15901
|
+
},
|
|
15902
|
+
{
|
|
15903
|
+
"property": "time_criticality",
|
|
15904
|
+
"type": "number",
|
|
15905
|
+
"required": true,
|
|
15906
|
+
"scope": "framework",
|
|
15907
|
+
"label": "Time Criticality",
|
|
15908
|
+
"description": "How much value decays if delivery is delayed (deadlines, competition, seasonal windows)"
|
|
15909
|
+
},
|
|
15910
|
+
{
|
|
15911
|
+
"property": "risk_reduction",
|
|
15912
|
+
"type": "number",
|
|
15913
|
+
"required": true,
|
|
15914
|
+
"scope": "framework",
|
|
15915
|
+
"label": "Risk Reduction / Opportunity Enablement",
|
|
15916
|
+
"description": "Value from reducing risk or enabling future opportunities"
|
|
15917
|
+
},
|
|
15918
|
+
{
|
|
15919
|
+
"property": "job_size",
|
|
15920
|
+
"type": "number",
|
|
15921
|
+
"required": true,
|
|
15922
|
+
"scope": "framework",
|
|
15923
|
+
"label": "Job Size",
|
|
15924
|
+
"description": "Estimated effort (story points, t-shirt size, or person-weeks)"
|
|
15925
|
+
}
|
|
15926
|
+
]
|
|
15927
|
+
},
|
|
15928
|
+
"computed_properties": [
|
|
15929
|
+
{
|
|
15930
|
+
"property": "wsjf_score",
|
|
15931
|
+
"expression": "(user_value + time_criticality + risk_reduction) / job_size",
|
|
15932
|
+
"entity_type": "feature",
|
|
15933
|
+
"label": "WSJF Score",
|
|
15934
|
+
"format": "number"
|
|
15935
|
+
}
|
|
15936
|
+
]
|
|
15937
|
+
},
|
|
15938
|
+
"structure": {
|
|
15939
|
+
"pattern": "table"
|
|
15940
|
+
},
|
|
15941
|
+
"presentation": {
|
|
15942
|
+
"layout": {
|
|
15943
|
+
"type": "table",
|
|
15944
|
+
"columns": [
|
|
15945
|
+
{
|
|
15946
|
+
"property": "title",
|
|
15947
|
+
"label": "Backlog Items",
|
|
15948
|
+
"sortable": true
|
|
15949
|
+
},
|
|
15950
|
+
{
|
|
15951
|
+
"property": "user_value",
|
|
15952
|
+
"label": "User/Business Value",
|
|
15953
|
+
"sortable": true
|
|
15954
|
+
},
|
|
15955
|
+
{
|
|
15956
|
+
"property": "time_criticality",
|
|
15957
|
+
"label": "Time Criticality",
|
|
15958
|
+
"sortable": true
|
|
15959
|
+
},
|
|
15960
|
+
{
|
|
15961
|
+
"property": "risk_reduction",
|
|
15962
|
+
"label": "Risk Reduction / Opportunity Enablement",
|
|
15963
|
+
"sortable": true
|
|
15964
|
+
},
|
|
15965
|
+
{
|
|
15966
|
+
"property": "job_size",
|
|
15967
|
+
"label": "Job Size",
|
|
15968
|
+
"sortable": true
|
|
15969
|
+
},
|
|
15970
|
+
{
|
|
15971
|
+
"property": "wsjf_score",
|
|
15972
|
+
"label": "WSJF Score",
|
|
15973
|
+
"sortable": true
|
|
15974
|
+
}
|
|
15975
|
+
]
|
|
15976
|
+
},
|
|
15977
|
+
"sort_by": {
|
|
15978
|
+
"property": "title",
|
|
15979
|
+
"direction": "asc"
|
|
15980
|
+
},
|
|
15981
|
+
"colour_by": "type",
|
|
15982
|
+
"card_fields": [
|
|
15983
|
+
"title",
|
|
15984
|
+
"description",
|
|
15985
|
+
"status"
|
|
15986
|
+
]
|
|
15987
|
+
},
|
|
15988
|
+
"education": {
|
|
15989
|
+
"purpose": "Prioritise work by dividing the Cost of Delay by job duration, ensuring the most time-sensitive, valuable items are done first.",
|
|
15990
|
+
"core_question": "Considering the cost of waiting, which items should we start now to maximise economic benefit?",
|
|
15991
|
+
"when_to_use": [
|
|
15992
|
+
"You need to coordinate work across multiple teams or time horizons",
|
|
15993
|
+
"Stakeholders need visibility into what is coming and when",
|
|
15994
|
+
"You want to balance commitments with flexibility"
|
|
15995
|
+
],
|
|
15996
|
+
"when_not_to_use": [
|
|
15997
|
+
"The team is small enough that informal coordination works",
|
|
15998
|
+
"Plans would create false precision about uncertain outcomes"
|
|
15999
|
+
]
|
|
16000
|
+
}
|
|
16001
|
+
},
|
|
16002
|
+
{
|
|
16003
|
+
"id": "cost-of-delay",
|
|
16004
|
+
"approach_ids": [
|
|
16005
|
+
"prioritise"
|
|
16006
|
+
],
|
|
16007
|
+
"name": "Cost of Delay",
|
|
16008
|
+
"version": "1.0.0",
|
|
16009
|
+
"description": "Quantify the economic cost of not shipping a feature to drive priority decisions. Combines urgency with value.",
|
|
16010
|
+
"category": "prioritization",
|
|
16011
|
+
"origin": {
|
|
16012
|
+
"type": "practitioner",
|
|
16013
|
+
"attribution": "Don Reinertsen",
|
|
16014
|
+
"description": "Formalised in The Principles of Product Development Flow (Celeritas Publishing). Foundational to lean product economics.",
|
|
16015
|
+
"year": 2009,
|
|
16016
|
+
"license": "public_domain"
|
|
16017
|
+
},
|
|
16018
|
+
"tags": [
|
|
16019
|
+
"prioritization",
|
|
16020
|
+
"table"
|
|
16021
|
+
],
|
|
16022
|
+
"slots": [
|
|
16023
|
+
{
|
|
16024
|
+
"label": "Items to evaluate",
|
|
16025
|
+
"entityTypeId": "feature",
|
|
16026
|
+
"description": "Features or initiatives being assessed"
|
|
16027
|
+
},
|
|
16028
|
+
{
|
|
16029
|
+
"label": "User-Business Value",
|
|
16030
|
+
"entityTypeId": "outcome",
|
|
16031
|
+
"description": "Revenue, retention, or strategic value"
|
|
16032
|
+
},
|
|
16033
|
+
{
|
|
16034
|
+
"label": "Time Criticality",
|
|
16035
|
+
"entityTypeId": "metric",
|
|
16036
|
+
"description": "How much value decays with delay"
|
|
16037
|
+
},
|
|
16038
|
+
{
|
|
16039
|
+
"label": "Risk Reduction",
|
|
16040
|
+
"entityTypeId": "risk",
|
|
16041
|
+
"description": "What risk does this mitigate?"
|
|
16042
|
+
}
|
|
16043
|
+
],
|
|
16044
|
+
"data": {
|
|
16045
|
+
"entity_types": [
|
|
16046
|
+
{
|
|
16047
|
+
"type": "feature",
|
|
16048
|
+
"role": "scored_item"
|
|
16049
|
+
},
|
|
16050
|
+
{
|
|
16051
|
+
"type": "metric",
|
|
16052
|
+
"role": "item"
|
|
16053
|
+
},
|
|
16054
|
+
{
|
|
16055
|
+
"type": "outcome",
|
|
16056
|
+
"role": "item"
|
|
16057
|
+
},
|
|
16058
|
+
{
|
|
16059
|
+
"type": "risk",
|
|
16060
|
+
"role": "item"
|
|
16061
|
+
}
|
|
16062
|
+
],
|
|
16063
|
+
"required_properties": {
|
|
16064
|
+
"feature": [
|
|
16065
|
+
{
|
|
16066
|
+
"property": "cost_of_delay",
|
|
16067
|
+
"type": "number",
|
|
16068
|
+
"required": true,
|
|
16069
|
+
"scope": "framework",
|
|
16070
|
+
"label": "Cost of Delay",
|
|
16071
|
+
"description": "Weekly revenue impact of not shipping"
|
|
16072
|
+
},
|
|
16073
|
+
{
|
|
16074
|
+
"property": "job_size",
|
|
16075
|
+
"type": "number",
|
|
16076
|
+
"required": true,
|
|
16077
|
+
"scope": "framework",
|
|
16078
|
+
"label": "Job Size",
|
|
16079
|
+
"description": "Weeks of development effort"
|
|
16080
|
+
}
|
|
16081
|
+
]
|
|
16082
|
+
},
|
|
16083
|
+
"computed_properties": [
|
|
16084
|
+
{
|
|
16085
|
+
"property": "wsjf_score",
|
|
16086
|
+
"expression": "cost_of_delay / job_size",
|
|
16087
|
+
"entity_type": "feature",
|
|
16088
|
+
"label": "WSJF Score",
|
|
16089
|
+
"format": "number"
|
|
16090
|
+
}
|
|
16091
|
+
]
|
|
16092
|
+
},
|
|
16093
|
+
"structure": {
|
|
16094
|
+
"pattern": "table"
|
|
16095
|
+
},
|
|
16096
|
+
"presentation": {
|
|
16097
|
+
"layout": {
|
|
16098
|
+
"type": "table",
|
|
16099
|
+
"columns": [
|
|
16100
|
+
{
|
|
16101
|
+
"property": "title",
|
|
16102
|
+
"label": "Items to evaluate",
|
|
16103
|
+
"sortable": true
|
|
16104
|
+
},
|
|
16105
|
+
{
|
|
16106
|
+
"property": "cost_of_delay",
|
|
16107
|
+
"label": "User-Business Value",
|
|
16108
|
+
"sortable": true
|
|
16109
|
+
},
|
|
16110
|
+
{
|
|
16111
|
+
"property": "job_size",
|
|
16112
|
+
"label": "Job Size",
|
|
16113
|
+
"sortable": true
|
|
16114
|
+
},
|
|
16115
|
+
{
|
|
16116
|
+
"property": "wsjf_score",
|
|
16117
|
+
"label": "CoD Score",
|
|
16118
|
+
"sortable": true
|
|
16119
|
+
}
|
|
16120
|
+
]
|
|
16121
|
+
},
|
|
16122
|
+
"sort_by": {
|
|
16123
|
+
"property": "title",
|
|
16124
|
+
"direction": "asc"
|
|
16125
|
+
},
|
|
16126
|
+
"colour_by": "type",
|
|
16127
|
+
"card_fields": [
|
|
16128
|
+
"title",
|
|
16129
|
+
"description",
|
|
16130
|
+
"status"
|
|
16131
|
+
]
|
|
16132
|
+
},
|
|
16133
|
+
"education": {
|
|
16134
|
+
"purpose": "Quantify the economic impact of not delivering a feature by a given date, making urgency visible and enabling time-sensitive prioritisation.",
|
|
16135
|
+
"core_question": "How much value are we losing every week this feature is not in production, and does that urgency justify fast-tracking it?",
|
|
16136
|
+
"when_to_use": [
|
|
16137
|
+
"You have more ideas or features than capacity to build them",
|
|
16138
|
+
"Stakeholders disagree on what to build next",
|
|
16139
|
+
"You need a transparent, defensible prioritisation process"
|
|
16140
|
+
],
|
|
16141
|
+
"when_not_to_use": [
|
|
16142
|
+
"You have a single obvious next step with no contention",
|
|
16143
|
+
"The backlog is small enough to sequence intuitively"
|
|
16144
|
+
]
|
|
16145
|
+
}
|
|
16146
|
+
},
|
|
16147
|
+
{
|
|
16148
|
+
"id": "five-whys",
|
|
16149
|
+
"approach_ids": [
|
|
16150
|
+
"reflect",
|
|
16151
|
+
"inspect"
|
|
16152
|
+
],
|
|
16153
|
+
"name": "Five Whys",
|
|
16154
|
+
"version": "1.0.0",
|
|
16155
|
+
"description": 'Iteratively ask "why?", typically five times, starting from a symptom; each answer becomes the subject of the next question. The chain of answers reveals the underlying root cause behind the surface problem.',
|
|
16156
|
+
"category": "team_process",
|
|
16157
|
+
"origin": {
|
|
16158
|
+
"type": "practitioner",
|
|
16159
|
+
"attribution": "Sakichi Toyoda / Toyota Production System",
|
|
16160
|
+
"description": "Developed within the Toyota Production System as a root-cause analysis technique. Popularised through Lean and Six Sigma practice; now a widely used incident-review and design-debug staple.",
|
|
16161
|
+
"year": 1930,
|
|
16162
|
+
"license": "public_domain"
|
|
16163
|
+
},
|
|
16164
|
+
"tags": [
|
|
16165
|
+
"team_process",
|
|
16166
|
+
"reflection",
|
|
16167
|
+
"root_cause",
|
|
16168
|
+
"tree"
|
|
16169
|
+
],
|
|
16170
|
+
"slots": [
|
|
16171
|
+
{
|
|
16172
|
+
"label": "Symptom",
|
|
16173
|
+
"entityTypeId": "need",
|
|
16174
|
+
"description": "The observed problem the analysis starts from."
|
|
16175
|
+
},
|
|
16176
|
+
{
|
|
16177
|
+
"label": "Why chain",
|
|
16178
|
+
"entityTypeId": "insight",
|
|
16179
|
+
"description": 'Each "why?" answer along the chain, typically five iterations deep.'
|
|
16180
|
+
},
|
|
16181
|
+
{
|
|
16182
|
+
"label": "Root cause",
|
|
16183
|
+
"entityTypeId": "insight",
|
|
16184
|
+
"description": "The terminal answer at the bottom of the chain: the underlying cause to address."
|
|
16185
|
+
}
|
|
16186
|
+
],
|
|
16187
|
+
"data": {
|
|
16188
|
+
"entity_types": [
|
|
16189
|
+
{
|
|
16190
|
+
"type": "need",
|
|
16191
|
+
"role": "root"
|
|
16192
|
+
},
|
|
16193
|
+
{
|
|
16194
|
+
"type": "insight",
|
|
16195
|
+
"role": "branch"
|
|
16196
|
+
}
|
|
16197
|
+
],
|
|
16198
|
+
"required_properties": {}
|
|
16199
|
+
},
|
|
16200
|
+
"structure": {
|
|
16201
|
+
"pattern": "tree"
|
|
16202
|
+
},
|
|
16203
|
+
"presentation": {
|
|
16204
|
+
"layout": {
|
|
16205
|
+
"type": "tree",
|
|
16206
|
+
"direction": "TB"
|
|
16207
|
+
},
|
|
16208
|
+
"sort_by": {
|
|
16209
|
+
"property": "title",
|
|
16210
|
+
"direction": "asc"
|
|
16211
|
+
},
|
|
16212
|
+
"card_fields": [
|
|
16213
|
+
"title",
|
|
16214
|
+
"description"
|
|
16215
|
+
]
|
|
16216
|
+
},
|
|
16217
|
+
"education": {
|
|
16218
|
+
"purpose": 'Move past surface symptoms by chaining "why?" questions until the underlying root cause surfaces, so fixes target the real driver rather than a downstream effect.',
|
|
16219
|
+
"core_question": "Why is this happening, and why is THAT happening, until we reach a cause we can act on?",
|
|
16220
|
+
"when_to_use": [
|
|
16221
|
+
"A problem keeps recurring after surface fixes",
|
|
16222
|
+
"Post-incident review where the obvious cause feels too obvious",
|
|
16223
|
+
"Designing a fix and you want to confirm you understand the actual driver"
|
|
16224
|
+
],
|
|
16225
|
+
"when_not_to_use": [
|
|
16226
|
+
"The problem has multiple independent root causes (use a fishbone or richer RCA tool)",
|
|
16227
|
+
"You need quantitative attribution rather than a single-thread narrative",
|
|
16228
|
+
'Five linear "whys" oversimplify a systems problem with feedback loops'
|
|
16229
|
+
]
|
|
16230
|
+
}
|
|
16231
|
+
},
|
|
16232
|
+
{
|
|
16233
|
+
"id": "pre-mortem",
|
|
16234
|
+
"approach_ids": [
|
|
16235
|
+
"reflect"
|
|
16236
|
+
],
|
|
16237
|
+
"name": "Pre-mortem",
|
|
16238
|
+
"version": "1.0.0",
|
|
16239
|
+
"description": "Imagine the project has already failed; work backward listing the plausible causes of the failure. Produce a risk register and matching mitigations before the work starts.",
|
|
16240
|
+
"category": "team_process",
|
|
16241
|
+
"origin": {
|
|
16242
|
+
"type": "practitioner",
|
|
16243
|
+
"attribution": "Gary Klein",
|
|
16244
|
+
"description": "Popularised by Gary Klein in Harvard Business Review (2007) as a prospective-hindsight technique. Inverts the post-mortem: imagine failure first, then list causes, while there is still time to act.",
|
|
16245
|
+
"url": "https://hbr.org/2007/09/performing-a-project-premortem",
|
|
16246
|
+
"year": 2007,
|
|
16247
|
+
"license": "published_methodology"
|
|
16248
|
+
},
|
|
16249
|
+
"tags": [
|
|
16250
|
+
"team_process",
|
|
16251
|
+
"reflection",
|
|
16252
|
+
"risk",
|
|
16253
|
+
"collection"
|
|
16254
|
+
],
|
|
16255
|
+
"slots": [
|
|
16256
|
+
{
|
|
16257
|
+
"label": "Imagined failures",
|
|
16258
|
+
"entityTypeId": "risk",
|
|
16259
|
+
"description": "Plausible failure modes named as if they had already occurred."
|
|
16260
|
+
},
|
|
16261
|
+
{
|
|
16262
|
+
"label": "Causes",
|
|
16263
|
+
"entityTypeId": "insight",
|
|
16264
|
+
"description": "For each imagined failure, the contributing causes the team can foresee."
|
|
16265
|
+
},
|
|
16266
|
+
{
|
|
16267
|
+
"label": "Mitigations",
|
|
16268
|
+
"entityTypeId": "initiative",
|
|
16269
|
+
"description": "Mitigation actions the team will take before failure can occur."
|
|
16270
|
+
}
|
|
16271
|
+
],
|
|
16272
|
+
"data": {
|
|
16273
|
+
"entity_types": [
|
|
16274
|
+
{
|
|
16275
|
+
"type": "risk",
|
|
16276
|
+
"role": "bucket"
|
|
16277
|
+
},
|
|
16278
|
+
{
|
|
16279
|
+
"type": "insight",
|
|
16280
|
+
"role": "bucket"
|
|
16281
|
+
},
|
|
16282
|
+
{
|
|
16283
|
+
"type": "initiative",
|
|
16284
|
+
"role": "bucket"
|
|
16285
|
+
}
|
|
16286
|
+
],
|
|
16287
|
+
"required_properties": {}
|
|
16288
|
+
},
|
|
16289
|
+
"structure": {
|
|
16290
|
+
"pattern": "collection"
|
|
16291
|
+
},
|
|
16292
|
+
"presentation": {
|
|
16293
|
+
"layout": {
|
|
16294
|
+
"type": "grid",
|
|
16295
|
+
"groupBy": "type"
|
|
16296
|
+
},
|
|
16297
|
+
"sort_by": {
|
|
16298
|
+
"property": "title",
|
|
16299
|
+
"direction": "asc"
|
|
16300
|
+
},
|
|
16301
|
+
"colour_by": "group",
|
|
16302
|
+
"card_fields": [
|
|
16303
|
+
"title",
|
|
16304
|
+
"description"
|
|
16305
|
+
]
|
|
16306
|
+
},
|
|
16307
|
+
"education": {
|
|
16308
|
+
"purpose": "Surface project risks early by inverting hindsight: imagine the project has already failed and ask why, while there is still time to mitigate.",
|
|
16309
|
+
"core_question": "It is six months from now and the project has failed catastrophically. What happened, and why?",
|
|
16310
|
+
"when_to_use": [
|
|
16311
|
+
"Kicking off a project with significant downside or irreversible commitment",
|
|
16312
|
+
"A plan looks too clean and the team senses unspoken concerns",
|
|
16313
|
+
"Stakeholders disagree on risk; the exercise externalises and ranks them"
|
|
16314
|
+
],
|
|
16315
|
+
"when_not_to_use": [
|
|
16316
|
+
"The work is small, reversible, and cheap to course-correct",
|
|
16317
|
+
"The team is in execution mode and reflective ceremonies will derail momentum",
|
|
16318
|
+
"Risk surfacing has become performative: the team names risks but never mitigates them"
|
|
16319
|
+
]
|
|
16320
|
+
}
|
|
16321
|
+
},
|
|
16322
|
+
{
|
|
16323
|
+
"id": "red-team",
|
|
16324
|
+
"approach_ids": [
|
|
16325
|
+
"reflect",
|
|
16326
|
+
"inspect"
|
|
16327
|
+
],
|
|
16328
|
+
"name": "Red Team",
|
|
16329
|
+
"version": "1.0.0",
|
|
16330
|
+
"description": "Structured adversarial review. A designated group is assigned to attack a plan, design, or proposal from an outside-in stance, surfacing weaknesses the inside-out builders cannot see.",
|
|
16331
|
+
"category": "team_process",
|
|
16332
|
+
"origin": {
|
|
16333
|
+
"type": "practitioner",
|
|
16334
|
+
"attribution": "US Department of Defense (Cold War era); broadened by security and intelligence practice",
|
|
16335
|
+
"description": `Originated in Cold War-era military strategic exercises ("red" team takes the adversary role against the "blue" team's defence). Adopted by cybersecurity, intelligence analysis, and product teams as a structured contrarian-review practice.`,
|
|
16336
|
+
"year": 1960,
|
|
16337
|
+
"license": "public_domain"
|
|
16338
|
+
},
|
|
16339
|
+
"tags": [
|
|
16340
|
+
"team_process",
|
|
16341
|
+
"reflection",
|
|
16342
|
+
"adversarial",
|
|
16343
|
+
"collection"
|
|
16344
|
+
],
|
|
16345
|
+
"slots": [
|
|
16346
|
+
{
|
|
16347
|
+
"label": "Target",
|
|
16348
|
+
"entityTypeId": "initiative",
|
|
16349
|
+
"description": "The plan, design, or proposal under adversarial review."
|
|
16350
|
+
},
|
|
16351
|
+
{
|
|
16352
|
+
"label": "Attack vectors",
|
|
16353
|
+
"entityTypeId": "risk",
|
|
16354
|
+
"description": "The angles the red team uses to probe weaknesses."
|
|
16355
|
+
},
|
|
16356
|
+
{
|
|
16357
|
+
"label": "Findings",
|
|
16358
|
+
"entityTypeId": "insight",
|
|
16359
|
+
"description": "Weaknesses, blind spots, or unstated assumptions surfaced by the review."
|
|
16360
|
+
}
|
|
16361
|
+
],
|
|
16362
|
+
"data": {
|
|
16363
|
+
"entity_types": [
|
|
16364
|
+
{
|
|
16365
|
+
"type": "initiative",
|
|
16366
|
+
"role": "root"
|
|
16367
|
+
},
|
|
16368
|
+
{
|
|
16369
|
+
"type": "risk",
|
|
16370
|
+
"role": "bucket"
|
|
16371
|
+
},
|
|
16372
|
+
{
|
|
16373
|
+
"type": "insight",
|
|
16374
|
+
"role": "bucket"
|
|
16375
|
+
}
|
|
16376
|
+
],
|
|
16377
|
+
"required_properties": {}
|
|
16378
|
+
},
|
|
16379
|
+
"structure": {
|
|
16380
|
+
"pattern": "collection"
|
|
16381
|
+
},
|
|
16382
|
+
"presentation": {
|
|
16383
|
+
"layout": {
|
|
16384
|
+
"type": "grid",
|
|
16385
|
+
"groupBy": "type"
|
|
16386
|
+
},
|
|
16387
|
+
"sort_by": {
|
|
16388
|
+
"property": "title",
|
|
16389
|
+
"direction": "asc"
|
|
16390
|
+
},
|
|
16391
|
+
"colour_by": "group",
|
|
16392
|
+
"card_fields": [
|
|
16393
|
+
"title",
|
|
16394
|
+
"description"
|
|
16395
|
+
]
|
|
16396
|
+
},
|
|
16397
|
+
"education": {
|
|
16398
|
+
"purpose": "Stress-test a plan against an explicit adversary by assigning reviewers to attack rather than agree, so weaknesses surface before reality finds them.",
|
|
16399
|
+
"core_question": "If a competent adversary wanted this to fail, where would they push first, and would we hold?",
|
|
16400
|
+
"when_to_use": [
|
|
16401
|
+
"A high-stakes decision, launch, or security posture needs hardening",
|
|
16402
|
+
"Inside-out thinking is dominant and dissent has gone quiet",
|
|
16403
|
+
"Risk register is suspiciously short for the size of the bet"
|
|
16404
|
+
],
|
|
16405
|
+
"when_not_to_use": [
|
|
16406
|
+
"Early-stage exploration where adversarial framing would crush a fragile idea prematurely",
|
|
16407
|
+
"Team trust is too low: red-teaming will read as personal attack rather than role-play",
|
|
16408
|
+
"The work is small enough that a lightweight devil's-advocate pass is sufficient"
|
|
16409
|
+
]
|
|
16410
|
+
}
|
|
16411
|
+
},
|
|
16412
|
+
{
|
|
16413
|
+
"id": "devils-advocate",
|
|
16414
|
+
"approach_ids": [
|
|
16415
|
+
"reflect"
|
|
16416
|
+
],
|
|
16417
|
+
"name": "Devil's Advocate",
|
|
16418
|
+
"version": "1.0.0",
|
|
16419
|
+
"description": "Designate one reviewer to formally take the opposing position regardless of personal view. The assigned-role contrarian defangs groupthink by making dissent legitimate and structured.",
|
|
16420
|
+
"category": "team_process",
|
|
16421
|
+
"origin": {
|
|
16422
|
+
"type": "practitioner",
|
|
16423
|
+
"attribution": "Roman Catholic Church (advocatus diaboli); broadened by decision-quality practice",
|
|
16424
|
+
"description": "Originated in 16th-century canonisation proceedings as the advocatus diaboli, an official assigned to argue against canonising a candidate. Adopted by decision-science and product-team practice as a structured antidote to groupthink.",
|
|
16425
|
+
"year": 1587,
|
|
16426
|
+
"license": "public_domain"
|
|
16427
|
+
},
|
|
16428
|
+
"tags": [
|
|
16429
|
+
"team_process",
|
|
16430
|
+
"reflection",
|
|
16431
|
+
"decision_quality",
|
|
16432
|
+
"collection"
|
|
16433
|
+
],
|
|
16434
|
+
"slots": [
|
|
16435
|
+
{
|
|
16436
|
+
"label": "Proposal",
|
|
16437
|
+
"entityTypeId": "initiative",
|
|
16438
|
+
"description": "The plan or recommendation under consideration."
|
|
16439
|
+
},
|
|
16440
|
+
{
|
|
16441
|
+
"label": "Opposing arguments",
|
|
16442
|
+
"entityTypeId": "insight",
|
|
16443
|
+
"description": "The case against the proposal, voiced by the assigned contrarian regardless of personal view."
|
|
16444
|
+
},
|
|
16445
|
+
{
|
|
16446
|
+
"label": "Counter-evidence",
|
|
16447
|
+
"entityTypeId": "evidence",
|
|
16448
|
+
"description": "Data points the contrarian raises that the proposal does not yet account for."
|
|
16449
|
+
}
|
|
16450
|
+
],
|
|
16451
|
+
"data": {
|
|
16452
|
+
"entity_types": [
|
|
16453
|
+
{
|
|
16454
|
+
"type": "initiative",
|
|
16455
|
+
"role": "root"
|
|
16456
|
+
},
|
|
16457
|
+
{
|
|
16458
|
+
"type": "insight",
|
|
16459
|
+
"role": "bucket"
|
|
16460
|
+
},
|
|
16461
|
+
{
|
|
16462
|
+
"type": "evidence",
|
|
16463
|
+
"role": "bucket"
|
|
16464
|
+
}
|
|
16465
|
+
],
|
|
16466
|
+
"required_properties": {}
|
|
16467
|
+
},
|
|
16468
|
+
"structure": {
|
|
16469
|
+
"pattern": "collection"
|
|
16470
|
+
},
|
|
16471
|
+
"presentation": {
|
|
16472
|
+
"layout": {
|
|
16473
|
+
"type": "grid",
|
|
16474
|
+
"groupBy": "type"
|
|
16475
|
+
},
|
|
16476
|
+
"sort_by": {
|
|
16477
|
+
"property": "title",
|
|
16478
|
+
"direction": "asc"
|
|
16479
|
+
},
|
|
16480
|
+
"colour_by": "group",
|
|
16481
|
+
"card_fields": [
|
|
16482
|
+
"title",
|
|
16483
|
+
"description"
|
|
16484
|
+
]
|
|
16485
|
+
},
|
|
16486
|
+
"education": {
|
|
16487
|
+
"purpose": "Make dissent a legitimate role rather than a personal stance. Assigning one reviewer to argue against the proposal forces the team to confront the strongest counter-case.",
|
|
16488
|
+
"core_question": "If we had to argue against this proposal (not because we believe it, but because the role demands it) what is the strongest case?",
|
|
16489
|
+
"when_to_use": [
|
|
16490
|
+
"A decision is heading toward consensus and you suspect groupthink",
|
|
16491
|
+
"Stakes are high and the team has not heard a serious counter-argument",
|
|
16492
|
+
"Cultural norms make raw dissent costly; assigning the role lowers the social cost"
|
|
16493
|
+
],
|
|
16494
|
+
"when_not_to_use": [
|
|
16495
|
+
"Genuine disagreement already exists in the room (let it surface; do not theatricalise it)",
|
|
16496
|
+
"The decision is small enough that the ceremony costs more than the insight returned",
|
|
16497
|
+
"The assigned contrarian will be punished socially for the role; set the norms first or skip"
|
|
16498
|
+
]
|
|
16499
|
+
}
|
|
16500
|
+
},
|
|
16501
|
+
{
|
|
16502
|
+
"id": "second-order-thinking",
|
|
16503
|
+
"approach_ids": [
|
|
16504
|
+
"reflect"
|
|
16505
|
+
],
|
|
16506
|
+
"name": "Second-order Thinking",
|
|
16507
|
+
"version": "1.0.0",
|
|
16508
|
+
"description": 'After deciding a move, ask "and then what?" repeatedly. Trace second-, third-, and higher-order consequences to surface downstream effects that first-order reasoning misses.',
|
|
16509
|
+
"category": "team_process",
|
|
16510
|
+
"origin": {
|
|
16511
|
+
"type": "practitioner",
|
|
16512
|
+
"attribution": "Howard Marks / Charlie Munger",
|
|
16513
|
+
"description": `Howard Marks distinguished first-order vs second-order thinking in The Most Important Thing (2011) as the essential discipline of consequential decision-making. Charlie Munger's "and then what?" framing is the practical heuristic.`,
|
|
16514
|
+
"url": "https://www.oaktreecapital.com/insights/memo/dare-to-be-great-ii",
|
|
16515
|
+
"year": 2011,
|
|
16516
|
+
"license": "published_methodology"
|
|
16517
|
+
},
|
|
16518
|
+
"tags": [
|
|
16519
|
+
"team_process",
|
|
16520
|
+
"reflection",
|
|
16521
|
+
"consequences",
|
|
16522
|
+
"tree"
|
|
16523
|
+
],
|
|
16524
|
+
"slots": [
|
|
16525
|
+
{
|
|
16526
|
+
"label": "First-order move",
|
|
16527
|
+
"entityTypeId": "decision",
|
|
16528
|
+
"description": "The decision or move under consideration."
|
|
16529
|
+
},
|
|
16530
|
+
{
|
|
16531
|
+
"label": "Second-order consequences",
|
|
16532
|
+
"entityTypeId": "insight",
|
|
16533
|
+
"description": "Downstream effects that follow from the first-order move."
|
|
16534
|
+
},
|
|
16535
|
+
{
|
|
16536
|
+
"label": "Higher-order consequences",
|
|
16537
|
+
"entityTypeId": "insight",
|
|
16538
|
+
"description": "Third-, fourth-, fifth-order ripples: second-order consequences of the second-order consequences."
|
|
16539
|
+
}
|
|
16540
|
+
],
|
|
16541
|
+
"data": {
|
|
16542
|
+
"entity_types": [
|
|
16543
|
+
{
|
|
16544
|
+
"type": "decision",
|
|
16545
|
+
"role": "root"
|
|
16546
|
+
},
|
|
16547
|
+
{
|
|
16548
|
+
"type": "insight",
|
|
16549
|
+
"role": "branch"
|
|
16550
|
+
}
|
|
16551
|
+
],
|
|
16552
|
+
"required_properties": {}
|
|
16553
|
+
},
|
|
16554
|
+
"structure": {
|
|
16555
|
+
"pattern": "tree"
|
|
16556
|
+
},
|
|
16557
|
+
"presentation": {
|
|
16558
|
+
"layout": {
|
|
16559
|
+
"type": "tree",
|
|
16560
|
+
"direction": "TB"
|
|
16561
|
+
},
|
|
16562
|
+
"sort_by": {
|
|
16563
|
+
"property": "title",
|
|
16564
|
+
"direction": "asc"
|
|
16565
|
+
},
|
|
16566
|
+
"card_fields": [
|
|
16567
|
+
"title",
|
|
16568
|
+
"description"
|
|
16569
|
+
]
|
|
16570
|
+
},
|
|
16571
|
+
"education": {
|
|
16572
|
+
"purpose": 'Resist first-order reasoning by chaining "and then what?" until non-obvious downstream consequences come into view.',
|
|
16573
|
+
"core_question": "If we make this move and it works, what does the world look like next, and is that the world we want?",
|
|
16574
|
+
"when_to_use": [
|
|
16575
|
+
"A decision has feedback loops, market reactions, or behavioural ripples",
|
|
16576
|
+
"The first-order case is compelling, which is exactly when downstream effects bite",
|
|
16577
|
+
"Considering an irreversible or large-scale commitment"
|
|
16578
|
+
],
|
|
16579
|
+
"when_not_to_use": [
|
|
16580
|
+
"Routine, reversible, low-blast-radius decisions where deliberation costs more than mistakes",
|
|
16581
|
+
"Higher-order branches diverge into pure speculation with no anchor in evidence",
|
|
16582
|
+
"Time pressure makes a deeper trace expensive and the first-order call is good enough"
|
|
16583
|
+
]
|
|
16584
|
+
}
|
|
16585
|
+
}
|
|
16586
|
+
];
|
|
16587
|
+
var UPG_FRAMEWORKS_BY_ID = Object.fromEntries(
|
|
16588
|
+
UPG_FRAMEWORKS.map((fw) => [fw.id, fw])
|
|
16589
|
+
);
|
|
16590
|
+
var UPG_FRAMEWORKS_BY_CATEGORY = {};
|
|
16591
|
+
for (const fw of UPG_FRAMEWORKS) {
|
|
16592
|
+
if (!UPG_FRAMEWORKS_BY_CATEGORY[fw.category]) UPG_FRAMEWORKS_BY_CATEGORY[fw.category] = [];
|
|
16593
|
+
UPG_FRAMEWORKS_BY_CATEGORY[fw.category].push(fw);
|
|
16594
|
+
}
|
|
16595
|
+
|
|
16596
|
+
// src/presentation/labels.ts
|
|
16597
|
+
var PRIORITY_LABELS = [
|
|
16598
|
+
// ── need (CONSOLIDATED: replaces pain_point + user_need) ─────────────────────
|
|
16599
|
+
{
|
|
16600
|
+
id: "need",
|
|
16601
|
+
canonical_label: "Need",
|
|
16602
|
+
alt_labels: [
|
|
16603
|
+
"pain point",
|
|
16604
|
+
"pain",
|
|
16605
|
+
"user need",
|
|
16606
|
+
"customer need",
|
|
16607
|
+
"problem",
|
|
16608
|
+
"struggle",
|
|
16609
|
+
"customer pain",
|
|
16610
|
+
"frustration",
|
|
16611
|
+
"gap",
|
|
16612
|
+
"unmet need",
|
|
16613
|
+
"user problem"
|
|
16614
|
+
],
|
|
16615
|
+
framework_labels: {
|
|
16616
|
+
lean_canvas: "Problem",
|
|
16617
|
+
design_thinking: "Pain Point",
|
|
16618
|
+
ost: "Opportunity (need)",
|
|
16619
|
+
jtbd: "Struggle",
|
|
16620
|
+
vpc: "Customer Pain"
|
|
16621
|
+
},
|
|
16622
|
+
designations: {
|
|
16623
|
+
pain: "Pain Point",
|
|
16624
|
+
gap: "Need",
|
|
16625
|
+
desire: "Desire",
|
|
16626
|
+
constraint: "Constraint"
|
|
16627
|
+
}
|
|
16628
|
+
},
|
|
16629
|
+
// ── opportunity ──────────────────────────────────────────────────────────────
|
|
16630
|
+
{
|
|
16631
|
+
id: "opportunity",
|
|
16632
|
+
canonical_label: "Opportunity",
|
|
16633
|
+
alt_labels: ["product opportunity", "market opportunity", "user opportunity"],
|
|
16634
|
+
framework_labels: {
|
|
16635
|
+
ost: "Opportunity"
|
|
16636
|
+
}
|
|
16637
|
+
},
|
|
16638
|
+
// ── solution ─────────────────────────────────────────────────────────────────
|
|
16639
|
+
{
|
|
16640
|
+
id: "solution",
|
|
16641
|
+
canonical_label: "Solution",
|
|
16642
|
+
alt_labels: ["proposed solution", "solution idea", "concept", "approach"],
|
|
16643
|
+
framework_labels: {
|
|
16644
|
+
ost: "Solution",
|
|
16645
|
+
design_thinking: "Solution",
|
|
16646
|
+
lean_canvas: "Solution",
|
|
16647
|
+
rice: "Scored Solution"
|
|
16648
|
+
}
|
|
16649
|
+
},
|
|
16650
|
+
// ── experiment (CONSOLIDATED: absorbs ab_test, growth_experiment, pricing_experiment) ──
|
|
16651
|
+
{
|
|
16652
|
+
id: "experiment",
|
|
16653
|
+
canonical_label: "Experiment",
|
|
16654
|
+
alt_labels: [
|
|
16655
|
+
"test",
|
|
16656
|
+
"validation",
|
|
16657
|
+
"ab test",
|
|
16658
|
+
"a/b test",
|
|
16659
|
+
"split test",
|
|
16660
|
+
"growth experiment",
|
|
16661
|
+
"pricing experiment",
|
|
16662
|
+
"usability test",
|
|
16663
|
+
"discovery experiment"
|
|
16664
|
+
],
|
|
16665
|
+
framework_labels: {
|
|
16666
|
+
ost: "Experiment",
|
|
16667
|
+
design_thinking: "Test",
|
|
16668
|
+
lean_startup: "Experiment"
|
|
16669
|
+
},
|
|
16670
|
+
designations: {
|
|
16671
|
+
discovery: "Discovery Experiment",
|
|
16672
|
+
ab_test: "A/B Test",
|
|
16673
|
+
growth: "Growth Experiment",
|
|
16674
|
+
pricing: "Pricing Experiment",
|
|
16675
|
+
usability: "Usability Test"
|
|
16676
|
+
}
|
|
16677
|
+
},
|
|
16678
|
+
// ── hypothesis ───────────────────────────────────────────────────────────────
|
|
16679
|
+
{
|
|
16680
|
+
id: "hypothesis",
|
|
16681
|
+
canonical_label: "Hypothesis",
|
|
16682
|
+
alt_labels: ["bet", "testable assumption", "leap of faith"],
|
|
16683
|
+
framework_labels: {
|
|
16684
|
+
lean_startup: "Hypothesis",
|
|
16685
|
+
running_lean: "Riskiest Assumption",
|
|
16686
|
+
lean_canvas: "Riskiest Assumption"
|
|
16687
|
+
}
|
|
16688
|
+
},
|
|
16689
|
+
// ── metric (CONSOLIDATED: absorbs kpi, north_star_metric, input_metric, metric_definition) ──
|
|
16690
|
+
{
|
|
16691
|
+
id: "metric",
|
|
16692
|
+
canonical_label: "Metric",
|
|
16693
|
+
alt_labels: [
|
|
16694
|
+
"kpi",
|
|
16695
|
+
"key performance indicator",
|
|
16696
|
+
"north star metric",
|
|
16697
|
+
"nsm",
|
|
16698
|
+
"input metric",
|
|
16699
|
+
"output metric",
|
|
16700
|
+
"metric definition",
|
|
16701
|
+
"measure",
|
|
16702
|
+
"indicator",
|
|
16703
|
+
"signal",
|
|
16704
|
+
"counter metric",
|
|
15687
16705
|
"guardrail metric"
|
|
15688
16706
|
],
|
|
15689
16707
|
framework_labels: {
|
|
@@ -16515,7 +17533,10 @@ var STRATEGY_OUTCOMES_PLAYBOOK = {
|
|
|
16515
17533
|
region: "strategy_outcomes",
|
|
16516
17534
|
is_canonical: true,
|
|
16517
17535
|
related_framework_ids: ["okr-framework", "three-horizons", "north-star-metric", "metrics-tree", "wardley-map"],
|
|
16518
|
-
|
|
17536
|
+
// DT-PB-3: anchor is `outcome`, not `objective`. The creation_sequence
|
|
17537
|
+
// creates outcome (step 3) before objective (step 4), and outcome is the
|
|
17538
|
+
// strategy region's gravitational centre (objectives translate outcomes).
|
|
17539
|
+
target_anchor_entity: "outcome",
|
|
16519
17540
|
creation_sequence: [
|
|
16520
17541
|
seqStep(
|
|
16521
17542
|
1,
|
|
@@ -16671,8 +17692,12 @@ var DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK = {
|
|
|
16671
17692
|
seqStep(
|
|
16672
17693
|
8,
|
|
16673
17694
|
"Test",
|
|
16674
|
-
|
|
16675
|
-
|
|
17695
|
+
// DT-PB-1: was `experiment` — which resolves to NO canonical edge with
|
|
17696
|
+
// hypothesis or test_plan, forcing an orphan. `experiment_run` is the
|
|
17697
|
+
// hypothesis-linked test unit (experiment_run_validates_hypothesis,
|
|
17698
|
+
// test_plan_ran_as_experiment_run, experiment_run_yields_evidence).
|
|
17699
|
+
["experiment_run", "test_plan", "evidence"],
|
|
17700
|
+
"Validate with targeted experiment runs. Close the loop between research and action."
|
|
16676
17701
|
)
|
|
16677
17702
|
]
|
|
16678
17703
|
};
|
|
@@ -16719,8 +17744,8 @@ var MARKET_COMPETITIVE_PLAYBOOK = {
|
|
|
16719
17744
|
seqStep(
|
|
16720
17745
|
6,
|
|
16721
17746
|
"Moves",
|
|
16722
|
-
["
|
|
16723
|
-
"Look where competitors are weak and trends are strong. That intersection is where your moves live
|
|
17747
|
+
["competitive_battle_card"],
|
|
17748
|
+
"Look where competitors are weak and trends are strong. That intersection is where your moves live: arm the team with battle cards that turn each competitor weakness into a position you can win. (Partnership moves belong in the business & GTM playbook, where `partnership` connects.)"
|
|
16724
17749
|
)
|
|
16725
17750
|
]
|
|
16726
17751
|
};
|
|
@@ -17133,8 +18158,8 @@ var OPERATIONS_QUALITY_PLAYBOOK = {
|
|
|
17133
18158
|
seqStep(
|
|
17134
18159
|
5,
|
|
17135
18160
|
"Quality Gates",
|
|
17136
|
-
["test_suite", "test_case", "regression_test", "qa_session"],
|
|
17137
|
-
"Establish what does not ship until tests pass. Define the test pyramid: unit, integration, end-to-end."
|
|
18161
|
+
["test_suite", "test_case", "regression_test", "qa_session", "feature", "bug"],
|
|
18162
|
+
"Establish what does not ship until tests pass. Define the test pyramid: unit, integration, end-to-end. Quality is a delivery concern: gates guard the features they cover and the bugs they catch, which is also where incidents trace back (a shipped defect becomes a production incident)."
|
|
17138
18163
|
),
|
|
17139
18164
|
seqStep(
|
|
17140
18165
|
6,
|
|
@@ -18789,7 +19814,7 @@ var PORTFOLIO_GUIDE = {
|
|
|
18789
19814
|
var WORKSPACE_GUIDE = {
|
|
18790
19815
|
domain_id: "workspace",
|
|
18791
19816
|
anchor_entity: "workspace",
|
|
18792
|
-
creation_sequence: ["workspace"],
|
|
19817
|
+
creation_sequence: ["workspace", "framework_exercise"],
|
|
18793
19818
|
patterns: [],
|
|
18794
19819
|
required_bridges: [],
|
|
18795
19820
|
anti_patterns: [
|
|
@@ -21201,7 +22226,7 @@ var UPG_ANTI_PATTERNS = [
|
|
|
21201
22226
|
]
|
|
21202
22227
|
},
|
|
21203
22228
|
why_it_matters: "Without any chain link, every downstream artefact (need, opportunity, feature) loses its anchor. Features end up addressing demographics instead of struggles.",
|
|
21204
|
-
remediation: "For each persona, connect it into the user chain via at least one of: `persona_pursues_job`, `persona_experiences_need`, `persona_aspires_to_desired_outcome`, or `persona_incurs_switching_cost`. Use `/upg-persona` or the JTBD canvas workflow.",
|
|
22229
|
+
remediation: "For each persona, connect it into the user chain via at least one of: `persona_pursues_job`, `persona_experiences_need`, `persona_aspires_to_desired_outcome`, or `persona_incurs_switching_cost`. Use `/upg-new-persona` or the JTBD canvas workflow.",
|
|
21205
22230
|
stages: ["concept", "validation", "build", "beta", "launch", "growth", "mature"],
|
|
21206
22231
|
severity: "high",
|
|
21207
22232
|
source: { kind: "practitioner", attribution: "Clayton Christensen, Jobs to Be Done" }
|
|
@@ -21341,7 +22366,7 @@ var UPG_ANTI_PATTERNS = [
|
|
|
21341
22366
|
]
|
|
21342
22367
|
},
|
|
21343
22368
|
why_it_matters: "OKRs without measurable key results cannot be tracked, debated, or learned from. The graph carries intent but not accountability.",
|
|
21344
|
-
remediation: "For each `objective`, define 2\u20134 `key_result` entities and link via `objective_achieved_through_key_result`. Use `/upg-okr` to author.",
|
|
22369
|
+
remediation: "For each `objective`, define 2\u20134 `key_result` entities and link via `objective_achieved_through_key_result`. Use `/upg-new-okr` to author.",
|
|
21345
22370
|
stages: ["validation", "build", "beta", "launch", "growth", "mature"],
|
|
21346
22371
|
severity: "high",
|
|
21347
22372
|
source: { kind: "book", citation: "Measure What Matters, John Doerr (2017)" }
|
|
@@ -21401,7 +22426,7 @@ var UPG_ANTI_PATTERNS = [
|
|
|
21401
22426
|
}
|
|
21402
22427
|
},
|
|
21403
22428
|
why_it_matters: 'A graph with one persona past validation is usually carrying an unexamined "everyone is the same user" assumption.',
|
|
21404
|
-
remediation: "Add personas representing the next 1\u20132 most distinct user segments. Use `/upg-persona`.",
|
|
22429
|
+
remediation: "Add personas representing the next 1\u20132 most distinct user segments. Use `/upg-new-persona`.",
|
|
21405
22430
|
stages: ["validation", "build", "beta", "launch", "growth", "mature"],
|
|
21406
22431
|
severity: "medium",
|
|
21407
22432
|
source: { kind: "practitioner", attribution: "Alan Cooper, The Inmates Are Running the Asylum" }
|
|
@@ -21419,7 +22444,7 @@ var UPG_ANTI_PATTERNS = [
|
|
|
21419
22444
|
]
|
|
21420
22445
|
},
|
|
21421
22446
|
why_it_matters: "Build-only graphs commit the team to delivery without a learning loop. Every shipped feature becomes a permanent assumption.",
|
|
21422
|
-
remediation: "Spin up at least one `experiment_plan` or `hypothesis` per quarter's build batch. Use `/upg-
|
|
22447
|
+
remediation: "Spin up at least one `experiment_plan` or `hypothesis` per quarter's build batch. Use `/upg-new-discovery` or `/upg-new-hypothesis`.",
|
|
21423
22448
|
stages: ["build", "beta", "launch", "growth"],
|
|
21424
22449
|
severity: "high",
|
|
21425
22450
|
source: { kind: "practitioner", attribution: "Marty Cagan, Inspired (continuous discovery)" }
|
|
@@ -21710,19 +22735,31 @@ var REFLECT_MODES = [
|
|
|
21710
22735
|
];
|
|
21711
22736
|
|
|
21712
22737
|
// src/approaches/definitions/index.ts
|
|
22738
|
+
function deriveFrameworkExamples() {
|
|
22739
|
+
const byApproach = {
|
|
22740
|
+
plan: [],
|
|
22741
|
+
inspect: [],
|
|
22742
|
+
prioritise: [],
|
|
22743
|
+
trace: [],
|
|
22744
|
+
reflect: []
|
|
22745
|
+
};
|
|
22746
|
+
for (const fw of UPG_FRAMEWORKS) {
|
|
22747
|
+
for (const approachId of fw.approach_ids ?? []) {
|
|
22748
|
+
if (approachId in byApproach) {
|
|
22749
|
+
byApproach[approachId].push(fw.id);
|
|
22750
|
+
}
|
|
22751
|
+
}
|
|
22752
|
+
}
|
|
22753
|
+
return byApproach;
|
|
22754
|
+
}
|
|
22755
|
+
var FRAMEWORK_EXAMPLES = deriveFrameworkExamples();
|
|
21713
22756
|
var PLAN = {
|
|
21714
22757
|
id: "plan",
|
|
21715
22758
|
label: "Plan",
|
|
21716
22759
|
description: 'The path of arrival to "what should I build next?". Plan engages a region by surveying its entity coverage against canonical expectations and surfacing the missing scaffolding: the entities a healthy region carries that this graph does not. Cartographic sense: you are walking the coastline of a region and noting where the contour is incomplete, not deciding a strategy. Frameworks like Now/Next/Later, MoSCoW, and Wardley Mapping live within Plan as the named techniques for organising the gap-filling sequence.',
|
|
21717
22760
|
question_answered: "what should I build next?",
|
|
21718
22761
|
signature_hint: "({ region?: UPGRegionId }) \u2192 { missing_entities, coverage_score }",
|
|
21719
|
-
framework_id_examples:
|
|
21720
|
-
"now-next-later",
|
|
21721
|
-
"moscow",
|
|
21722
|
-
"wardley-map",
|
|
21723
|
-
"okr-framework",
|
|
21724
|
-
"three-horizons"
|
|
21725
|
-
]
|
|
22762
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.plan
|
|
21726
22763
|
};
|
|
21727
22764
|
var INSPECT = {
|
|
21728
22765
|
id: "inspect",
|
|
@@ -21730,28 +22767,15 @@ var INSPECT = {
|
|
|
21730
22767
|
description: 'The path of arrival to "what\'s broken?". Inspect engages a region or a set of entities by running canonical health checks (anti-pattern audits, drift reports, lint passes) and emitting a structured violation list with severity, kind, target entity, description, and fix hint. Cartographic sense: you are surveying the coastline for hazards before approach; the violations are the rocks marked on the chart. The named techniques inside Inspect are the audit catalogues themselves (`UPG_ANTI_PATTERNS` and the lint passes built on the structural rules).',
|
|
21731
22768
|
question_answered: "what's broken?",
|
|
21732
22769
|
signature_hint: "({ region?: UPGRegionId, entities?: entity_ids[] }) \u2192 { violations: [{ severity, kind, entity_id, description, fix_hint }] }",
|
|
21733
|
-
framework_id_examples:
|
|
21734
|
-
"heuristic-evaluation",
|
|
21735
|
-
"tech-debt-tracker",
|
|
21736
|
-
"accessibility-maturity-model",
|
|
21737
|
-
"cognitive-walkthrough",
|
|
21738
|
-
"blameless-postmortem"
|
|
21739
|
-
]
|
|
22770
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.inspect
|
|
21740
22771
|
};
|
|
21741
22772
|
var PRIORITISE = {
|
|
21742
22773
|
id: "prioritise",
|
|
21743
22774
|
label: "Prioritise",
|
|
21744
|
-
description: `The path of arrival to "what's most important?". Prioritise engages an explicit candidate set (entity ids the caller passes in) and ranks it by an explicit framework: RICE,
|
|
22775
|
+
description: `The path of arrival to "what's most important?". Prioritise engages an explicit candidate set (entity ids the caller passes in) and ranks it by an explicit framework: RICE, Kano, MoSCoW. The framework_id is required because prioritisation without a declared scoring lens is incoherent. Cartographic sense: you have a set of charted destinations and you are computing the order of arrival from a chosen vantage. Different frameworks weight the same candidate set differently; the approach delegates the actual ranking math to the named technique (the framework definition).`,
|
|
21745
22776
|
question_answered: "what's most important?",
|
|
21746
22777
|
signature_hint: "({ candidates: entity_ids[], framework_id }) \u2192 { ranked: [{ entity_id, score, rationale }], framework_used }",
|
|
21747
|
-
framework_id_examples:
|
|
21748
|
-
"rice-scoring",
|
|
21749
|
-
"ice-scoring",
|
|
21750
|
-
"kano-model",
|
|
21751
|
-
"cost-of-delay",
|
|
21752
|
-
"moscow",
|
|
21753
|
-
"wsjf"
|
|
21754
|
-
]
|
|
22778
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.prioritise
|
|
21755
22779
|
};
|
|
21756
22780
|
var TRACE = {
|
|
21757
22781
|
id: "trace",
|
|
@@ -21759,34 +22783,15 @@ var TRACE = {
|
|
|
21759
22783
|
description: 'The path of arrival to "walk a meaningful path through existing graph". Trace engages an anchor entity and follows a path expressed as a UPGEntityType[] shorthand. Example: `["persona", "job", "feature"]` walks persona\u2192job\u2192feature using the canonical edge for each pair (resolved via `resolve_edge_for_pair`). An optional `edges_override` array selects non-canonical edges per hop when a pair has multiple resolutions. Cartographic sense: you are tracing a route across charted terrain; anchor is the departure, path is the heading sequence, the canonical edges are the roads. No DSL invented; the shorthand IS the path expression.',
|
|
21760
22784
|
question_answered: "walk a meaningful path through existing graph",
|
|
21761
22785
|
signature_hint: "({ anchor: entity_id, path: UPGEntityType[], edges_override?: (string | null)[] }) \u2192 { trail: [{ depth, entity_id, edge_type_in }], reached: entity_id[] }",
|
|
21762
|
-
framework_id_examples:
|
|
21763
|
-
"opportunity-solution-tree",
|
|
21764
|
-
"strategic-cascade",
|
|
21765
|
-
"metrics-tree",
|
|
21766
|
-
"user-journey-map",
|
|
21767
|
-
"impact-map",
|
|
21768
|
-
"dependency-map"
|
|
21769
|
-
]
|
|
22786
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.trace
|
|
21770
22787
|
};
|
|
21771
22788
|
var REFLECT = {
|
|
21772
22789
|
id: "reflect",
|
|
21773
22790
|
label: "Reflect",
|
|
21774
|
-
description: 'The path of arrival to "what should I be questioning?". Reflect engages an optional scope (region, entity, or `null` for the whole graph) and emits structured prompts a thinker should consider: assumptions to test, alternatives to weigh, blind-spots to surface, load-bearing claims to verify. Mode is optional; absence is open reflection. Cartographic sense: before approaching the coastline, you are asking which features of your chart you have not actually verified; the prompts mark the parts of the map that may be conjecture.
|
|
22791
|
+
description: 'The path of arrival to "what should I be questioning?". Reflect engages an optional scope (region, entity, or `null` for the whole graph) and emits structured prompts a thinker should consider: assumptions to test, alternatives to weigh, blind-spots to surface, load-bearing claims to verify. Mode is optional; absence is open reflection. Cartographic sense: before approaching the coastline, you are asking which features of your chart you have not actually verified; the prompts mark the parts of the map that may be conjecture. Retrospective and Build-Measure-Learn are the named reflective techniques in the canonical surface.',
|
|
21775
22792
|
question_answered: "what should I be questioning?",
|
|
21776
22793
|
signature_hint: "({ scope?: UPGRegionId | entity_id | null, mode?: 'assumptions' | 'alternatives' | 'blind-spots' | 'load-bearing' }) \u2192 { prompts: [{ kind, question, target_entities? }] }",
|
|
21777
|
-
framework_id_examples:
|
|
21778
|
-
// Reflection classics: the five canonical reflect frameworks.
|
|
21779
|
-
"five-whys",
|
|
21780
|
-
"pre-mortem",
|
|
21781
|
-
"red-team",
|
|
21782
|
-
"devils-advocate",
|
|
21783
|
-
"second-order-thinking",
|
|
21784
|
-
// Reflective ceremonies + reflective JTBD lens already in the catalog.
|
|
21785
|
-
"retrospective",
|
|
21786
|
-
"four-forces-of-progress",
|
|
21787
|
-
"assumption-canvas",
|
|
21788
|
-
"win-loss-analysis"
|
|
21789
|
-
]
|
|
22794
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.reflect
|
|
21790
22795
|
};
|
|
21791
22796
|
var UPG_APPROACHES = [PLAN, INSPECT, PRIORITISE, TRACE, REFLECT];
|
|
21792
22797
|
var UPG_APPROACHES_BY_ID = Object.fromEntries(
|
|
@@ -23817,7 +24822,7 @@ var NODE_KEY_ORDER = [
|
|
|
23817
24822
|
"sort_order",
|
|
23818
24823
|
"properties"
|
|
23819
24824
|
];
|
|
23820
|
-
var EDGE_KEY_ORDER = ["id", "source", "target", "type", "mapping_confidence"];
|
|
24825
|
+
var EDGE_KEY_ORDER = ["id", "source", "target", "type", "mapping_confidence", "properties"];
|
|
23821
24826
|
var CROSS_EDGE_KEY_ORDER = ["id", "source", "target", "type", "source_product_id", "target_product_id", "mapping_confidence"];
|
|
23822
24827
|
var PRODUCT_KEY_ORDER = ["id", "title", "description", "stage", "properties"];
|
|
23823
24828
|
function canonicalNode(node) {
|
|
@@ -23829,7 +24834,8 @@ function canonicalNode(node) {
|
|
|
23829
24834
|
}
|
|
23830
24835
|
function canonicalEdge(edge) {
|
|
23831
24836
|
return orderedObject(edge, EDGE_KEY_ORDER, {
|
|
23832
|
-
forceKeys: ["id", "source", "target", "type"]
|
|
24837
|
+
forceKeys: ["id", "source", "target", "type"],
|
|
24838
|
+
openKeys: ["properties"]
|
|
23833
24839
|
});
|
|
23834
24840
|
}
|
|
23835
24841
|
function canonicalCrossEdge(edge) {
|
|
@@ -23983,7 +24989,7 @@ function isCanonical(text) {
|
|
|
23983
24989
|
}
|
|
23984
24990
|
|
|
23985
24991
|
// src/index.ts
|
|
23986
|
-
var UPG_VERSION = "0.8.
|
|
24992
|
+
var UPG_VERSION = "0.8.4";
|
|
23987
24993
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
23988
24994
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
23989
24995
|
var UPG_TYPES = getTypes();
|
|
@@ -24132,6 +25138,7 @@ var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
|
24132
25138
|
collectSlugsForType,
|
|
24133
25139
|
compareVersions,
|
|
24134
25140
|
computeBodyChecksum,
|
|
25141
|
+
edgeCarriesProperties,
|
|
24135
25142
|
evaluateAntiPatterns,
|
|
24136
25143
|
findInvalidStatusMigrationTargets,
|
|
24137
25144
|
formatUpgText,
|