@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.js
CHANGED
|
@@ -486,8 +486,8 @@ var UPG_DOMAINS = [
|
|
|
486
486
|
{
|
|
487
487
|
id: "workspace",
|
|
488
488
|
label: "Workspace",
|
|
489
|
-
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.",
|
|
490
|
-
types: ["workspace"]
|
|
489
|
+
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.",
|
|
490
|
+
types: ["workspace", "framework_exercise"]
|
|
491
491
|
}
|
|
492
492
|
];
|
|
493
493
|
var UPG_ENTITY_TO_DOMAIN = Object.freeze(
|
|
@@ -913,7 +913,8 @@ var UPG_ENTITY_META = [
|
|
|
913
913
|
{ name: "integration_partner", type_id: "ent_311", maturity: "stable", since: "0.1.0" },
|
|
914
914
|
{ name: "partner_revenue_share", type_id: "ent_312", maturity: "stable", since: "0.1.0" },
|
|
915
915
|
// ── Workspace ──
|
|
916
|
-
{ name: "workspace", type_id: "ent_328", maturity: "proposed", since: "0.2.0" }
|
|
916
|
+
{ name: "workspace", type_id: "ent_328", maturity: "proposed", since: "0.2.0" },
|
|
917
|
+
{ name: "framework_exercise", type_id: "ent_350", maturity: "proposed", since: "0.8.4" }
|
|
917
918
|
];
|
|
918
919
|
var UPG_ENTITY_META_BY_NAME = new Map(
|
|
919
920
|
UPG_ENTITY_META.map((m) => [m.name, m])
|
|
@@ -946,7 +947,7 @@ var UPG_EDGE_CATALOG = {
|
|
|
946
947
|
// product → persona is the most fundamental relationship in the
|
|
947
948
|
// user domain ("who is this product for?") and was the only way to
|
|
948
949
|
// anchor a fresh persona to its product before this edge existed. Without
|
|
949
|
-
// it, the natural agent path through `/upg-persona` produced an orphan
|
|
950
|
+
// it, the natural agent path through `/upg-new-persona` produced an orphan
|
|
950
951
|
// persona only attached laterally via `ideal_customer_profile_maps_to_persona`
|
|
951
952
|
// or `positioning_resonates_with_persona`. Semantic, not hierarchy: a
|
|
952
953
|
// product doesn't "contain" personas; it targets them.
|
|
@@ -2066,6 +2067,18 @@ var UPG_EDGE_CATALOG = {
|
|
|
2066
2067
|
// universal across the DDD type family. Verbs follow DDD literature:
|
|
2067
2068
|
// aggregate belongs_to context, context contains aggregates.
|
|
2068
2069
|
node_belongs_to_bounded_context: { forward_verb: "belongs_to", reverse_verb: "contains", classification: "cross-domain", source_type: "node", target_type: "bounded_context" },
|
|
2070
|
+
// ── Cross-domain: Framework exercises ────────────────────────────────────────
|
|
2071
|
+
// A framework_exercise is one run of a framework (MoSCoW, RICE, Kano, …) over a
|
|
2072
|
+
// set of entities. It `includes` each entity it touches; the framework's
|
|
2073
|
+
// per-entity result — a MoSCoW bucket, a RICE score, a canvas slot, a funnel
|
|
2074
|
+
// stage — rides on this edge's `properties`, NOT on the entity node. A value
|
|
2075
|
+
// that exists only within a specific exercise is a fact about the relationship,
|
|
2076
|
+
// not the entity, so it lives on the edge (same principle as owner-as-edge).
|
|
2077
|
+
// Polymorphic (`target_type: 'node'`): an exercise can include any entity type,
|
|
2078
|
+
// which closes the feature-only limitation structurally. `carries_properties`
|
|
2079
|
+
// opts this edge into the gated edge-property model. See ADR
|
|
2080
|
+
// 2026-06-02-framework-exercises.
|
|
2081
|
+
framework_exercise_includes_node: { forward_verb: "includes", reverse_verb: "included_in", classification: "cross-domain", source_type: "framework_exercise", target_type: "node", carries_properties: true },
|
|
2069
2082
|
// ── New edges replacing deleted string properties ────────────────────
|
|
2070
2083
|
// Marketing
|
|
2071
2084
|
marketing_strategy_pursues_outcome: { forward_verb: "pursues", reverse_verb: "pursued_by", classification: "cross-domain", source_type: "marketing_strategy", target_type: "outcome" },
|
|
@@ -2161,6 +2174,13 @@ var UPG_EDGE_CATALOG = {
|
|
|
2161
2174
|
// release strategy to the concrete deployments it governs.
|
|
2162
2175
|
incident_affects_feature: { forward_verb: "affects", reverse_verb: "affected_by", classification: "cross-domain", source_type: "incident", target_type: "feature" },
|
|
2163
2176
|
release_strategy_used_by_deployment: { forward_verb: "used_by", reverse_verb: "uses", classification: "cross-domain", source_type: "release_strategy", target_type: "deployment" },
|
|
2177
|
+
// v0.8.2 (UPG-615): ITIL/ITSM incident management explicitly links an incident
|
|
2178
|
+
// to the customer-facing support tickets/cases it spawns — when a service
|
|
2179
|
+
// breaks, customers raise tickets; the incident is the cause, the ticket the
|
|
2180
|
+
// effect. Closes the otherwise-unmediated "Customer Support" island in
|
|
2181
|
+
// `playbook:operations-quality`, binding `support_ticket` to the incident/ops
|
|
2182
|
+
// spine. Source: ITIL v4 incident management; DORA/SRE customer-facing impact.
|
|
2183
|
+
incident_generates_support_ticket: { forward_verb: "generates", reverse_verb: "generated_by", classification: "cross-domain", source_type: "incident", target_type: "support_ticket" },
|
|
2164
2184
|
// Cluster C: User Research linkage matrix.
|
|
2165
2185
|
// research_study → {participant, research_question, survey_response,
|
|
2166
2186
|
// interview_guide} containment edges already exist (49/49 in Wave 4).
|
|
@@ -2688,7 +2708,9 @@ var UPG_POLYMORPHIC_EDGE_KEYS = [
|
|
|
2688
2708
|
"node_owned_by_department",
|
|
2689
2709
|
"node_owned_by_person",
|
|
2690
2710
|
// Universal architecture references
|
|
2691
|
-
"node_belongs_to_bounded_context"
|
|
2711
|
+
"node_belongs_to_bounded_context",
|
|
2712
|
+
// Framework exercises (an exercise can include any entity type)
|
|
2713
|
+
"framework_exercise_includes_node"
|
|
2692
2714
|
];
|
|
2693
2715
|
var _POLY_KEY_SET = new Set(UPG_POLYMORPHIC_EDGE_KEYS);
|
|
2694
2716
|
function isPolymorphicEdge(key) {
|
|
@@ -2698,6 +2720,10 @@ function isPolymorphicEdge(key) {
|
|
|
2698
2720
|
function isRegisteredPolymorphicEdge(key) {
|
|
2699
2721
|
return _POLY_KEY_SET.has(key);
|
|
2700
2722
|
}
|
|
2723
|
+
function edgeCarriesProperties(type) {
|
|
2724
|
+
const def = UPG_EDGE_CATALOG[type];
|
|
2725
|
+
return def?.carries_properties === true;
|
|
2726
|
+
}
|
|
2701
2727
|
|
|
2702
2728
|
// src/catalog/legacy-product-stages.ts
|
|
2703
2729
|
var LEGACY_PRODUCT_STAGES = Object.freeze({
|
|
@@ -3349,7 +3375,13 @@ function canBeChildOf(childType, parentType) {
|
|
|
3349
3375
|
return getValidChildren(parentType).includes(childType);
|
|
3350
3376
|
}
|
|
3351
3377
|
var UPG_CONTAINMENT_FREE_TYPES = /* @__PURE__ */ new Set([
|
|
3352
|
-
"person"
|
|
3378
|
+
"person",
|
|
3379
|
+
// A framework_exercise has no structural parent: it anchors to the entities
|
|
3380
|
+
// it scores via the `framework_exercise_includes_node` edge, not by
|
|
3381
|
+
// containment. Modelling it as a product child would force a containment edge
|
|
3382
|
+
// and read against the whole point of the exercise model (relational, not
|
|
3383
|
+
// hierarchical). Same posture as `person`. See ADR 2026-06-02-framework-exercises.
|
|
3384
|
+
"framework_exercise"
|
|
3353
3385
|
]);
|
|
3354
3386
|
function isContainmentFreeType(entityType) {
|
|
3355
3387
|
return UPG_CONTAINMENT_FREE_TYPES.has(entityType);
|
|
@@ -5651,6 +5683,31 @@ var TEMPLATE_LIFECYCLES = [
|
|
|
5651
5683
|
// ── Phase B: SALES_DEAL (qualified → proposal → negotiation → won/lost) ─────
|
|
5652
5684
|
fromTemplate("deal", SALES_DEAL_TEMPLATE)
|
|
5653
5685
|
];
|
|
5686
|
+
var FRAMEWORK_EXERCISE_LIFECYCLE = {
|
|
5687
|
+
entity_type: "framework_exercise",
|
|
5688
|
+
initial_phase: "draft",
|
|
5689
|
+
terminal_phases: ["archived"],
|
|
5690
|
+
phases: [
|
|
5691
|
+
{
|
|
5692
|
+
id: "draft",
|
|
5693
|
+
label: "Draft",
|
|
5694
|
+
description: "The exercise has been created and entities pulled into scope, but the framework's inputs have not all been filled in yet.",
|
|
5695
|
+
transitions_to: ["active", "archived"]
|
|
5696
|
+
},
|
|
5697
|
+
{
|
|
5698
|
+
id: "active",
|
|
5699
|
+
label: "Active",
|
|
5700
|
+
description: "The current, authoritative run of its framework. Its include edges carry the live results consumers read, rank, and render by.",
|
|
5701
|
+
transitions_to: ["archived"]
|
|
5702
|
+
},
|
|
5703
|
+
{
|
|
5704
|
+
id: "archived",
|
|
5705
|
+
label: "Archived",
|
|
5706
|
+
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.",
|
|
5707
|
+
transitions_to: ["active"]
|
|
5708
|
+
}
|
|
5709
|
+
]
|
|
5710
|
+
};
|
|
5654
5711
|
var UPG_LIFECYCLES = [
|
|
5655
5712
|
// Product (root)
|
|
5656
5713
|
PRODUCT_LIFECYCLE,
|
|
@@ -5752,6 +5809,8 @@ var UPG_LIFECYCLES = [
|
|
|
5752
5809
|
// Product & Growth
|
|
5753
5810
|
VARIANT_LIFECYCLE,
|
|
5754
5811
|
GROWTH_CAMPAIGN_LIFECYCLE,
|
|
5812
|
+
// Workspace
|
|
5813
|
+
FRAMEWORK_EXERCISE_LIFECYCLE,
|
|
5755
5814
|
// ── Template-generated lifecycles ─────────────────────────────────
|
|
5756
5815
|
...TEMPLATE_LIFECYCLES
|
|
5757
5816
|
];
|
|
@@ -9941,6 +10000,11 @@ var UPG_PROPERTY_SCHEMA = {
|
|
|
9941
10000
|
},
|
|
9942
10001
|
methodology: { type: "string", description: "Forecasting methodology used" }
|
|
9943
10002
|
},
|
|
10003
|
+
// FrameworkExerciseProperties: Framework exercise: one run of a framework over a set of entities.
|
|
10004
|
+
framework_exercise: {
|
|
10005
|
+
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." },
|
|
10006
|
+
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)." }
|
|
10007
|
+
},
|
|
9944
10008
|
// FunnelProperties: Funnel entity.
|
|
9945
10009
|
funnel: {
|
|
9946
10010
|
funnel_type: { type: "string", enum: ["acquisition", "activation", "retention", "revenue", "referral", "custom"], description: "Which stage of the customer lifecycle this funnel measures" },
|
|
@@ -11968,6 +12032,9 @@ var UPG_FRAMEWORKS = [
|
|
|
11968
12032
|
},
|
|
11969
12033
|
{
|
|
11970
12034
|
"id": "value-proposition-canvas",
|
|
12035
|
+
"approach_ids": [
|
|
12036
|
+
"trace"
|
|
12037
|
+
],
|
|
11971
12038
|
"name": "Value Proposition Canvas",
|
|
11972
12039
|
"version": "1.0.0",
|
|
11973
12040
|
"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.",
|
|
@@ -12072,6 +12139,9 @@ var UPG_FRAMEWORKS = [
|
|
|
12072
12139
|
},
|
|
12073
12140
|
{
|
|
12074
12141
|
"id": "persona-canvas",
|
|
12142
|
+
"approach_ids": [
|
|
12143
|
+
"trace"
|
|
12144
|
+
],
|
|
12075
12145
|
"name": "Persona Canvas",
|
|
12076
12146
|
"version": "1.0.0",
|
|
12077
12147
|
"description": "Demographics, goals, frustrations, JTBD: a structured template for creating research-backed personas.",
|
|
@@ -12184,6 +12254,9 @@ var UPG_FRAMEWORKS = [
|
|
|
12184
12254
|
},
|
|
12185
12255
|
{
|
|
12186
12256
|
"id": "empathy-map",
|
|
12257
|
+
"approach_ids": [
|
|
12258
|
+
"trace"
|
|
12259
|
+
],
|
|
12187
12260
|
"name": "Empathy Map",
|
|
12188
12261
|
"version": "1.0.0",
|
|
12189
12262
|
"description": "Visualise what a user says, thinks, does, and feels to build deeper empathy and uncover hidden needs.",
|
|
@@ -12344,6 +12417,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12344
12417
|
"property": "evolution_stage",
|
|
12345
12418
|
"type": "enum",
|
|
12346
12419
|
"required": true,
|
|
12420
|
+
"scope": "framework",
|
|
12347
12421
|
"label": "Evolution Stage",
|
|
12348
12422
|
"description": "Where this component sits on the evolution axis",
|
|
12349
12423
|
"enum_values": [
|
|
@@ -12357,6 +12431,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12357
12431
|
"property": "visibility",
|
|
12358
12432
|
"type": "number",
|
|
12359
12433
|
"required": true,
|
|
12434
|
+
"scope": "framework",
|
|
12360
12435
|
"label": "Visibility",
|
|
12361
12436
|
"description": "Y-axis position (0=infrastructure, 1=anchor/user)"
|
|
12362
12437
|
}
|
|
@@ -12366,6 +12441,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12366
12441
|
"property": "evolution_stage",
|
|
12367
12442
|
"type": "enum",
|
|
12368
12443
|
"required": true,
|
|
12444
|
+
"scope": "framework",
|
|
12369
12445
|
"label": "Evolution Stage",
|
|
12370
12446
|
"description": "Where this component sits on the evolution axis",
|
|
12371
12447
|
"enum_values": [
|
|
@@ -12379,6 +12455,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12379
12455
|
"property": "visibility",
|
|
12380
12456
|
"type": "number",
|
|
12381
12457
|
"required": true,
|
|
12458
|
+
"scope": "framework",
|
|
12382
12459
|
"label": "Visibility",
|
|
12383
12460
|
"description": "Y-axis position (0=infrastructure, 1=anchor/user)"
|
|
12384
12461
|
}
|
|
@@ -12388,6 +12465,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12388
12465
|
"property": "evolution_stage",
|
|
12389
12466
|
"type": "enum",
|
|
12390
12467
|
"required": true,
|
|
12468
|
+
"scope": "framework",
|
|
12391
12469
|
"label": "Evolution Stage",
|
|
12392
12470
|
"description": "Where this component sits on the evolution axis",
|
|
12393
12471
|
"enum_values": [
|
|
@@ -12401,6 +12479,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12401
12479
|
"property": "visibility",
|
|
12402
12480
|
"type": "number",
|
|
12403
12481
|
"required": true,
|
|
12482
|
+
"scope": "framework",
|
|
12404
12483
|
"label": "Visibility",
|
|
12405
12484
|
"description": "Y-axis position (0=infrastructure, 1=anchor/user)"
|
|
12406
12485
|
}
|
|
@@ -12410,6 +12489,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12410
12489
|
"property": "evolution_stage",
|
|
12411
12490
|
"type": "enum",
|
|
12412
12491
|
"required": true,
|
|
12492
|
+
"scope": "framework",
|
|
12413
12493
|
"label": "Evolution Stage",
|
|
12414
12494
|
"description": 'Where this component sits on the evolution axis (need anchor is usually at "product" or "commodity")',
|
|
12415
12495
|
"enum_values": [
|
|
@@ -12423,6 +12503,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12423
12503
|
"property": "visibility",
|
|
12424
12504
|
"type": "number",
|
|
12425
12505
|
"required": true,
|
|
12506
|
+
"scope": "framework",
|
|
12426
12507
|
"label": "Visibility",
|
|
12427
12508
|
"description": "Y-axis position (0=infrastructure, 1=anchor/user); needs sit at 1.0"
|
|
12428
12509
|
}
|
|
@@ -12463,6 +12544,9 @@ var UPG_FRAMEWORKS = [
|
|
|
12463
12544
|
},
|
|
12464
12545
|
{
|
|
12465
12546
|
"id": "business-model-canvas",
|
|
12547
|
+
"approach_ids": [
|
|
12548
|
+
"plan"
|
|
12549
|
+
],
|
|
12466
12550
|
"name": "Business Model Canvas",
|
|
12467
12551
|
"version": "1.0.0",
|
|
12468
12552
|
"description": "Nine building blocks that describe how an organisation creates, delivers, and captures value.",
|
|
@@ -12602,6 +12686,9 @@ var UPG_FRAMEWORKS = [
|
|
|
12602
12686
|
},
|
|
12603
12687
|
{
|
|
12604
12688
|
"id": "porter-five-forces",
|
|
12689
|
+
"approach_ids": [
|
|
12690
|
+
"inspect"
|
|
12691
|
+
],
|
|
12605
12692
|
"name": "Porter Five Forces",
|
|
12606
12693
|
"version": "1.0.0",
|
|
12607
12694
|
"description": "Analyse industry competitiveness through five forces: rivalry, new entrants, substitutes, buyer power, and supplier power.",
|
|
@@ -12691,6 +12778,9 @@ var UPG_FRAMEWORKS = [
|
|
|
12691
12778
|
},
|
|
12692
12779
|
{
|
|
12693
12780
|
"id": "swot-analysis",
|
|
12781
|
+
"approach_ids": [
|
|
12782
|
+
"inspect"
|
|
12783
|
+
],
|
|
12694
12784
|
"name": "SWOT Analysis",
|
|
12695
12785
|
"version": "1.0.0",
|
|
12696
12786
|
"description": "Map Strengths, Weaknesses, Opportunities, and Threats in a 2x2 grid. Internal vs external, helpful vs harmful.",
|
|
@@ -13017,6 +13107,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13017
13107
|
"type": "assessment",
|
|
13018
13108
|
"scale_id": "reach_5",
|
|
13019
13109
|
"required": true,
|
|
13110
|
+
"scope": "framework",
|
|
13020
13111
|
"label": "Reach",
|
|
13021
13112
|
"description": "How many users will this impact per quarter?"
|
|
13022
13113
|
},
|
|
@@ -13025,6 +13116,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13025
13116
|
"type": "assessment",
|
|
13026
13117
|
"scale_id": "impact_5",
|
|
13027
13118
|
"required": true,
|
|
13119
|
+
"scope": "framework",
|
|
13028
13120
|
"label": "Impact",
|
|
13029
13121
|
"description": "How much will this impact each user, on the impact scale?"
|
|
13030
13122
|
},
|
|
@@ -13033,6 +13125,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13033
13125
|
"type": "assessment",
|
|
13034
13126
|
"scale_id": "confidence_5",
|
|
13035
13127
|
"required": true,
|
|
13128
|
+
"scope": "framework",
|
|
13036
13129
|
"label": "Confidence",
|
|
13037
13130
|
"description": "How confident are you in the reach, impact, and effort estimates?"
|
|
13038
13131
|
},
|
|
@@ -13041,6 +13134,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13041
13134
|
"type": "assessment",
|
|
13042
13135
|
"scale_id": "effort_5",
|
|
13043
13136
|
"required": true,
|
|
13137
|
+
"scope": "framework",
|
|
13044
13138
|
"label": "Effort",
|
|
13045
13139
|
"description": "How much work is required to build and ship this, on the effort scale?"
|
|
13046
13140
|
}
|
|
@@ -13127,6 +13221,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13127
13221
|
},
|
|
13128
13222
|
{
|
|
13129
13223
|
"id": "build-measure-learn",
|
|
13224
|
+
"approach_ids": [
|
|
13225
|
+
"reflect"
|
|
13226
|
+
],
|
|
13130
13227
|
"name": "Build-Measure-Learn",
|
|
13131
13228
|
"version": "1.0.0",
|
|
13132
13229
|
"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.",
|
|
@@ -13262,6 +13359,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13262
13359
|
"property": "functional_response",
|
|
13263
13360
|
"type": "enum",
|
|
13264
13361
|
"required": true,
|
|
13362
|
+
"scope": "framework",
|
|
13265
13363
|
"label": "Functional Response",
|
|
13266
13364
|
"description": "How users feel when the feature IS present",
|
|
13267
13365
|
"enum_values": [
|
|
@@ -13276,6 +13374,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13276
13374
|
"property": "dysfunctional_response",
|
|
13277
13375
|
"type": "enum",
|
|
13278
13376
|
"required": true,
|
|
13377
|
+
"scope": "framework",
|
|
13279
13378
|
"label": "Dysfunctional Response",
|
|
13280
13379
|
"description": "How users feel when the feature IS NOT present",
|
|
13281
13380
|
"enum_values": [
|
|
@@ -13290,6 +13389,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13290
13389
|
"property": "delighter_count",
|
|
13291
13390
|
"type": "number",
|
|
13292
13391
|
"required": false,
|
|
13392
|
+
"scope": "framework",
|
|
13293
13393
|
"label": "Delighter classifications",
|
|
13294
13394
|
"description": "Count of survey responses classifying this feature as a delighter (attractive)"
|
|
13295
13395
|
},
|
|
@@ -13297,6 +13397,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13297
13397
|
"property": "performance_count",
|
|
13298
13398
|
"type": "number",
|
|
13299
13399
|
"required": false,
|
|
13400
|
+
"scope": "framework",
|
|
13300
13401
|
"label": "Performance classifications",
|
|
13301
13402
|
"description": "Count of survey responses classifying this feature as performance (one-dimensional)"
|
|
13302
13403
|
},
|
|
@@ -13304,6 +13405,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13304
13405
|
"property": "must_be_count",
|
|
13305
13406
|
"type": "number",
|
|
13306
13407
|
"required": false,
|
|
13408
|
+
"scope": "framework",
|
|
13307
13409
|
"label": "Must-be classifications",
|
|
13308
13410
|
"description": "Count of survey responses classifying this feature as must-be (basic)"
|
|
13309
13411
|
},
|
|
@@ -13311,6 +13413,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13311
13413
|
"property": "indifferent_count",
|
|
13312
13414
|
"type": "number",
|
|
13313
13415
|
"required": false,
|
|
13416
|
+
"scope": "framework",
|
|
13314
13417
|
"label": "Indifferent classifications",
|
|
13315
13418
|
"description": "Count of survey responses classifying this feature as indifferent"
|
|
13316
13419
|
}
|
|
@@ -13503,6 +13606,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13503
13606
|
"property": "moscow",
|
|
13504
13607
|
"type": "enum",
|
|
13505
13608
|
"required": true,
|
|
13609
|
+
"scope": "framework",
|
|
13506
13610
|
"label": "MoSCoW priority",
|
|
13507
13611
|
"description": "Which scope bucket this requirement falls into for the current release",
|
|
13508
13612
|
"enum_values": [
|
|
@@ -13513,16 +13617,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13513
13617
|
]
|
|
13514
13618
|
}
|
|
13515
13619
|
]
|
|
13516
|
-
}
|
|
13517
|
-
"computed_properties": [
|
|
13518
|
-
{
|
|
13519
|
-
"property": "must_have_ratio",
|
|
13520
|
-
"expression": "must_count / total_count",
|
|
13521
|
-
"entity_type": "feature",
|
|
13522
|
-
"label": "Must-have Ratio",
|
|
13523
|
-
"format": "percentage"
|
|
13524
|
-
}
|
|
13525
|
-
]
|
|
13620
|
+
}
|
|
13526
13621
|
},
|
|
13527
13622
|
"structure": {
|
|
13528
13623
|
"pattern": "table"
|
|
@@ -13686,6 +13781,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13686
13781
|
},
|
|
13687
13782
|
{
|
|
13688
13783
|
"id": "c4-model",
|
|
13784
|
+
"approach_ids": [
|
|
13785
|
+
"trace"
|
|
13786
|
+
],
|
|
13689
13787
|
"name": "C4 Model",
|
|
13690
13788
|
"version": "1.0.0",
|
|
13691
13789
|
"description": "Visualise software architecture at four levels of abstraction: System Context, Container, Component, and Code. Each level zooms in to reveal more detail.",
|
|
@@ -13778,6 +13876,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13778
13876
|
},
|
|
13779
13877
|
{
|
|
13780
13878
|
"id": "adr-log",
|
|
13879
|
+
"approach_ids": [
|
|
13880
|
+
"inspect"
|
|
13881
|
+
],
|
|
13781
13882
|
"name": "ADR Log",
|
|
13782
13883
|
"version": "1.0.0",
|
|
13783
13884
|
"description": "Architecture Decision Records: log decisions with context, options, and rationale.",
|
|
@@ -13891,6 +13992,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13891
13992
|
},
|
|
13892
13993
|
{
|
|
13893
13994
|
"id": "atomic-design",
|
|
13995
|
+
"approach_ids": [
|
|
13996
|
+
"trace"
|
|
13997
|
+
],
|
|
13894
13998
|
"name": "Atomic Design",
|
|
13895
13999
|
"version": "1.0.0",
|
|
13896
14000
|
"description": "Atoms, Molecules, Organisms, Templates, Pages: a methodology for creating design systems from the smallest elements up.",
|
|
@@ -13988,6 +14092,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13988
14092
|
},
|
|
13989
14093
|
{
|
|
13990
14094
|
"id": "double-diamond",
|
|
14095
|
+
"approach_ids": [
|
|
14096
|
+
"plan"
|
|
14097
|
+
],
|
|
13991
14098
|
"name": "Double Diamond",
|
|
13992
14099
|
"version": "1.0.0",
|
|
13993
14100
|
"description": "Discover, Define, Develop, Deliver: a four-phase divergent/convergent design process.",
|
|
@@ -14078,6 +14185,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14078
14185
|
},
|
|
14079
14186
|
{
|
|
14080
14187
|
"id": "dora-metrics",
|
|
14188
|
+
"approach_ids": [
|
|
14189
|
+
"inspect"
|
|
14190
|
+
],
|
|
14081
14191
|
"name": "DORA Metrics",
|
|
14082
14192
|
"version": "1.0.0",
|
|
14083
14193
|
"description": "Four key metrics for software delivery performance: deployment frequency, lead time, change failure rate, and time to restore.",
|
|
@@ -14137,16 +14247,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14137
14247
|
]
|
|
14138
14248
|
}
|
|
14139
14249
|
]
|
|
14140
|
-
}
|
|
14141
|
-
"computed_properties": [
|
|
14142
|
-
{
|
|
14143
|
-
"property": "stability_index",
|
|
14144
|
-
"expression": "change_failure_rate * mean_time_to_recovery",
|
|
14145
|
-
"entity_type": "metric",
|
|
14146
|
-
"label": "Stability Index",
|
|
14147
|
-
"format": "number"
|
|
14148
|
-
}
|
|
14149
|
-
]
|
|
14250
|
+
}
|
|
14150
14251
|
},
|
|
14151
14252
|
"structure": {
|
|
14152
14253
|
"pattern": "collection"
|
|
@@ -14275,6 +14376,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14275
14376
|
},
|
|
14276
14377
|
{
|
|
14277
14378
|
"id": "pirate-metrics-aarrr",
|
|
14379
|
+
"approach_ids": [
|
|
14380
|
+
"trace"
|
|
14381
|
+
],
|
|
14278
14382
|
"name": "Pirate Metrics AARRR",
|
|
14279
14383
|
"version": "1.0.0",
|
|
14280
14384
|
"description": "Track user lifecycle across five stages: Acquisition, Activation, Retention, Revenue, and Referral.",
|
|
@@ -14308,7 +14412,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14308
14412
|
"required_properties": {
|
|
14309
14413
|
"metric": [
|
|
14310
14414
|
{
|
|
14311
|
-
"property": "
|
|
14415
|
+
"property": "metric_category",
|
|
14312
14416
|
"type": "enum",
|
|
14313
14417
|
"required": true,
|
|
14314
14418
|
"label": "Lifecycle stage",
|
|
@@ -14322,16 +14426,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14322
14426
|
]
|
|
14323
14427
|
}
|
|
14324
14428
|
]
|
|
14325
|
-
}
|
|
14326
|
-
"computed_properties": [
|
|
14327
|
-
{
|
|
14328
|
-
"property": "conversion_rate",
|
|
14329
|
-
"expression": "(stage_exits / stage_entries) * 100",
|
|
14330
|
-
"entity_type": "metric",
|
|
14331
|
-
"label": "Stage Conversion",
|
|
14332
|
-
"format": "percentage"
|
|
14333
|
-
}
|
|
14334
|
-
]
|
|
14429
|
+
}
|
|
14335
14430
|
},
|
|
14336
14431
|
"structure": {
|
|
14337
14432
|
"pattern": "funnel",
|
|
@@ -14395,6 +14490,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14395
14490
|
},
|
|
14396
14491
|
{
|
|
14397
14492
|
"id": "north-star-metric",
|
|
14493
|
+
"approach_ids": [
|
|
14494
|
+
"plan"
|
|
14495
|
+
],
|
|
14398
14496
|
"name": "North Star Metric",
|
|
14399
14497
|
"version": "1.0.0",
|
|
14400
14498
|
"description": "One metric that best captures the core value you deliver. Supported by 3-5 input metrics that drive it.",
|
|
@@ -14428,7 +14526,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14428
14526
|
"required_properties": {
|
|
14429
14527
|
"metric": [
|
|
14430
14528
|
{
|
|
14431
|
-
"property": "
|
|
14529
|
+
"property": "designation",
|
|
14432
14530
|
"type": "enum",
|
|
14433
14531
|
"required": true,
|
|
14434
14532
|
"label": "Metric role",
|
|
@@ -14446,16 +14544,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14446
14544
|
"description": "How strongly this input metric moves the North Star (input metrics only)"
|
|
14447
14545
|
}
|
|
14448
14546
|
]
|
|
14449
|
-
}
|
|
14450
|
-
"computed_properties": [
|
|
14451
|
-
{
|
|
14452
|
-
"property": "nsm_impact",
|
|
14453
|
-
"expression": "input_metric_value * leverage",
|
|
14454
|
-
"entity_type": "metric",
|
|
14455
|
-
"label": "NSM Impact",
|
|
14456
|
-
"format": "number"
|
|
14457
|
-
}
|
|
14458
|
-
]
|
|
14547
|
+
}
|
|
14459
14548
|
},
|
|
14460
14549
|
"structure": {
|
|
14461
14550
|
"pattern": "collection"
|
|
@@ -14491,6 +14580,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14491
14580
|
},
|
|
14492
14581
|
{
|
|
14493
14582
|
"id": "marketing-mix-4ps",
|
|
14583
|
+
"approach_ids": [
|
|
14584
|
+
"plan"
|
|
14585
|
+
],
|
|
14494
14586
|
"name": "Marketing Mix 4Ps",
|
|
14495
14587
|
"version": "1.0.0",
|
|
14496
14588
|
"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).",
|
|
@@ -14584,6 +14676,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14584
14676
|
},
|
|
14585
14677
|
{
|
|
14586
14678
|
"id": "bullseye-framework",
|
|
14679
|
+
"approach_ids": [
|
|
14680
|
+
"plan"
|
|
14681
|
+
],
|
|
14587
14682
|
"name": "Bullseye Framework",
|
|
14588
14683
|
"version": "1.0.0",
|
|
14589
14684
|
"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.",
|
|
@@ -14670,6 +14765,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14670
14765
|
},
|
|
14671
14766
|
{
|
|
14672
14767
|
"id": "product-led-growth-framework",
|
|
14768
|
+
"approach_ids": [
|
|
14769
|
+
"plan"
|
|
14770
|
+
],
|
|
14673
14771
|
"name": "PLG Framework",
|
|
14674
14772
|
"version": "1.0.0",
|
|
14675
14773
|
"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.",
|
|
@@ -14852,6 +14950,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14852
14950
|
},
|
|
14853
14951
|
{
|
|
14854
14952
|
"id": "raci-matrix",
|
|
14953
|
+
"approach_ids": [
|
|
14954
|
+
"inspect"
|
|
14955
|
+
],
|
|
14855
14956
|
"name": "RACI Matrix",
|
|
14856
14957
|
"version": "1.0.0",
|
|
14857
14958
|
"description": "Assign roles: Responsible, Accountable, Consulted, Informed for each activity.",
|
|
@@ -14903,16 +15004,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14903
15004
|
"role": "item"
|
|
14904
15005
|
}
|
|
14905
15006
|
],
|
|
14906
|
-
"required_properties": {}
|
|
14907
|
-
"computed_properties": [
|
|
14908
|
-
{
|
|
14909
|
-
"property": "coverage_score",
|
|
14910
|
-
"expression": "assigned_count / total_activities",
|
|
14911
|
-
"entity_type": "team",
|
|
14912
|
-
"label": "RACI Coverage",
|
|
14913
|
-
"format": "percentage"
|
|
14914
|
-
}
|
|
14915
|
-
]
|
|
15007
|
+
"required_properties": {}
|
|
14916
15008
|
},
|
|
14917
15009
|
"structure": {
|
|
14918
15010
|
"pattern": "matrix"
|
|
@@ -15136,6 +15228,9 @@ var UPG_FRAMEWORKS = [
|
|
|
15136
15228
|
},
|
|
15137
15229
|
{
|
|
15138
15230
|
"id": "team-health-check",
|
|
15231
|
+
"approach_ids": [
|
|
15232
|
+
"inspect"
|
|
15233
|
+
],
|
|
15139
15234
|
"name": "Team Health Check",
|
|
15140
15235
|
"version": "1.0.0",
|
|
15141
15236
|
"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.",
|
|
@@ -15193,16 +15288,7 @@ var UPG_FRAMEWORKS = [
|
|
|
15193
15288
|
"role": "item"
|
|
15194
15289
|
}
|
|
15195
15290
|
],
|
|
15196
|
-
"required_properties": {}
|
|
15197
|
-
"computed_properties": [
|
|
15198
|
-
{
|
|
15199
|
-
"property": "health_index",
|
|
15200
|
-
"expression": "(green_count - red_count) / total_indicators",
|
|
15201
|
-
"entity_type": "team",
|
|
15202
|
-
"label": "Health Index",
|
|
15203
|
-
"format": "number"
|
|
15204
|
-
}
|
|
15205
|
-
]
|
|
15291
|
+
"required_properties": {}
|
|
15206
15292
|
},
|
|
15207
15293
|
"structure": {
|
|
15208
15294
|
"pattern": "table"
|
|
@@ -15259,6 +15345,9 @@ var UPG_FRAMEWORKS = [
|
|
|
15259
15345
|
},
|
|
15260
15346
|
{
|
|
15261
15347
|
"id": "raid-log",
|
|
15348
|
+
"approach_ids": [
|
|
15349
|
+
"inspect"
|
|
15350
|
+
],
|
|
15262
15351
|
"name": "RAID Log",
|
|
15263
15352
|
"version": "1.0.0",
|
|
15264
15353
|
"description": "A project management register tracking Risks, Assumptions, Issues, and Dependencies, the four categories most likely to derail a project if left unmanaged.",
|
|
@@ -15278,6 +15367,11 @@ var UPG_FRAMEWORKS = [
|
|
|
15278
15367
|
"entityTypeId": "risk_register",
|
|
15279
15368
|
"description": "Risk or assumption logged with likelihood, impact, owner, and mitigation strategy"
|
|
15280
15369
|
},
|
|
15370
|
+
{
|
|
15371
|
+
"label": "Risk",
|
|
15372
|
+
"entityTypeId": "risk",
|
|
15373
|
+
"description": "Individual risk scored by probability and impact; severity = probability * impact"
|
|
15374
|
+
},
|
|
15281
15375
|
{
|
|
15282
15376
|
"label": "Dependency",
|
|
15283
15377
|
"entityTypeId": "dependency",
|
|
@@ -15300,6 +15394,10 @@ var UPG_FRAMEWORKS = [
|
|
|
15300
15394
|
"type": "risk_register",
|
|
15301
15395
|
"role": "item"
|
|
15302
15396
|
},
|
|
15397
|
+
{
|
|
15398
|
+
"type": "risk",
|
|
15399
|
+
"role": "scored_item"
|
|
15400
|
+
},
|
|
15303
15401
|
{
|
|
15304
15402
|
"type": "dependency",
|
|
15305
15403
|
"role": "item"
|
|
@@ -15313,7 +15411,24 @@ var UPG_FRAMEWORKS = [
|
|
|
15313
15411
|
"role": "item"
|
|
15314
15412
|
}
|
|
15315
15413
|
],
|
|
15316
|
-
"required_properties": {
|
|
15414
|
+
"required_properties": {
|
|
15415
|
+
"risk": [
|
|
15416
|
+
{
|
|
15417
|
+
"property": "probability",
|
|
15418
|
+
"type": "number",
|
|
15419
|
+
"required": true,
|
|
15420
|
+
"label": "Probability",
|
|
15421
|
+
"description": "Likelihood the risk materialises (risk.probability assessment)"
|
|
15422
|
+
},
|
|
15423
|
+
{
|
|
15424
|
+
"property": "impact",
|
|
15425
|
+
"type": "number",
|
|
15426
|
+
"required": true,
|
|
15427
|
+
"label": "Impact",
|
|
15428
|
+
"description": "Consequence severity if the risk materialises (risk.impact assessment)"
|
|
15429
|
+
}
|
|
15430
|
+
]
|
|
15431
|
+
},
|
|
15317
15432
|
"computed_properties": [
|
|
15318
15433
|
{
|
|
15319
15434
|
"property": "severity",
|
|
@@ -15374,126 +15489,1028 @@ var UPG_FRAMEWORKS = [
|
|
|
15374
15489
|
"Formal programme management would create overhead without value"
|
|
15375
15490
|
]
|
|
15376
15491
|
}
|
|
15377
|
-
}
|
|
15378
|
-
];
|
|
15379
|
-
var UPG_FRAMEWORKS_BY_ID = Object.fromEntries(
|
|
15380
|
-
UPG_FRAMEWORKS.map((fw) => [fw.id, fw])
|
|
15381
|
-
);
|
|
15382
|
-
var UPG_FRAMEWORKS_BY_CATEGORY = {};
|
|
15383
|
-
for (const fw of UPG_FRAMEWORKS) {
|
|
15384
|
-
if (!UPG_FRAMEWORKS_BY_CATEGORY[fw.category]) UPG_FRAMEWORKS_BY_CATEGORY[fw.category] = [];
|
|
15385
|
-
UPG_FRAMEWORKS_BY_CATEGORY[fw.category].push(fw);
|
|
15386
|
-
}
|
|
15387
|
-
|
|
15388
|
-
// src/presentation/labels.ts
|
|
15389
|
-
var PRIORITY_LABELS = [
|
|
15390
|
-
// ── need (CONSOLIDATED: replaces pain_point + user_need) ─────────────────────
|
|
15391
|
-
{
|
|
15392
|
-
id: "need",
|
|
15393
|
-
canonical_label: "Need",
|
|
15394
|
-
alt_labels: [
|
|
15395
|
-
"pain point",
|
|
15396
|
-
"pain",
|
|
15397
|
-
"user need",
|
|
15398
|
-
"customer need",
|
|
15399
|
-
"problem",
|
|
15400
|
-
"struggle",
|
|
15401
|
-
"customer pain",
|
|
15402
|
-
"frustration",
|
|
15403
|
-
"gap",
|
|
15404
|
-
"unmet need",
|
|
15405
|
-
"user problem"
|
|
15406
|
-
],
|
|
15407
|
-
framework_labels: {
|
|
15408
|
-
lean_canvas: "Problem",
|
|
15409
|
-
design_thinking: "Pain Point",
|
|
15410
|
-
ost: "Opportunity (need)",
|
|
15411
|
-
jtbd: "Struggle",
|
|
15412
|
-
vpc: "Customer Pain"
|
|
15413
|
-
},
|
|
15414
|
-
designations: {
|
|
15415
|
-
pain: "Pain Point",
|
|
15416
|
-
gap: "Need",
|
|
15417
|
-
desire: "Desire",
|
|
15418
|
-
constraint: "Constraint"
|
|
15419
|
-
}
|
|
15420
|
-
},
|
|
15421
|
-
// ── opportunity ──────────────────────────────────────────────────────────────
|
|
15422
|
-
{
|
|
15423
|
-
id: "opportunity",
|
|
15424
|
-
canonical_label: "Opportunity",
|
|
15425
|
-
alt_labels: ["product opportunity", "market opportunity", "user opportunity"],
|
|
15426
|
-
framework_labels: {
|
|
15427
|
-
ost: "Opportunity"
|
|
15428
|
-
}
|
|
15429
|
-
},
|
|
15430
|
-
// ── solution ─────────────────────────────────────────────────────────────────
|
|
15431
|
-
{
|
|
15432
|
-
id: "solution",
|
|
15433
|
-
canonical_label: "Solution",
|
|
15434
|
-
alt_labels: ["proposed solution", "solution idea", "concept", "approach"],
|
|
15435
|
-
framework_labels: {
|
|
15436
|
-
ost: "Solution",
|
|
15437
|
-
design_thinking: "Solution",
|
|
15438
|
-
lean_canvas: "Solution",
|
|
15439
|
-
rice: "Scored Solution"
|
|
15440
|
-
}
|
|
15441
15492
|
},
|
|
15442
|
-
// ── experiment (CONSOLIDATED: absorbs ab_test, growth_experiment, pricing_experiment) ──
|
|
15443
15493
|
{
|
|
15444
|
-
id: "
|
|
15445
|
-
|
|
15446
|
-
|
|
15447
|
-
"test",
|
|
15448
|
-
"validation",
|
|
15449
|
-
"ab test",
|
|
15450
|
-
"a/b test",
|
|
15451
|
-
"split test",
|
|
15452
|
-
"growth experiment",
|
|
15453
|
-
"pricing experiment",
|
|
15454
|
-
"usability test",
|
|
15455
|
-
"discovery experiment"
|
|
15494
|
+
"id": "ice-scoring",
|
|
15495
|
+
"approach_ids": [
|
|
15496
|
+
"prioritise"
|
|
15456
15497
|
],
|
|
15457
|
-
|
|
15458
|
-
|
|
15459
|
-
|
|
15460
|
-
|
|
15498
|
+
"name": "ICE Scoring",
|
|
15499
|
+
"version": "1.0.0",
|
|
15500
|
+
"description": "Rate ideas by Impact, Confidence, and Ease on a 1-10 scale. Multiply for a composite score. Fast and lightweight.",
|
|
15501
|
+
"category": "prioritization",
|
|
15502
|
+
"origin": {
|
|
15503
|
+
"type": "practitioner",
|
|
15504
|
+
"attribution": "Sean Ellis",
|
|
15505
|
+
"description": "Created by Sean Ellis as a lightweight growth experiment scoring method. Widely adopted in growth teams.",
|
|
15506
|
+
"year": 2010,
|
|
15507
|
+
"license": "open_attribution"
|
|
15461
15508
|
},
|
|
15462
|
-
|
|
15463
|
-
|
|
15464
|
-
|
|
15465
|
-
|
|
15466
|
-
|
|
15467
|
-
|
|
15468
|
-
|
|
15469
|
-
|
|
15470
|
-
|
|
15471
|
-
|
|
15472
|
-
|
|
15473
|
-
|
|
15474
|
-
|
|
15475
|
-
|
|
15476
|
-
|
|
15477
|
-
|
|
15478
|
-
|
|
15479
|
-
|
|
15480
|
-
|
|
15481
|
-
|
|
15482
|
-
|
|
15483
|
-
|
|
15484
|
-
|
|
15485
|
-
|
|
15486
|
-
|
|
15487
|
-
|
|
15488
|
-
|
|
15489
|
-
"
|
|
15490
|
-
|
|
15491
|
-
|
|
15492
|
-
|
|
15493
|
-
|
|
15494
|
-
|
|
15495
|
-
|
|
15496
|
-
|
|
15509
|
+
"tags": [
|
|
15510
|
+
"prioritization",
|
|
15511
|
+
"table"
|
|
15512
|
+
],
|
|
15513
|
+
"slots": [
|
|
15514
|
+
{
|
|
15515
|
+
"label": "Items to score",
|
|
15516
|
+
"entityTypeId": "feature",
|
|
15517
|
+
"description": "Features or experiments being evaluated"
|
|
15518
|
+
},
|
|
15519
|
+
{
|
|
15520
|
+
"label": "Impact",
|
|
15521
|
+
"entityTypeId": "outcome",
|
|
15522
|
+
"description": "How much will this move the needle?"
|
|
15523
|
+
},
|
|
15524
|
+
{
|
|
15525
|
+
"label": "Confidence",
|
|
15526
|
+
"entityTypeId": "assumption",
|
|
15527
|
+
"description": "How sure are we about the impact?"
|
|
15528
|
+
},
|
|
15529
|
+
{
|
|
15530
|
+
"label": "Ease",
|
|
15531
|
+
"entityTypeId": "feature",
|
|
15532
|
+
"description": "How easy is this to implement?"
|
|
15533
|
+
}
|
|
15534
|
+
],
|
|
15535
|
+
"data": {
|
|
15536
|
+
"entity_types": [
|
|
15537
|
+
{
|
|
15538
|
+
"type": "feature",
|
|
15539
|
+
"role": "scored_item"
|
|
15540
|
+
},
|
|
15541
|
+
{
|
|
15542
|
+
"type": "outcome",
|
|
15543
|
+
"role": "item"
|
|
15544
|
+
},
|
|
15545
|
+
{
|
|
15546
|
+
"type": "assumption",
|
|
15547
|
+
"role": "item"
|
|
15548
|
+
}
|
|
15549
|
+
],
|
|
15550
|
+
"required_properties": {
|
|
15551
|
+
"feature": [
|
|
15552
|
+
{
|
|
15553
|
+
"property": "impact",
|
|
15554
|
+
"type": "number",
|
|
15555
|
+
"required": true,
|
|
15556
|
+
"scope": "framework",
|
|
15557
|
+
"label": "Impact",
|
|
15558
|
+
"description": "Expected impact on the target metric (1-10)"
|
|
15559
|
+
},
|
|
15560
|
+
{
|
|
15561
|
+
"property": "confidence",
|
|
15562
|
+
"type": "number",
|
|
15563
|
+
"required": true,
|
|
15564
|
+
"scope": "framework",
|
|
15565
|
+
"label": "Confidence",
|
|
15566
|
+
"description": "Confidence in the impact estimate (1-10)"
|
|
15567
|
+
},
|
|
15568
|
+
{
|
|
15569
|
+
"property": "ease",
|
|
15570
|
+
"type": "number",
|
|
15571
|
+
"required": true,
|
|
15572
|
+
"scope": "framework",
|
|
15573
|
+
"label": "Ease",
|
|
15574
|
+
"description": "Ease of implementation (1-10)"
|
|
15575
|
+
}
|
|
15576
|
+
]
|
|
15577
|
+
},
|
|
15578
|
+
"computed_properties": [
|
|
15579
|
+
{
|
|
15580
|
+
"property": "ice_score",
|
|
15581
|
+
"expression": "impact * confidence * ease",
|
|
15582
|
+
"entity_type": "feature",
|
|
15583
|
+
"label": "ICE Score",
|
|
15584
|
+
"format": "number"
|
|
15585
|
+
}
|
|
15586
|
+
]
|
|
15587
|
+
},
|
|
15588
|
+
"structure": {
|
|
15589
|
+
"pattern": "table"
|
|
15590
|
+
},
|
|
15591
|
+
"presentation": {
|
|
15592
|
+
"layout": {
|
|
15593
|
+
"type": "table",
|
|
15594
|
+
"columns": [
|
|
15595
|
+
{
|
|
15596
|
+
"property": "title",
|
|
15597
|
+
"label": "Items to score",
|
|
15598
|
+
"sortable": true
|
|
15599
|
+
},
|
|
15600
|
+
{
|
|
15601
|
+
"property": "impact",
|
|
15602
|
+
"label": "Impact",
|
|
15603
|
+
"sortable": true
|
|
15604
|
+
},
|
|
15605
|
+
{
|
|
15606
|
+
"property": "confidence",
|
|
15607
|
+
"label": "Confidence",
|
|
15608
|
+
"sortable": true
|
|
15609
|
+
},
|
|
15610
|
+
{
|
|
15611
|
+
"property": "ease",
|
|
15612
|
+
"label": "Ease",
|
|
15613
|
+
"sortable": true
|
|
15614
|
+
}
|
|
15615
|
+
]
|
|
15616
|
+
},
|
|
15617
|
+
"sort_by": {
|
|
15618
|
+
"property": "title",
|
|
15619
|
+
"direction": "asc"
|
|
15620
|
+
},
|
|
15621
|
+
"colour_by": "type",
|
|
15622
|
+
"card_fields": [
|
|
15623
|
+
"title",
|
|
15624
|
+
"description",
|
|
15625
|
+
"status"
|
|
15626
|
+
]
|
|
15627
|
+
},
|
|
15628
|
+
"education": {
|
|
15629
|
+
"purpose": "Provide a lightweight scoring model for early-stage ideas when detailed effort estimates are unavailable. Faster than RICE and useful for brainstorm triage.",
|
|
15630
|
+
"core_question": "Which ideas should we investigate further based on their potential impact, confidence in our assumptions, and implementation ease?",
|
|
15631
|
+
"when_to_use": [
|
|
15632
|
+
"You have more ideas or features than capacity to build them",
|
|
15633
|
+
"Stakeholders disagree on what to build next",
|
|
15634
|
+
"You need a transparent, defensible prioritisation process"
|
|
15635
|
+
],
|
|
15636
|
+
"when_not_to_use": [
|
|
15637
|
+
"You have a single obvious next step with no contention",
|
|
15638
|
+
"The backlog is small enough to sequence intuitively"
|
|
15639
|
+
]
|
|
15640
|
+
}
|
|
15641
|
+
},
|
|
15642
|
+
{
|
|
15643
|
+
"id": "wsjf",
|
|
15644
|
+
"approach_ids": [
|
|
15645
|
+
"prioritise"
|
|
15646
|
+
],
|
|
15647
|
+
"name": "WSJF (Weighted Shortest Job First)",
|
|
15648
|
+
"version": "1.0.0",
|
|
15649
|
+
"description": "Prioritise work by dividing Cost of Delay (user value + time criticality + risk reduction) by job duration to maximise economic throughput.",
|
|
15650
|
+
"category": "planning",
|
|
15651
|
+
"origin": {
|
|
15652
|
+
"type": "practitioner",
|
|
15653
|
+
"attribution": "Reinertsen / SAFe",
|
|
15654
|
+
"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.",
|
|
15655
|
+
"url": "https://www.scaledagileframework.com/wsjf/",
|
|
15656
|
+
"year": 2011,
|
|
15657
|
+
"license": "open_attribution"
|
|
15658
|
+
},
|
|
15659
|
+
"tags": [
|
|
15660
|
+
"planning",
|
|
15661
|
+
"table"
|
|
15662
|
+
],
|
|
15663
|
+
"slots": [
|
|
15664
|
+
{
|
|
15665
|
+
"label": "Backlog Items",
|
|
15666
|
+
"entityTypeId": "feature",
|
|
15667
|
+
"description": "Backlog Items: feature entries to evaluate"
|
|
15668
|
+
},
|
|
15669
|
+
{
|
|
15670
|
+
"label": "User/Business Value",
|
|
15671
|
+
"entityTypeId": "metric",
|
|
15672
|
+
"description": "User/Business Value: metric entries to evaluate"
|
|
15673
|
+
},
|
|
15674
|
+
{
|
|
15675
|
+
"label": "Time Criticality",
|
|
15676
|
+
"entityTypeId": "metric",
|
|
15677
|
+
"description": "How much value decays if delivery is delayed (deadlines, competition, seasonal windows)"
|
|
15678
|
+
},
|
|
15679
|
+
{
|
|
15680
|
+
"label": "Risk Reduction / Opportunity Enablement",
|
|
15681
|
+
"entityTypeId": "metric",
|
|
15682
|
+
"description": "Risk Reduction / Opportunity Enablement: metric entries to evaluate"
|
|
15683
|
+
},
|
|
15684
|
+
{
|
|
15685
|
+
"label": "Job Size",
|
|
15686
|
+
"entityTypeId": "metric",
|
|
15687
|
+
"description": "Estimated effort (story points, t-shirt size, or person-weeks)"
|
|
15688
|
+
}
|
|
15689
|
+
],
|
|
15690
|
+
"data": {
|
|
15691
|
+
"entity_types": [
|
|
15692
|
+
{
|
|
15693
|
+
"type": "feature",
|
|
15694
|
+
"role": "scored_item"
|
|
15695
|
+
},
|
|
15696
|
+
{
|
|
15697
|
+
"type": "metric",
|
|
15698
|
+
"role": "item"
|
|
15699
|
+
}
|
|
15700
|
+
],
|
|
15701
|
+
"required_properties": {
|
|
15702
|
+
"feature": [
|
|
15703
|
+
{
|
|
15704
|
+
"property": "user_value",
|
|
15705
|
+
"type": "number",
|
|
15706
|
+
"required": true,
|
|
15707
|
+
"scope": "framework",
|
|
15708
|
+
"label": "User/Business Value",
|
|
15709
|
+
"description": "Relative value to users and the business if delivered"
|
|
15710
|
+
},
|
|
15711
|
+
{
|
|
15712
|
+
"property": "time_criticality",
|
|
15713
|
+
"type": "number",
|
|
15714
|
+
"required": true,
|
|
15715
|
+
"scope": "framework",
|
|
15716
|
+
"label": "Time Criticality",
|
|
15717
|
+
"description": "How much value decays if delivery is delayed (deadlines, competition, seasonal windows)"
|
|
15718
|
+
},
|
|
15719
|
+
{
|
|
15720
|
+
"property": "risk_reduction",
|
|
15721
|
+
"type": "number",
|
|
15722
|
+
"required": true,
|
|
15723
|
+
"scope": "framework",
|
|
15724
|
+
"label": "Risk Reduction / Opportunity Enablement",
|
|
15725
|
+
"description": "Value from reducing risk or enabling future opportunities"
|
|
15726
|
+
},
|
|
15727
|
+
{
|
|
15728
|
+
"property": "job_size",
|
|
15729
|
+
"type": "number",
|
|
15730
|
+
"required": true,
|
|
15731
|
+
"scope": "framework",
|
|
15732
|
+
"label": "Job Size",
|
|
15733
|
+
"description": "Estimated effort (story points, t-shirt size, or person-weeks)"
|
|
15734
|
+
}
|
|
15735
|
+
]
|
|
15736
|
+
},
|
|
15737
|
+
"computed_properties": [
|
|
15738
|
+
{
|
|
15739
|
+
"property": "wsjf_score",
|
|
15740
|
+
"expression": "(user_value + time_criticality + risk_reduction) / job_size",
|
|
15741
|
+
"entity_type": "feature",
|
|
15742
|
+
"label": "WSJF Score",
|
|
15743
|
+
"format": "number"
|
|
15744
|
+
}
|
|
15745
|
+
]
|
|
15746
|
+
},
|
|
15747
|
+
"structure": {
|
|
15748
|
+
"pattern": "table"
|
|
15749
|
+
},
|
|
15750
|
+
"presentation": {
|
|
15751
|
+
"layout": {
|
|
15752
|
+
"type": "table",
|
|
15753
|
+
"columns": [
|
|
15754
|
+
{
|
|
15755
|
+
"property": "title",
|
|
15756
|
+
"label": "Backlog Items",
|
|
15757
|
+
"sortable": true
|
|
15758
|
+
},
|
|
15759
|
+
{
|
|
15760
|
+
"property": "user_value",
|
|
15761
|
+
"label": "User/Business Value",
|
|
15762
|
+
"sortable": true
|
|
15763
|
+
},
|
|
15764
|
+
{
|
|
15765
|
+
"property": "time_criticality",
|
|
15766
|
+
"label": "Time Criticality",
|
|
15767
|
+
"sortable": true
|
|
15768
|
+
},
|
|
15769
|
+
{
|
|
15770
|
+
"property": "risk_reduction",
|
|
15771
|
+
"label": "Risk Reduction / Opportunity Enablement",
|
|
15772
|
+
"sortable": true
|
|
15773
|
+
},
|
|
15774
|
+
{
|
|
15775
|
+
"property": "job_size",
|
|
15776
|
+
"label": "Job Size",
|
|
15777
|
+
"sortable": true
|
|
15778
|
+
},
|
|
15779
|
+
{
|
|
15780
|
+
"property": "wsjf_score",
|
|
15781
|
+
"label": "WSJF Score",
|
|
15782
|
+
"sortable": true
|
|
15783
|
+
}
|
|
15784
|
+
]
|
|
15785
|
+
},
|
|
15786
|
+
"sort_by": {
|
|
15787
|
+
"property": "title",
|
|
15788
|
+
"direction": "asc"
|
|
15789
|
+
},
|
|
15790
|
+
"colour_by": "type",
|
|
15791
|
+
"card_fields": [
|
|
15792
|
+
"title",
|
|
15793
|
+
"description",
|
|
15794
|
+
"status"
|
|
15795
|
+
]
|
|
15796
|
+
},
|
|
15797
|
+
"education": {
|
|
15798
|
+
"purpose": "Prioritise work by dividing the Cost of Delay by job duration, ensuring the most time-sensitive, valuable items are done first.",
|
|
15799
|
+
"core_question": "Considering the cost of waiting, which items should we start now to maximise economic benefit?",
|
|
15800
|
+
"when_to_use": [
|
|
15801
|
+
"You need to coordinate work across multiple teams or time horizons",
|
|
15802
|
+
"Stakeholders need visibility into what is coming and when",
|
|
15803
|
+
"You want to balance commitments with flexibility"
|
|
15804
|
+
],
|
|
15805
|
+
"when_not_to_use": [
|
|
15806
|
+
"The team is small enough that informal coordination works",
|
|
15807
|
+
"Plans would create false precision about uncertain outcomes"
|
|
15808
|
+
]
|
|
15809
|
+
}
|
|
15810
|
+
},
|
|
15811
|
+
{
|
|
15812
|
+
"id": "cost-of-delay",
|
|
15813
|
+
"approach_ids": [
|
|
15814
|
+
"prioritise"
|
|
15815
|
+
],
|
|
15816
|
+
"name": "Cost of Delay",
|
|
15817
|
+
"version": "1.0.0",
|
|
15818
|
+
"description": "Quantify the economic cost of not shipping a feature to drive priority decisions. Combines urgency with value.",
|
|
15819
|
+
"category": "prioritization",
|
|
15820
|
+
"origin": {
|
|
15821
|
+
"type": "practitioner",
|
|
15822
|
+
"attribution": "Don Reinertsen",
|
|
15823
|
+
"description": "Formalised in The Principles of Product Development Flow (Celeritas Publishing). Foundational to lean product economics.",
|
|
15824
|
+
"year": 2009,
|
|
15825
|
+
"license": "public_domain"
|
|
15826
|
+
},
|
|
15827
|
+
"tags": [
|
|
15828
|
+
"prioritization",
|
|
15829
|
+
"table"
|
|
15830
|
+
],
|
|
15831
|
+
"slots": [
|
|
15832
|
+
{
|
|
15833
|
+
"label": "Items to evaluate",
|
|
15834
|
+
"entityTypeId": "feature",
|
|
15835
|
+
"description": "Features or initiatives being assessed"
|
|
15836
|
+
},
|
|
15837
|
+
{
|
|
15838
|
+
"label": "User-Business Value",
|
|
15839
|
+
"entityTypeId": "outcome",
|
|
15840
|
+
"description": "Revenue, retention, or strategic value"
|
|
15841
|
+
},
|
|
15842
|
+
{
|
|
15843
|
+
"label": "Time Criticality",
|
|
15844
|
+
"entityTypeId": "metric",
|
|
15845
|
+
"description": "How much value decays with delay"
|
|
15846
|
+
},
|
|
15847
|
+
{
|
|
15848
|
+
"label": "Risk Reduction",
|
|
15849
|
+
"entityTypeId": "risk",
|
|
15850
|
+
"description": "What risk does this mitigate?"
|
|
15851
|
+
}
|
|
15852
|
+
],
|
|
15853
|
+
"data": {
|
|
15854
|
+
"entity_types": [
|
|
15855
|
+
{
|
|
15856
|
+
"type": "feature",
|
|
15857
|
+
"role": "scored_item"
|
|
15858
|
+
},
|
|
15859
|
+
{
|
|
15860
|
+
"type": "metric",
|
|
15861
|
+
"role": "item"
|
|
15862
|
+
},
|
|
15863
|
+
{
|
|
15864
|
+
"type": "outcome",
|
|
15865
|
+
"role": "item"
|
|
15866
|
+
},
|
|
15867
|
+
{
|
|
15868
|
+
"type": "risk",
|
|
15869
|
+
"role": "item"
|
|
15870
|
+
}
|
|
15871
|
+
],
|
|
15872
|
+
"required_properties": {
|
|
15873
|
+
"feature": [
|
|
15874
|
+
{
|
|
15875
|
+
"property": "cost_of_delay",
|
|
15876
|
+
"type": "number",
|
|
15877
|
+
"required": true,
|
|
15878
|
+
"scope": "framework",
|
|
15879
|
+
"label": "Cost of Delay",
|
|
15880
|
+
"description": "Weekly revenue impact of not shipping"
|
|
15881
|
+
},
|
|
15882
|
+
{
|
|
15883
|
+
"property": "job_size",
|
|
15884
|
+
"type": "number",
|
|
15885
|
+
"required": true,
|
|
15886
|
+
"scope": "framework",
|
|
15887
|
+
"label": "Job Size",
|
|
15888
|
+
"description": "Weeks of development effort"
|
|
15889
|
+
}
|
|
15890
|
+
]
|
|
15891
|
+
},
|
|
15892
|
+
"computed_properties": [
|
|
15893
|
+
{
|
|
15894
|
+
"property": "wsjf_score",
|
|
15895
|
+
"expression": "cost_of_delay / job_size",
|
|
15896
|
+
"entity_type": "feature",
|
|
15897
|
+
"label": "WSJF Score",
|
|
15898
|
+
"format": "number"
|
|
15899
|
+
}
|
|
15900
|
+
]
|
|
15901
|
+
},
|
|
15902
|
+
"structure": {
|
|
15903
|
+
"pattern": "table"
|
|
15904
|
+
},
|
|
15905
|
+
"presentation": {
|
|
15906
|
+
"layout": {
|
|
15907
|
+
"type": "table",
|
|
15908
|
+
"columns": [
|
|
15909
|
+
{
|
|
15910
|
+
"property": "title",
|
|
15911
|
+
"label": "Items to evaluate",
|
|
15912
|
+
"sortable": true
|
|
15913
|
+
},
|
|
15914
|
+
{
|
|
15915
|
+
"property": "cost_of_delay",
|
|
15916
|
+
"label": "User-Business Value",
|
|
15917
|
+
"sortable": true
|
|
15918
|
+
},
|
|
15919
|
+
{
|
|
15920
|
+
"property": "job_size",
|
|
15921
|
+
"label": "Job Size",
|
|
15922
|
+
"sortable": true
|
|
15923
|
+
},
|
|
15924
|
+
{
|
|
15925
|
+
"property": "wsjf_score",
|
|
15926
|
+
"label": "CoD Score",
|
|
15927
|
+
"sortable": true
|
|
15928
|
+
}
|
|
15929
|
+
]
|
|
15930
|
+
},
|
|
15931
|
+
"sort_by": {
|
|
15932
|
+
"property": "title",
|
|
15933
|
+
"direction": "asc"
|
|
15934
|
+
},
|
|
15935
|
+
"colour_by": "type",
|
|
15936
|
+
"card_fields": [
|
|
15937
|
+
"title",
|
|
15938
|
+
"description",
|
|
15939
|
+
"status"
|
|
15940
|
+
]
|
|
15941
|
+
},
|
|
15942
|
+
"education": {
|
|
15943
|
+
"purpose": "Quantify the economic impact of not delivering a feature by a given date, making urgency visible and enabling time-sensitive prioritisation.",
|
|
15944
|
+
"core_question": "How much value are we losing every week this feature is not in production, and does that urgency justify fast-tracking it?",
|
|
15945
|
+
"when_to_use": [
|
|
15946
|
+
"You have more ideas or features than capacity to build them",
|
|
15947
|
+
"Stakeholders disagree on what to build next",
|
|
15948
|
+
"You need a transparent, defensible prioritisation process"
|
|
15949
|
+
],
|
|
15950
|
+
"when_not_to_use": [
|
|
15951
|
+
"You have a single obvious next step with no contention",
|
|
15952
|
+
"The backlog is small enough to sequence intuitively"
|
|
15953
|
+
]
|
|
15954
|
+
}
|
|
15955
|
+
},
|
|
15956
|
+
{
|
|
15957
|
+
"id": "five-whys",
|
|
15958
|
+
"approach_ids": [
|
|
15959
|
+
"reflect",
|
|
15960
|
+
"inspect"
|
|
15961
|
+
],
|
|
15962
|
+
"name": "Five Whys",
|
|
15963
|
+
"version": "1.0.0",
|
|
15964
|
+
"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.',
|
|
15965
|
+
"category": "team_process",
|
|
15966
|
+
"origin": {
|
|
15967
|
+
"type": "practitioner",
|
|
15968
|
+
"attribution": "Sakichi Toyoda / Toyota Production System",
|
|
15969
|
+
"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.",
|
|
15970
|
+
"year": 1930,
|
|
15971
|
+
"license": "public_domain"
|
|
15972
|
+
},
|
|
15973
|
+
"tags": [
|
|
15974
|
+
"team_process",
|
|
15975
|
+
"reflection",
|
|
15976
|
+
"root_cause",
|
|
15977
|
+
"tree"
|
|
15978
|
+
],
|
|
15979
|
+
"slots": [
|
|
15980
|
+
{
|
|
15981
|
+
"label": "Symptom",
|
|
15982
|
+
"entityTypeId": "need",
|
|
15983
|
+
"description": "The observed problem the analysis starts from."
|
|
15984
|
+
},
|
|
15985
|
+
{
|
|
15986
|
+
"label": "Why chain",
|
|
15987
|
+
"entityTypeId": "insight",
|
|
15988
|
+
"description": 'Each "why?" answer along the chain, typically five iterations deep.'
|
|
15989
|
+
},
|
|
15990
|
+
{
|
|
15991
|
+
"label": "Root cause",
|
|
15992
|
+
"entityTypeId": "insight",
|
|
15993
|
+
"description": "The terminal answer at the bottom of the chain: the underlying cause to address."
|
|
15994
|
+
}
|
|
15995
|
+
],
|
|
15996
|
+
"data": {
|
|
15997
|
+
"entity_types": [
|
|
15998
|
+
{
|
|
15999
|
+
"type": "need",
|
|
16000
|
+
"role": "root"
|
|
16001
|
+
},
|
|
16002
|
+
{
|
|
16003
|
+
"type": "insight",
|
|
16004
|
+
"role": "branch"
|
|
16005
|
+
}
|
|
16006
|
+
],
|
|
16007
|
+
"required_properties": {}
|
|
16008
|
+
},
|
|
16009
|
+
"structure": {
|
|
16010
|
+
"pattern": "tree"
|
|
16011
|
+
},
|
|
16012
|
+
"presentation": {
|
|
16013
|
+
"layout": {
|
|
16014
|
+
"type": "tree",
|
|
16015
|
+
"direction": "TB"
|
|
16016
|
+
},
|
|
16017
|
+
"sort_by": {
|
|
16018
|
+
"property": "title",
|
|
16019
|
+
"direction": "asc"
|
|
16020
|
+
},
|
|
16021
|
+
"card_fields": [
|
|
16022
|
+
"title",
|
|
16023
|
+
"description"
|
|
16024
|
+
]
|
|
16025
|
+
},
|
|
16026
|
+
"education": {
|
|
16027
|
+
"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.',
|
|
16028
|
+
"core_question": "Why is this happening, and why is THAT happening, until we reach a cause we can act on?",
|
|
16029
|
+
"when_to_use": [
|
|
16030
|
+
"A problem keeps recurring after surface fixes",
|
|
16031
|
+
"Post-incident review where the obvious cause feels too obvious",
|
|
16032
|
+
"Designing a fix and you want to confirm you understand the actual driver"
|
|
16033
|
+
],
|
|
16034
|
+
"when_not_to_use": [
|
|
16035
|
+
"The problem has multiple independent root causes (use a fishbone or richer RCA tool)",
|
|
16036
|
+
"You need quantitative attribution rather than a single-thread narrative",
|
|
16037
|
+
'Five linear "whys" oversimplify a systems problem with feedback loops'
|
|
16038
|
+
]
|
|
16039
|
+
}
|
|
16040
|
+
},
|
|
16041
|
+
{
|
|
16042
|
+
"id": "pre-mortem",
|
|
16043
|
+
"approach_ids": [
|
|
16044
|
+
"reflect"
|
|
16045
|
+
],
|
|
16046
|
+
"name": "Pre-mortem",
|
|
16047
|
+
"version": "1.0.0",
|
|
16048
|
+
"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.",
|
|
16049
|
+
"category": "team_process",
|
|
16050
|
+
"origin": {
|
|
16051
|
+
"type": "practitioner",
|
|
16052
|
+
"attribution": "Gary Klein",
|
|
16053
|
+
"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.",
|
|
16054
|
+
"url": "https://hbr.org/2007/09/performing-a-project-premortem",
|
|
16055
|
+
"year": 2007,
|
|
16056
|
+
"license": "published_methodology"
|
|
16057
|
+
},
|
|
16058
|
+
"tags": [
|
|
16059
|
+
"team_process",
|
|
16060
|
+
"reflection",
|
|
16061
|
+
"risk",
|
|
16062
|
+
"collection"
|
|
16063
|
+
],
|
|
16064
|
+
"slots": [
|
|
16065
|
+
{
|
|
16066
|
+
"label": "Imagined failures",
|
|
16067
|
+
"entityTypeId": "risk",
|
|
16068
|
+
"description": "Plausible failure modes named as if they had already occurred."
|
|
16069
|
+
},
|
|
16070
|
+
{
|
|
16071
|
+
"label": "Causes",
|
|
16072
|
+
"entityTypeId": "insight",
|
|
16073
|
+
"description": "For each imagined failure, the contributing causes the team can foresee."
|
|
16074
|
+
},
|
|
16075
|
+
{
|
|
16076
|
+
"label": "Mitigations",
|
|
16077
|
+
"entityTypeId": "initiative",
|
|
16078
|
+
"description": "Mitigation actions the team will take before failure can occur."
|
|
16079
|
+
}
|
|
16080
|
+
],
|
|
16081
|
+
"data": {
|
|
16082
|
+
"entity_types": [
|
|
16083
|
+
{
|
|
16084
|
+
"type": "risk",
|
|
16085
|
+
"role": "bucket"
|
|
16086
|
+
},
|
|
16087
|
+
{
|
|
16088
|
+
"type": "insight",
|
|
16089
|
+
"role": "bucket"
|
|
16090
|
+
},
|
|
16091
|
+
{
|
|
16092
|
+
"type": "initiative",
|
|
16093
|
+
"role": "bucket"
|
|
16094
|
+
}
|
|
16095
|
+
],
|
|
16096
|
+
"required_properties": {}
|
|
16097
|
+
},
|
|
16098
|
+
"structure": {
|
|
16099
|
+
"pattern": "collection"
|
|
16100
|
+
},
|
|
16101
|
+
"presentation": {
|
|
16102
|
+
"layout": {
|
|
16103
|
+
"type": "grid",
|
|
16104
|
+
"groupBy": "type"
|
|
16105
|
+
},
|
|
16106
|
+
"sort_by": {
|
|
16107
|
+
"property": "title",
|
|
16108
|
+
"direction": "asc"
|
|
16109
|
+
},
|
|
16110
|
+
"colour_by": "group",
|
|
16111
|
+
"card_fields": [
|
|
16112
|
+
"title",
|
|
16113
|
+
"description"
|
|
16114
|
+
]
|
|
16115
|
+
},
|
|
16116
|
+
"education": {
|
|
16117
|
+
"purpose": "Surface project risks early by inverting hindsight: imagine the project has already failed and ask why, while there is still time to mitigate.",
|
|
16118
|
+
"core_question": "It is six months from now and the project has failed catastrophically. What happened, and why?",
|
|
16119
|
+
"when_to_use": [
|
|
16120
|
+
"Kicking off a project with significant downside or irreversible commitment",
|
|
16121
|
+
"A plan looks too clean and the team senses unspoken concerns",
|
|
16122
|
+
"Stakeholders disagree on risk; the exercise externalises and ranks them"
|
|
16123
|
+
],
|
|
16124
|
+
"when_not_to_use": [
|
|
16125
|
+
"The work is small, reversible, and cheap to course-correct",
|
|
16126
|
+
"The team is in execution mode and reflective ceremonies will derail momentum",
|
|
16127
|
+
"Risk surfacing has become performative: the team names risks but never mitigates them"
|
|
16128
|
+
]
|
|
16129
|
+
}
|
|
16130
|
+
},
|
|
16131
|
+
{
|
|
16132
|
+
"id": "red-team",
|
|
16133
|
+
"approach_ids": [
|
|
16134
|
+
"reflect",
|
|
16135
|
+
"inspect"
|
|
16136
|
+
],
|
|
16137
|
+
"name": "Red Team",
|
|
16138
|
+
"version": "1.0.0",
|
|
16139
|
+
"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.",
|
|
16140
|
+
"category": "team_process",
|
|
16141
|
+
"origin": {
|
|
16142
|
+
"type": "practitioner",
|
|
16143
|
+
"attribution": "US Department of Defense (Cold War era); broadened by security and intelligence practice",
|
|
16144
|
+
"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.`,
|
|
16145
|
+
"year": 1960,
|
|
16146
|
+
"license": "public_domain"
|
|
16147
|
+
},
|
|
16148
|
+
"tags": [
|
|
16149
|
+
"team_process",
|
|
16150
|
+
"reflection",
|
|
16151
|
+
"adversarial",
|
|
16152
|
+
"collection"
|
|
16153
|
+
],
|
|
16154
|
+
"slots": [
|
|
16155
|
+
{
|
|
16156
|
+
"label": "Target",
|
|
16157
|
+
"entityTypeId": "initiative",
|
|
16158
|
+
"description": "The plan, design, or proposal under adversarial review."
|
|
16159
|
+
},
|
|
16160
|
+
{
|
|
16161
|
+
"label": "Attack vectors",
|
|
16162
|
+
"entityTypeId": "risk",
|
|
16163
|
+
"description": "The angles the red team uses to probe weaknesses."
|
|
16164
|
+
},
|
|
16165
|
+
{
|
|
16166
|
+
"label": "Findings",
|
|
16167
|
+
"entityTypeId": "insight",
|
|
16168
|
+
"description": "Weaknesses, blind spots, or unstated assumptions surfaced by the review."
|
|
16169
|
+
}
|
|
16170
|
+
],
|
|
16171
|
+
"data": {
|
|
16172
|
+
"entity_types": [
|
|
16173
|
+
{
|
|
16174
|
+
"type": "initiative",
|
|
16175
|
+
"role": "root"
|
|
16176
|
+
},
|
|
16177
|
+
{
|
|
16178
|
+
"type": "risk",
|
|
16179
|
+
"role": "bucket"
|
|
16180
|
+
},
|
|
16181
|
+
{
|
|
16182
|
+
"type": "insight",
|
|
16183
|
+
"role": "bucket"
|
|
16184
|
+
}
|
|
16185
|
+
],
|
|
16186
|
+
"required_properties": {}
|
|
16187
|
+
},
|
|
16188
|
+
"structure": {
|
|
16189
|
+
"pattern": "collection"
|
|
16190
|
+
},
|
|
16191
|
+
"presentation": {
|
|
16192
|
+
"layout": {
|
|
16193
|
+
"type": "grid",
|
|
16194
|
+
"groupBy": "type"
|
|
16195
|
+
},
|
|
16196
|
+
"sort_by": {
|
|
16197
|
+
"property": "title",
|
|
16198
|
+
"direction": "asc"
|
|
16199
|
+
},
|
|
16200
|
+
"colour_by": "group",
|
|
16201
|
+
"card_fields": [
|
|
16202
|
+
"title",
|
|
16203
|
+
"description"
|
|
16204
|
+
]
|
|
16205
|
+
},
|
|
16206
|
+
"education": {
|
|
16207
|
+
"purpose": "Stress-test a plan against an explicit adversary by assigning reviewers to attack rather than agree, so weaknesses surface before reality finds them.",
|
|
16208
|
+
"core_question": "If a competent adversary wanted this to fail, where would they push first, and would we hold?",
|
|
16209
|
+
"when_to_use": [
|
|
16210
|
+
"A high-stakes decision, launch, or security posture needs hardening",
|
|
16211
|
+
"Inside-out thinking is dominant and dissent has gone quiet",
|
|
16212
|
+
"Risk register is suspiciously short for the size of the bet"
|
|
16213
|
+
],
|
|
16214
|
+
"when_not_to_use": [
|
|
16215
|
+
"Early-stage exploration where adversarial framing would crush a fragile idea prematurely",
|
|
16216
|
+
"Team trust is too low: red-teaming will read as personal attack rather than role-play",
|
|
16217
|
+
"The work is small enough that a lightweight devil's-advocate pass is sufficient"
|
|
16218
|
+
]
|
|
16219
|
+
}
|
|
16220
|
+
},
|
|
16221
|
+
{
|
|
16222
|
+
"id": "devils-advocate",
|
|
16223
|
+
"approach_ids": [
|
|
16224
|
+
"reflect"
|
|
16225
|
+
],
|
|
16226
|
+
"name": "Devil's Advocate",
|
|
16227
|
+
"version": "1.0.0",
|
|
16228
|
+
"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.",
|
|
16229
|
+
"category": "team_process",
|
|
16230
|
+
"origin": {
|
|
16231
|
+
"type": "practitioner",
|
|
16232
|
+
"attribution": "Roman Catholic Church (advocatus diaboli); broadened by decision-quality practice",
|
|
16233
|
+
"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.",
|
|
16234
|
+
"year": 1587,
|
|
16235
|
+
"license": "public_domain"
|
|
16236
|
+
},
|
|
16237
|
+
"tags": [
|
|
16238
|
+
"team_process",
|
|
16239
|
+
"reflection",
|
|
16240
|
+
"decision_quality",
|
|
16241
|
+
"collection"
|
|
16242
|
+
],
|
|
16243
|
+
"slots": [
|
|
16244
|
+
{
|
|
16245
|
+
"label": "Proposal",
|
|
16246
|
+
"entityTypeId": "initiative",
|
|
16247
|
+
"description": "The plan or recommendation under consideration."
|
|
16248
|
+
},
|
|
16249
|
+
{
|
|
16250
|
+
"label": "Opposing arguments",
|
|
16251
|
+
"entityTypeId": "insight",
|
|
16252
|
+
"description": "The case against the proposal, voiced by the assigned contrarian regardless of personal view."
|
|
16253
|
+
},
|
|
16254
|
+
{
|
|
16255
|
+
"label": "Counter-evidence",
|
|
16256
|
+
"entityTypeId": "evidence",
|
|
16257
|
+
"description": "Data points the contrarian raises that the proposal does not yet account for."
|
|
16258
|
+
}
|
|
16259
|
+
],
|
|
16260
|
+
"data": {
|
|
16261
|
+
"entity_types": [
|
|
16262
|
+
{
|
|
16263
|
+
"type": "initiative",
|
|
16264
|
+
"role": "root"
|
|
16265
|
+
},
|
|
16266
|
+
{
|
|
16267
|
+
"type": "insight",
|
|
16268
|
+
"role": "bucket"
|
|
16269
|
+
},
|
|
16270
|
+
{
|
|
16271
|
+
"type": "evidence",
|
|
16272
|
+
"role": "bucket"
|
|
16273
|
+
}
|
|
16274
|
+
],
|
|
16275
|
+
"required_properties": {}
|
|
16276
|
+
},
|
|
16277
|
+
"structure": {
|
|
16278
|
+
"pattern": "collection"
|
|
16279
|
+
},
|
|
16280
|
+
"presentation": {
|
|
16281
|
+
"layout": {
|
|
16282
|
+
"type": "grid",
|
|
16283
|
+
"groupBy": "type"
|
|
16284
|
+
},
|
|
16285
|
+
"sort_by": {
|
|
16286
|
+
"property": "title",
|
|
16287
|
+
"direction": "asc"
|
|
16288
|
+
},
|
|
16289
|
+
"colour_by": "group",
|
|
16290
|
+
"card_fields": [
|
|
16291
|
+
"title",
|
|
16292
|
+
"description"
|
|
16293
|
+
]
|
|
16294
|
+
},
|
|
16295
|
+
"education": {
|
|
16296
|
+
"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.",
|
|
16297
|
+
"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?",
|
|
16298
|
+
"when_to_use": [
|
|
16299
|
+
"A decision is heading toward consensus and you suspect groupthink",
|
|
16300
|
+
"Stakes are high and the team has not heard a serious counter-argument",
|
|
16301
|
+
"Cultural norms make raw dissent costly; assigning the role lowers the social cost"
|
|
16302
|
+
],
|
|
16303
|
+
"when_not_to_use": [
|
|
16304
|
+
"Genuine disagreement already exists in the room (let it surface; do not theatricalise it)",
|
|
16305
|
+
"The decision is small enough that the ceremony costs more than the insight returned",
|
|
16306
|
+
"The assigned contrarian will be punished socially for the role; set the norms first or skip"
|
|
16307
|
+
]
|
|
16308
|
+
}
|
|
16309
|
+
},
|
|
16310
|
+
{
|
|
16311
|
+
"id": "second-order-thinking",
|
|
16312
|
+
"approach_ids": [
|
|
16313
|
+
"reflect"
|
|
16314
|
+
],
|
|
16315
|
+
"name": "Second-order Thinking",
|
|
16316
|
+
"version": "1.0.0",
|
|
16317
|
+
"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.',
|
|
16318
|
+
"category": "team_process",
|
|
16319
|
+
"origin": {
|
|
16320
|
+
"type": "practitioner",
|
|
16321
|
+
"attribution": "Howard Marks / Charlie Munger",
|
|
16322
|
+
"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.`,
|
|
16323
|
+
"url": "https://www.oaktreecapital.com/insights/memo/dare-to-be-great-ii",
|
|
16324
|
+
"year": 2011,
|
|
16325
|
+
"license": "published_methodology"
|
|
16326
|
+
},
|
|
16327
|
+
"tags": [
|
|
16328
|
+
"team_process",
|
|
16329
|
+
"reflection",
|
|
16330
|
+
"consequences",
|
|
16331
|
+
"tree"
|
|
16332
|
+
],
|
|
16333
|
+
"slots": [
|
|
16334
|
+
{
|
|
16335
|
+
"label": "First-order move",
|
|
16336
|
+
"entityTypeId": "decision",
|
|
16337
|
+
"description": "The decision or move under consideration."
|
|
16338
|
+
},
|
|
16339
|
+
{
|
|
16340
|
+
"label": "Second-order consequences",
|
|
16341
|
+
"entityTypeId": "insight",
|
|
16342
|
+
"description": "Downstream effects that follow from the first-order move."
|
|
16343
|
+
},
|
|
16344
|
+
{
|
|
16345
|
+
"label": "Higher-order consequences",
|
|
16346
|
+
"entityTypeId": "insight",
|
|
16347
|
+
"description": "Third-, fourth-, fifth-order ripples: second-order consequences of the second-order consequences."
|
|
16348
|
+
}
|
|
16349
|
+
],
|
|
16350
|
+
"data": {
|
|
16351
|
+
"entity_types": [
|
|
16352
|
+
{
|
|
16353
|
+
"type": "decision",
|
|
16354
|
+
"role": "root"
|
|
16355
|
+
},
|
|
16356
|
+
{
|
|
16357
|
+
"type": "insight",
|
|
16358
|
+
"role": "branch"
|
|
16359
|
+
}
|
|
16360
|
+
],
|
|
16361
|
+
"required_properties": {}
|
|
16362
|
+
},
|
|
16363
|
+
"structure": {
|
|
16364
|
+
"pattern": "tree"
|
|
16365
|
+
},
|
|
16366
|
+
"presentation": {
|
|
16367
|
+
"layout": {
|
|
16368
|
+
"type": "tree",
|
|
16369
|
+
"direction": "TB"
|
|
16370
|
+
},
|
|
16371
|
+
"sort_by": {
|
|
16372
|
+
"property": "title",
|
|
16373
|
+
"direction": "asc"
|
|
16374
|
+
},
|
|
16375
|
+
"card_fields": [
|
|
16376
|
+
"title",
|
|
16377
|
+
"description"
|
|
16378
|
+
]
|
|
16379
|
+
},
|
|
16380
|
+
"education": {
|
|
16381
|
+
"purpose": 'Resist first-order reasoning by chaining "and then what?" until non-obvious downstream consequences come into view.',
|
|
16382
|
+
"core_question": "If we make this move and it works, what does the world look like next, and is that the world we want?",
|
|
16383
|
+
"when_to_use": [
|
|
16384
|
+
"A decision has feedback loops, market reactions, or behavioural ripples",
|
|
16385
|
+
"The first-order case is compelling, which is exactly when downstream effects bite",
|
|
16386
|
+
"Considering an irreversible or large-scale commitment"
|
|
16387
|
+
],
|
|
16388
|
+
"when_not_to_use": [
|
|
16389
|
+
"Routine, reversible, low-blast-radius decisions where deliberation costs more than mistakes",
|
|
16390
|
+
"Higher-order branches diverge into pure speculation with no anchor in evidence",
|
|
16391
|
+
"Time pressure makes a deeper trace expensive and the first-order call is good enough"
|
|
16392
|
+
]
|
|
16393
|
+
}
|
|
16394
|
+
}
|
|
16395
|
+
];
|
|
16396
|
+
var UPG_FRAMEWORKS_BY_ID = Object.fromEntries(
|
|
16397
|
+
UPG_FRAMEWORKS.map((fw) => [fw.id, fw])
|
|
16398
|
+
);
|
|
16399
|
+
var UPG_FRAMEWORKS_BY_CATEGORY = {};
|
|
16400
|
+
for (const fw of UPG_FRAMEWORKS) {
|
|
16401
|
+
if (!UPG_FRAMEWORKS_BY_CATEGORY[fw.category]) UPG_FRAMEWORKS_BY_CATEGORY[fw.category] = [];
|
|
16402
|
+
UPG_FRAMEWORKS_BY_CATEGORY[fw.category].push(fw);
|
|
16403
|
+
}
|
|
16404
|
+
|
|
16405
|
+
// src/presentation/labels.ts
|
|
16406
|
+
var PRIORITY_LABELS = [
|
|
16407
|
+
// ── need (CONSOLIDATED: replaces pain_point + user_need) ─────────────────────
|
|
16408
|
+
{
|
|
16409
|
+
id: "need",
|
|
16410
|
+
canonical_label: "Need",
|
|
16411
|
+
alt_labels: [
|
|
16412
|
+
"pain point",
|
|
16413
|
+
"pain",
|
|
16414
|
+
"user need",
|
|
16415
|
+
"customer need",
|
|
16416
|
+
"problem",
|
|
16417
|
+
"struggle",
|
|
16418
|
+
"customer pain",
|
|
16419
|
+
"frustration",
|
|
16420
|
+
"gap",
|
|
16421
|
+
"unmet need",
|
|
16422
|
+
"user problem"
|
|
16423
|
+
],
|
|
16424
|
+
framework_labels: {
|
|
16425
|
+
lean_canvas: "Problem",
|
|
16426
|
+
design_thinking: "Pain Point",
|
|
16427
|
+
ost: "Opportunity (need)",
|
|
16428
|
+
jtbd: "Struggle",
|
|
16429
|
+
vpc: "Customer Pain"
|
|
16430
|
+
},
|
|
16431
|
+
designations: {
|
|
16432
|
+
pain: "Pain Point",
|
|
16433
|
+
gap: "Need",
|
|
16434
|
+
desire: "Desire",
|
|
16435
|
+
constraint: "Constraint"
|
|
16436
|
+
}
|
|
16437
|
+
},
|
|
16438
|
+
// ── opportunity ──────────────────────────────────────────────────────────────
|
|
16439
|
+
{
|
|
16440
|
+
id: "opportunity",
|
|
16441
|
+
canonical_label: "Opportunity",
|
|
16442
|
+
alt_labels: ["product opportunity", "market opportunity", "user opportunity"],
|
|
16443
|
+
framework_labels: {
|
|
16444
|
+
ost: "Opportunity"
|
|
16445
|
+
}
|
|
16446
|
+
},
|
|
16447
|
+
// ── solution ─────────────────────────────────────────────────────────────────
|
|
16448
|
+
{
|
|
16449
|
+
id: "solution",
|
|
16450
|
+
canonical_label: "Solution",
|
|
16451
|
+
alt_labels: ["proposed solution", "solution idea", "concept", "approach"],
|
|
16452
|
+
framework_labels: {
|
|
16453
|
+
ost: "Solution",
|
|
16454
|
+
design_thinking: "Solution",
|
|
16455
|
+
lean_canvas: "Solution",
|
|
16456
|
+
rice: "Scored Solution"
|
|
16457
|
+
}
|
|
16458
|
+
},
|
|
16459
|
+
// ── experiment (CONSOLIDATED: absorbs ab_test, growth_experiment, pricing_experiment) ──
|
|
16460
|
+
{
|
|
16461
|
+
id: "experiment",
|
|
16462
|
+
canonical_label: "Experiment",
|
|
16463
|
+
alt_labels: [
|
|
16464
|
+
"test",
|
|
16465
|
+
"validation",
|
|
16466
|
+
"ab test",
|
|
16467
|
+
"a/b test",
|
|
16468
|
+
"split test",
|
|
16469
|
+
"growth experiment",
|
|
16470
|
+
"pricing experiment",
|
|
16471
|
+
"usability test",
|
|
16472
|
+
"discovery experiment"
|
|
16473
|
+
],
|
|
16474
|
+
framework_labels: {
|
|
16475
|
+
ost: "Experiment",
|
|
16476
|
+
design_thinking: "Test",
|
|
16477
|
+
lean_startup: "Experiment"
|
|
16478
|
+
},
|
|
16479
|
+
designations: {
|
|
16480
|
+
discovery: "Discovery Experiment",
|
|
16481
|
+
ab_test: "A/B Test",
|
|
16482
|
+
growth: "Growth Experiment",
|
|
16483
|
+
pricing: "Pricing Experiment",
|
|
16484
|
+
usability: "Usability Test"
|
|
16485
|
+
}
|
|
16486
|
+
},
|
|
16487
|
+
// ── hypothesis ───────────────────────────────────────────────────────────────
|
|
16488
|
+
{
|
|
16489
|
+
id: "hypothesis",
|
|
16490
|
+
canonical_label: "Hypothesis",
|
|
16491
|
+
alt_labels: ["bet", "testable assumption", "leap of faith"],
|
|
16492
|
+
framework_labels: {
|
|
16493
|
+
lean_startup: "Hypothesis",
|
|
16494
|
+
running_lean: "Riskiest Assumption",
|
|
16495
|
+
lean_canvas: "Riskiest Assumption"
|
|
16496
|
+
}
|
|
16497
|
+
},
|
|
16498
|
+
// ── metric (CONSOLIDATED: absorbs kpi, north_star_metric, input_metric, metric_definition) ──
|
|
16499
|
+
{
|
|
16500
|
+
id: "metric",
|
|
16501
|
+
canonical_label: "Metric",
|
|
16502
|
+
alt_labels: [
|
|
16503
|
+
"kpi",
|
|
16504
|
+
"key performance indicator",
|
|
16505
|
+
"north star metric",
|
|
16506
|
+
"nsm",
|
|
16507
|
+
"input metric",
|
|
16508
|
+
"output metric",
|
|
16509
|
+
"metric definition",
|
|
16510
|
+
"measure",
|
|
16511
|
+
"indicator",
|
|
16512
|
+
"signal",
|
|
16513
|
+
"counter metric",
|
|
15497
16514
|
"guardrail metric"
|
|
15498
16515
|
],
|
|
15499
16516
|
framework_labels: {
|
|
@@ -16325,7 +17342,10 @@ var STRATEGY_OUTCOMES_PLAYBOOK = {
|
|
|
16325
17342
|
region: "strategy_outcomes",
|
|
16326
17343
|
is_canonical: true,
|
|
16327
17344
|
related_framework_ids: ["okr-framework", "three-horizons", "north-star-metric", "metrics-tree", "wardley-map"],
|
|
16328
|
-
|
|
17345
|
+
// DT-PB-3: anchor is `outcome`, not `objective`. The creation_sequence
|
|
17346
|
+
// creates outcome (step 3) before objective (step 4), and outcome is the
|
|
17347
|
+
// strategy region's gravitational centre (objectives translate outcomes).
|
|
17348
|
+
target_anchor_entity: "outcome",
|
|
16329
17349
|
creation_sequence: [
|
|
16330
17350
|
seqStep(
|
|
16331
17351
|
1,
|
|
@@ -16481,8 +17501,12 @@ var DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK = {
|
|
|
16481
17501
|
seqStep(
|
|
16482
17502
|
8,
|
|
16483
17503
|
"Test",
|
|
16484
|
-
|
|
16485
|
-
|
|
17504
|
+
// DT-PB-1: was `experiment` — which resolves to NO canonical edge with
|
|
17505
|
+
// hypothesis or test_plan, forcing an orphan. `experiment_run` is the
|
|
17506
|
+
// hypothesis-linked test unit (experiment_run_validates_hypothesis,
|
|
17507
|
+
// test_plan_ran_as_experiment_run, experiment_run_yields_evidence).
|
|
17508
|
+
["experiment_run", "test_plan", "evidence"],
|
|
17509
|
+
"Validate with targeted experiment runs. Close the loop between research and action."
|
|
16486
17510
|
)
|
|
16487
17511
|
]
|
|
16488
17512
|
};
|
|
@@ -16529,8 +17553,8 @@ var MARKET_COMPETITIVE_PLAYBOOK = {
|
|
|
16529
17553
|
seqStep(
|
|
16530
17554
|
6,
|
|
16531
17555
|
"Moves",
|
|
16532
|
-
["
|
|
16533
|
-
"Look where competitors are weak and trends are strong. That intersection is where your moves live
|
|
17556
|
+
["competitive_battle_card"],
|
|
17557
|
+
"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.)"
|
|
16534
17558
|
)
|
|
16535
17559
|
]
|
|
16536
17560
|
};
|
|
@@ -16943,8 +17967,8 @@ var OPERATIONS_QUALITY_PLAYBOOK = {
|
|
|
16943
17967
|
seqStep(
|
|
16944
17968
|
5,
|
|
16945
17969
|
"Quality Gates",
|
|
16946
|
-
["test_suite", "test_case", "regression_test", "qa_session"],
|
|
16947
|
-
"Establish what does not ship until tests pass. Define the test pyramid: unit, integration, end-to-end."
|
|
17970
|
+
["test_suite", "test_case", "regression_test", "qa_session", "feature", "bug"],
|
|
17971
|
+
"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)."
|
|
16948
17972
|
),
|
|
16949
17973
|
seqStep(
|
|
16950
17974
|
6,
|
|
@@ -18599,7 +19623,7 @@ var PORTFOLIO_GUIDE = {
|
|
|
18599
19623
|
var WORKSPACE_GUIDE = {
|
|
18600
19624
|
domain_id: "workspace",
|
|
18601
19625
|
anchor_entity: "workspace",
|
|
18602
|
-
creation_sequence: ["workspace"],
|
|
19626
|
+
creation_sequence: ["workspace", "framework_exercise"],
|
|
18603
19627
|
patterns: [],
|
|
18604
19628
|
required_bridges: [],
|
|
18605
19629
|
anti_patterns: [
|
|
@@ -21011,7 +22035,7 @@ var UPG_ANTI_PATTERNS = [
|
|
|
21011
22035
|
]
|
|
21012
22036
|
},
|
|
21013
22037
|
why_it_matters: "Without any chain link, every downstream artefact (need, opportunity, feature) loses its anchor. Features end up addressing demographics instead of struggles.",
|
|
21014
|
-
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.",
|
|
22038
|
+
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.",
|
|
21015
22039
|
stages: ["concept", "validation", "build", "beta", "launch", "growth", "mature"],
|
|
21016
22040
|
severity: "high",
|
|
21017
22041
|
source: { kind: "practitioner", attribution: "Clayton Christensen, Jobs to Be Done" }
|
|
@@ -21151,7 +22175,7 @@ var UPG_ANTI_PATTERNS = [
|
|
|
21151
22175
|
]
|
|
21152
22176
|
},
|
|
21153
22177
|
why_it_matters: "OKRs without measurable key results cannot be tracked, debated, or learned from. The graph carries intent but not accountability.",
|
|
21154
|
-
remediation: "For each `objective`, define 2\u20134 `key_result` entities and link via `objective_achieved_through_key_result`. Use `/upg-okr` to author.",
|
|
22178
|
+
remediation: "For each `objective`, define 2\u20134 `key_result` entities and link via `objective_achieved_through_key_result`. Use `/upg-new-okr` to author.",
|
|
21155
22179
|
stages: ["validation", "build", "beta", "launch", "growth", "mature"],
|
|
21156
22180
|
severity: "high",
|
|
21157
22181
|
source: { kind: "book", citation: "Measure What Matters, John Doerr (2017)" }
|
|
@@ -21211,7 +22235,7 @@ var UPG_ANTI_PATTERNS = [
|
|
|
21211
22235
|
}
|
|
21212
22236
|
},
|
|
21213
22237
|
why_it_matters: 'A graph with one persona past validation is usually carrying an unexamined "everyone is the same user" assumption.',
|
|
21214
|
-
remediation: "Add personas representing the next 1\u20132 most distinct user segments. Use `/upg-persona`.",
|
|
22238
|
+
remediation: "Add personas representing the next 1\u20132 most distinct user segments. Use `/upg-new-persona`.",
|
|
21215
22239
|
stages: ["validation", "build", "beta", "launch", "growth", "mature"],
|
|
21216
22240
|
severity: "medium",
|
|
21217
22241
|
source: { kind: "practitioner", attribution: "Alan Cooper, The Inmates Are Running the Asylum" }
|
|
@@ -21229,7 +22253,7 @@ var UPG_ANTI_PATTERNS = [
|
|
|
21229
22253
|
]
|
|
21230
22254
|
},
|
|
21231
22255
|
why_it_matters: "Build-only graphs commit the team to delivery without a learning loop. Every shipped feature becomes a permanent assumption.",
|
|
21232
|
-
remediation: "Spin up at least one `experiment_plan` or `hypothesis` per quarter's build batch. Use `/upg-
|
|
22256
|
+
remediation: "Spin up at least one `experiment_plan` or `hypothesis` per quarter's build batch. Use `/upg-new-discovery` or `/upg-new-hypothesis`.",
|
|
21233
22257
|
stages: ["build", "beta", "launch", "growth"],
|
|
21234
22258
|
severity: "high",
|
|
21235
22259
|
source: { kind: "practitioner", attribution: "Marty Cagan, Inspired (continuous discovery)" }
|
|
@@ -21520,19 +22544,31 @@ var REFLECT_MODES = [
|
|
|
21520
22544
|
];
|
|
21521
22545
|
|
|
21522
22546
|
// src/approaches/definitions/index.ts
|
|
22547
|
+
function deriveFrameworkExamples() {
|
|
22548
|
+
const byApproach = {
|
|
22549
|
+
plan: [],
|
|
22550
|
+
inspect: [],
|
|
22551
|
+
prioritise: [],
|
|
22552
|
+
trace: [],
|
|
22553
|
+
reflect: []
|
|
22554
|
+
};
|
|
22555
|
+
for (const fw of UPG_FRAMEWORKS) {
|
|
22556
|
+
for (const approachId of fw.approach_ids ?? []) {
|
|
22557
|
+
if (approachId in byApproach) {
|
|
22558
|
+
byApproach[approachId].push(fw.id);
|
|
22559
|
+
}
|
|
22560
|
+
}
|
|
22561
|
+
}
|
|
22562
|
+
return byApproach;
|
|
22563
|
+
}
|
|
22564
|
+
var FRAMEWORK_EXAMPLES = deriveFrameworkExamples();
|
|
21523
22565
|
var PLAN = {
|
|
21524
22566
|
id: "plan",
|
|
21525
22567
|
label: "Plan",
|
|
21526
22568
|
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.',
|
|
21527
22569
|
question_answered: "what should I build next?",
|
|
21528
22570
|
signature_hint: "({ region?: UPGRegionId }) \u2192 { missing_entities, coverage_score }",
|
|
21529
|
-
framework_id_examples:
|
|
21530
|
-
"now-next-later",
|
|
21531
|
-
"moscow",
|
|
21532
|
-
"wardley-map",
|
|
21533
|
-
"okr-framework",
|
|
21534
|
-
"three-horizons"
|
|
21535
|
-
]
|
|
22571
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.plan
|
|
21536
22572
|
};
|
|
21537
22573
|
var INSPECT = {
|
|
21538
22574
|
id: "inspect",
|
|
@@ -21540,28 +22576,15 @@ var INSPECT = {
|
|
|
21540
22576
|
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).',
|
|
21541
22577
|
question_answered: "what's broken?",
|
|
21542
22578
|
signature_hint: "({ region?: UPGRegionId, entities?: entity_ids[] }) \u2192 { violations: [{ severity, kind, entity_id, description, fix_hint }] }",
|
|
21543
|
-
framework_id_examples:
|
|
21544
|
-
"heuristic-evaluation",
|
|
21545
|
-
"tech-debt-tracker",
|
|
21546
|
-
"accessibility-maturity-model",
|
|
21547
|
-
"cognitive-walkthrough",
|
|
21548
|
-
"blameless-postmortem"
|
|
21549
|
-
]
|
|
22579
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.inspect
|
|
21550
22580
|
};
|
|
21551
22581
|
var PRIORITISE = {
|
|
21552
22582
|
id: "prioritise",
|
|
21553
22583
|
label: "Prioritise",
|
|
21554
|
-
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,
|
|
22584
|
+
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).`,
|
|
21555
22585
|
question_answered: "what's most important?",
|
|
21556
22586
|
signature_hint: "({ candidates: entity_ids[], framework_id }) \u2192 { ranked: [{ entity_id, score, rationale }], framework_used }",
|
|
21557
|
-
framework_id_examples:
|
|
21558
|
-
"rice-scoring",
|
|
21559
|
-
"ice-scoring",
|
|
21560
|
-
"kano-model",
|
|
21561
|
-
"cost-of-delay",
|
|
21562
|
-
"moscow",
|
|
21563
|
-
"wsjf"
|
|
21564
|
-
]
|
|
22587
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.prioritise
|
|
21565
22588
|
};
|
|
21566
22589
|
var TRACE = {
|
|
21567
22590
|
id: "trace",
|
|
@@ -21569,34 +22592,15 @@ var TRACE = {
|
|
|
21569
22592
|
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.',
|
|
21570
22593
|
question_answered: "walk a meaningful path through existing graph",
|
|
21571
22594
|
signature_hint: "({ anchor: entity_id, path: UPGEntityType[], edges_override?: (string | null)[] }) \u2192 { trail: [{ depth, entity_id, edge_type_in }], reached: entity_id[] }",
|
|
21572
|
-
framework_id_examples:
|
|
21573
|
-
"opportunity-solution-tree",
|
|
21574
|
-
"strategic-cascade",
|
|
21575
|
-
"metrics-tree",
|
|
21576
|
-
"user-journey-map",
|
|
21577
|
-
"impact-map",
|
|
21578
|
-
"dependency-map"
|
|
21579
|
-
]
|
|
22595
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.trace
|
|
21580
22596
|
};
|
|
21581
22597
|
var REFLECT = {
|
|
21582
22598
|
id: "reflect",
|
|
21583
22599
|
label: "Reflect",
|
|
21584
|
-
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.
|
|
22600
|
+
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.',
|
|
21585
22601
|
question_answered: "what should I be questioning?",
|
|
21586
22602
|
signature_hint: "({ scope?: UPGRegionId | entity_id | null, mode?: 'assumptions' | 'alternatives' | 'blind-spots' | 'load-bearing' }) \u2192 { prompts: [{ kind, question, target_entities? }] }",
|
|
21587
|
-
framework_id_examples:
|
|
21588
|
-
// Reflection classics: the five canonical reflect frameworks.
|
|
21589
|
-
"five-whys",
|
|
21590
|
-
"pre-mortem",
|
|
21591
|
-
"red-team",
|
|
21592
|
-
"devils-advocate",
|
|
21593
|
-
"second-order-thinking",
|
|
21594
|
-
// Reflective ceremonies + reflective JTBD lens already in the catalog.
|
|
21595
|
-
"retrospective",
|
|
21596
|
-
"four-forces-of-progress",
|
|
21597
|
-
"assumption-canvas",
|
|
21598
|
-
"win-loss-analysis"
|
|
21599
|
-
]
|
|
22603
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.reflect
|
|
21600
22604
|
};
|
|
21601
22605
|
var UPG_APPROACHES = [PLAN, INSPECT, PRIORITISE, TRACE, REFLECT];
|
|
21602
22606
|
var UPG_APPROACHES_BY_ID = Object.fromEntries(
|
|
@@ -23627,7 +24631,7 @@ var NODE_KEY_ORDER = [
|
|
|
23627
24631
|
"sort_order",
|
|
23628
24632
|
"properties"
|
|
23629
24633
|
];
|
|
23630
|
-
var EDGE_KEY_ORDER = ["id", "source", "target", "type", "mapping_confidence"];
|
|
24634
|
+
var EDGE_KEY_ORDER = ["id", "source", "target", "type", "mapping_confidence", "properties"];
|
|
23631
24635
|
var CROSS_EDGE_KEY_ORDER = ["id", "source", "target", "type", "source_product_id", "target_product_id", "mapping_confidence"];
|
|
23632
24636
|
var PRODUCT_KEY_ORDER = ["id", "title", "description", "stage", "properties"];
|
|
23633
24637
|
function canonicalNode(node) {
|
|
@@ -23639,7 +24643,8 @@ function canonicalNode(node) {
|
|
|
23639
24643
|
}
|
|
23640
24644
|
function canonicalEdge(edge) {
|
|
23641
24645
|
return orderedObject(edge, EDGE_KEY_ORDER, {
|
|
23642
|
-
forceKeys: ["id", "source", "target", "type"]
|
|
24646
|
+
forceKeys: ["id", "source", "target", "type"],
|
|
24647
|
+
openKeys: ["properties"]
|
|
23643
24648
|
});
|
|
23644
24649
|
}
|
|
23645
24650
|
function canonicalCrossEdge(edge) {
|
|
@@ -23793,7 +24798,7 @@ function isCanonical(text) {
|
|
|
23793
24798
|
}
|
|
23794
24799
|
|
|
23795
24800
|
// src/index.ts
|
|
23796
|
-
var UPG_VERSION = "0.8.
|
|
24801
|
+
var UPG_VERSION = "0.8.4";
|
|
23797
24802
|
var UPG_FORMAT_VERSION = "0.4.0";
|
|
23798
24803
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
23799
24804
|
var UPG_TYPES = getTypes();
|
|
@@ -23941,6 +24946,7 @@ export {
|
|
|
23941
24946
|
collectSlugsForType,
|
|
23942
24947
|
compareVersions,
|
|
23943
24948
|
computeBodyChecksum,
|
|
24949
|
+
edgeCarriesProperties,
|
|
23944
24950
|
evaluateAntiPatterns,
|
|
23945
24951
|
findInvalidStatusMigrationTargets,
|
|
23946
24952
|
formatUpgText,
|