@unified-product-graph/mcp-server 0.8.0 → 0.8.2
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 +11 -0
- package/README.md +1 -1
- package/TOOLS.md +20 -14
- package/dist/index.js +1289 -485
- package/dist/index.js.map +1 -1
- package/dist/tools-manifest.json +95 -76
- package/package.json +1 -1
- package/scripts/claudemd-snippet.md +7 -7
- package/scripts/install-skills.sh +2 -2
- package/skills/upg/SKILL.md +41 -41
- package/skills/{upg-gaps → upg-check-gaps}/SKILL.md +40 -43
- package/skills/{upg-schema-health → upg-check-schema}/SKILL.md +7 -7
- package/skills/{upg-schema-evolve → upg-check-schema-coverage}/SKILL.md +12 -12
- package/skills/{upg-schema-edges → upg-check-schema-edges}/SKILL.md +3 -3
- package/skills/{upg-schema-consolidate → upg-check-schema-merge}/SKILL.md +5 -5
- package/skills/upg-context/SKILL.md +96 -72
- package/skills/upg-context-intelligence/SKILL.md +23 -27
- package/skills/upg-design-system/SKILL.md +21 -26
- package/skills/{upg-verify → upg-find-untracked}/SKILL.md +7 -12
- package/skills/{upg-rollback → upg-fix-rollback}/SKILL.md +6 -12
- package/skills/{upg-migrate → upg-fix-types}/SKILL.md +5 -9
- package/skills/upg-link/SKILL.md +125 -0
- package/skills/{upg-discover → upg-new-discovery}/SKILL.md +42 -58
- package/skills/{upg-capture → upg-new-from-session}/SKILL.md +13 -15
- package/skills/{upg-template → upg-new-from-template}/SKILL.md +8 -12
- package/skills/{upg-init → upg-new-graph}/SKILL.md +50 -82
- package/skills/{upg-hypothesis → upg-new-hypothesis}/SKILL.md +27 -36
- package/skills/{upg-launch → upg-new-launch}/SKILL-DETAIL.md +36 -92
- package/skills/{upg-launch → upg-new-launch}/SKILL.md +8 -18
- package/skills/{upg-okr → upg-new-okr}/SKILL-DETAIL.md +28 -46
- package/skills/{upg-okr → upg-new-okr}/SKILL.md +3 -3
- package/skills/{upg-persona → upg-new-persona}/SKILL.md +35 -67
- package/skills/{upg-research → upg-new-research}/SKILL.md +25 -33
- package/skills/{upg-schema-update → upg-new-schema-type}/SKILL.md +2 -2
- package/skills/{upg-strategy → upg-new-strategy}/SKILL.md +21 -27
- package/skills/upg-prioritise/SKILL.md +4 -4
- package/skills/upg-reflect/SKILL.md +7 -7
- package/skills/{upg-feedback → upg-send-feedback}/SKILL.md +30 -51
- package/skills/{upg-diff → upg-show-diff}/SKILL.md +6 -12
- package/skills/{upg-inspect → upg-show-entity}/SKILL.md +7 -9
- package/skills/{upg-impact → upg-show-impact}/SKILL.md +11 -15
- package/skills/{upg-journey → upg-show-journey}/SKILL.md +31 -32
- package/skills/{upg-analytics → upg-show-metrics}/SKILL.md +9 -12
- package/skills/{upg-schema-changelog → upg-show-schema-changelog}/SKILL.md +5 -5
- package/skills/{upg-status → upg-show-status}/SKILL.md +39 -40
- package/skills/{upg-tree → upg-show-tree}/SKILL.md +15 -15
- package/skills/{upg-export → upg-sync-export}/SKILL.md +10 -13
- package/skills/{upg-import → upg-sync-import}/SKILL.md +7 -13
- package/skills/{upg-pull → upg-sync-pull}/SKILL-DETAIL.md +13 -17
- package/skills/{upg-pull → upg-sync-pull}/SKILL.md +3 -3
- package/skills/{upg-push → upg-sync-push}/SKILL-DETAIL.md +4 -10
- package/skills/{upg-push → upg-sync-push}/SKILL.md +4 -4
- package/skills/{upg-snapshot → upg-sync-snapshot}/SKILL.md +2 -6
- package/skills/upg-trace/SKILL.md +7 -7
- package/skills/{upg-workspace → upg-use-workspace}/SKILL.md +8 -14
- package/skills/{upg-run → upg-walk-playbook}/SKILL.md +14 -14
- package/skills/upg-walk-region/SKILL-DETAIL.md +320 -0
- package/skills/upg-walk-region/SKILL.md +89 -0
- package/skills/upg-connect/SKILL.md +0 -167
- package/skills/upg-explore/SKILL-DETAIL.md +0 -481
- package/skills/upg-explore/SKILL.md +0 -297
package/dist/index.js
CHANGED
|
@@ -20,50 +20,10 @@ import {
|
|
|
20
20
|
// src/lib/server-context.ts
|
|
21
21
|
import * as fsp from "fs/promises";
|
|
22
22
|
import * as path from "path";
|
|
23
|
-
import { createHash } from "crypto";
|
|
24
|
-
function text(s) {
|
|
25
|
-
return { content: [{ type: "text", text: s }] };
|
|
26
|
-
}
|
|
27
|
-
function textError(s) {
|
|
28
|
-
return { content: [{ type: "text", text: s }], isError: true };
|
|
29
|
-
}
|
|
30
|
-
function createSessionContext() {
|
|
31
|
-
return {
|
|
32
|
-
lens: "product",
|
|
33
|
-
skills_invoked: [],
|
|
34
|
-
recommendations_given: [],
|
|
35
|
-
focus_area: null,
|
|
36
|
-
custom: {}
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
function createQueryCache() {
|
|
40
|
-
return { entries: /* @__PURE__ */ new Map(), counter: 0 };
|
|
41
|
-
}
|
|
42
|
-
function syncFilePath(upgPath) {
|
|
43
|
-
const dir = path.dirname(upgPath);
|
|
44
|
-
const base = path.basename(upgPath, ".upg");
|
|
45
|
-
return path.join(dir, `${base}.upg-sync`);
|
|
46
|
-
}
|
|
47
|
-
async function readSyncState(upgPath) {
|
|
48
|
-
const p = syncFilePath(upgPath);
|
|
49
|
-
try {
|
|
50
|
-
const raw = await fsp.readFile(p, "utf-8");
|
|
51
|
-
return JSON.parse(raw);
|
|
52
|
-
} catch {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
async function writeSyncState(upgPath, state) {
|
|
57
|
-
const p = syncFilePath(upgPath);
|
|
58
|
-
await fsp.writeFile(p, JSON.stringify(state, null, 2) + "\n", "utf-8");
|
|
59
|
-
}
|
|
60
|
-
async function hashFile(filePath) {
|
|
61
|
-
const content = await fsp.readFile(filePath, "utf-8");
|
|
62
|
-
return createHash("sha256").update(content).digest("hex");
|
|
63
|
-
}
|
|
23
|
+
import { createHash as createHash2 } from "crypto";
|
|
64
24
|
|
|
65
25
|
// ../upg-spec/dist/index.js
|
|
66
|
-
import { createHash
|
|
26
|
+
import { createHash } from "crypto";
|
|
67
27
|
var UPG_DOMAINS = [
|
|
68
28
|
{
|
|
69
29
|
id: "strategy",
|
|
@@ -993,7 +953,7 @@ var UPG_EDGE_CATALOG = {
|
|
|
993
953
|
// product → persona is the most fundamental relationship in the
|
|
994
954
|
// user domain ("who is this product for?") and was the only way to
|
|
995
955
|
// anchor a fresh persona to its product before this edge existed. Without
|
|
996
|
-
// it, the natural agent path through `/upg-persona` produced an orphan
|
|
956
|
+
// it, the natural agent path through `/upg-new-persona` produced an orphan
|
|
997
957
|
// persona only attached laterally via `ideal_customer_profile_maps_to_persona`
|
|
998
958
|
// or `positioning_resonates_with_persona`. Semantic, not hierarchy: a
|
|
999
959
|
// product doesn't "contain" personas; it targets them.
|
|
@@ -2208,6 +2168,13 @@ var UPG_EDGE_CATALOG = {
|
|
|
2208
2168
|
// release strategy to the concrete deployments it governs.
|
|
2209
2169
|
incident_affects_feature: { forward_verb: "affects", reverse_verb: "affected_by", classification: "cross-domain", source_type: "incident", target_type: "feature" },
|
|
2210
2170
|
release_strategy_used_by_deployment: { forward_verb: "used_by", reverse_verb: "uses", classification: "cross-domain", source_type: "release_strategy", target_type: "deployment" },
|
|
2171
|
+
// v0.8.2 (UPG-615): ITIL/ITSM incident management explicitly links an incident
|
|
2172
|
+
// to the customer-facing support tickets/cases it spawns — when a service
|
|
2173
|
+
// breaks, customers raise tickets; the incident is the cause, the ticket the
|
|
2174
|
+
// effect. Closes the otherwise-unmediated "Customer Support" island in
|
|
2175
|
+
// `playbook:operations-quality`, binding `support_ticket` to the incident/ops
|
|
2176
|
+
// spine. Source: ITIL v4 incident management; DORA/SRE customer-facing impact.
|
|
2177
|
+
incident_generates_support_ticket: { forward_verb: "generates", reverse_verb: "generated_by", classification: "cross-domain", source_type: "incident", target_type: "support_ticket" },
|
|
2211
2178
|
// Cluster C: User Research linkage matrix.
|
|
2212
2179
|
// research_study → {participant, research_question, survey_response,
|
|
2213
2180
|
// interview_guide} containment edges already exist (49/49 in Wave 4).
|
|
@@ -11261,6 +11228,9 @@ var UPG_FRAMEWORKS = [
|
|
|
11261
11228
|
},
|
|
11262
11229
|
{
|
|
11263
11230
|
"id": "value-proposition-canvas",
|
|
11231
|
+
"approach_ids": [
|
|
11232
|
+
"trace"
|
|
11233
|
+
],
|
|
11264
11234
|
"name": "Value Proposition Canvas",
|
|
11265
11235
|
"version": "1.0.0",
|
|
11266
11236
|
"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.",
|
|
@@ -11365,6 +11335,9 @@ var UPG_FRAMEWORKS = [
|
|
|
11365
11335
|
},
|
|
11366
11336
|
{
|
|
11367
11337
|
"id": "persona-canvas",
|
|
11338
|
+
"approach_ids": [
|
|
11339
|
+
"trace"
|
|
11340
|
+
],
|
|
11368
11341
|
"name": "Persona Canvas",
|
|
11369
11342
|
"version": "1.0.0",
|
|
11370
11343
|
"description": "Demographics, goals, frustrations, JTBD: a structured template for creating research-backed personas.",
|
|
@@ -11477,6 +11450,9 @@ var UPG_FRAMEWORKS = [
|
|
|
11477
11450
|
},
|
|
11478
11451
|
{
|
|
11479
11452
|
"id": "empathy-map",
|
|
11453
|
+
"approach_ids": [
|
|
11454
|
+
"trace"
|
|
11455
|
+
],
|
|
11480
11456
|
"name": "Empathy Map",
|
|
11481
11457
|
"version": "1.0.0",
|
|
11482
11458
|
"description": "Visualise what a user says, thinks, does, and feels to build deeper empathy and uncover hidden needs.",
|
|
@@ -11637,6 +11613,7 @@ var UPG_FRAMEWORKS = [
|
|
|
11637
11613
|
"property": "evolution_stage",
|
|
11638
11614
|
"type": "enum",
|
|
11639
11615
|
"required": true,
|
|
11616
|
+
"scope": "framework",
|
|
11640
11617
|
"label": "Evolution Stage",
|
|
11641
11618
|
"description": "Where this component sits on the evolution axis",
|
|
11642
11619
|
"enum_values": [
|
|
@@ -11650,6 +11627,7 @@ var UPG_FRAMEWORKS = [
|
|
|
11650
11627
|
"property": "visibility",
|
|
11651
11628
|
"type": "number",
|
|
11652
11629
|
"required": true,
|
|
11630
|
+
"scope": "framework",
|
|
11653
11631
|
"label": "Visibility",
|
|
11654
11632
|
"description": "Y-axis position (0=infrastructure, 1=anchor/user)"
|
|
11655
11633
|
}
|
|
@@ -11659,6 +11637,7 @@ var UPG_FRAMEWORKS = [
|
|
|
11659
11637
|
"property": "evolution_stage",
|
|
11660
11638
|
"type": "enum",
|
|
11661
11639
|
"required": true,
|
|
11640
|
+
"scope": "framework",
|
|
11662
11641
|
"label": "Evolution Stage",
|
|
11663
11642
|
"description": "Where this component sits on the evolution axis",
|
|
11664
11643
|
"enum_values": [
|
|
@@ -11672,6 +11651,7 @@ var UPG_FRAMEWORKS = [
|
|
|
11672
11651
|
"property": "visibility",
|
|
11673
11652
|
"type": "number",
|
|
11674
11653
|
"required": true,
|
|
11654
|
+
"scope": "framework",
|
|
11675
11655
|
"label": "Visibility",
|
|
11676
11656
|
"description": "Y-axis position (0=infrastructure, 1=anchor/user)"
|
|
11677
11657
|
}
|
|
@@ -11681,6 +11661,7 @@ var UPG_FRAMEWORKS = [
|
|
|
11681
11661
|
"property": "evolution_stage",
|
|
11682
11662
|
"type": "enum",
|
|
11683
11663
|
"required": true,
|
|
11664
|
+
"scope": "framework",
|
|
11684
11665
|
"label": "Evolution Stage",
|
|
11685
11666
|
"description": "Where this component sits on the evolution axis",
|
|
11686
11667
|
"enum_values": [
|
|
@@ -11694,6 +11675,7 @@ var UPG_FRAMEWORKS = [
|
|
|
11694
11675
|
"property": "visibility",
|
|
11695
11676
|
"type": "number",
|
|
11696
11677
|
"required": true,
|
|
11678
|
+
"scope": "framework",
|
|
11697
11679
|
"label": "Visibility",
|
|
11698
11680
|
"description": "Y-axis position (0=infrastructure, 1=anchor/user)"
|
|
11699
11681
|
}
|
|
@@ -11703,6 +11685,7 @@ var UPG_FRAMEWORKS = [
|
|
|
11703
11685
|
"property": "evolution_stage",
|
|
11704
11686
|
"type": "enum",
|
|
11705
11687
|
"required": true,
|
|
11688
|
+
"scope": "framework",
|
|
11706
11689
|
"label": "Evolution Stage",
|
|
11707
11690
|
"description": 'Where this component sits on the evolution axis (need anchor is usually at "product" or "commodity")',
|
|
11708
11691
|
"enum_values": [
|
|
@@ -11716,6 +11699,7 @@ var UPG_FRAMEWORKS = [
|
|
|
11716
11699
|
"property": "visibility",
|
|
11717
11700
|
"type": "number",
|
|
11718
11701
|
"required": true,
|
|
11702
|
+
"scope": "framework",
|
|
11719
11703
|
"label": "Visibility",
|
|
11720
11704
|
"description": "Y-axis position (0=infrastructure, 1=anchor/user); needs sit at 1.0"
|
|
11721
11705
|
}
|
|
@@ -11756,6 +11740,9 @@ var UPG_FRAMEWORKS = [
|
|
|
11756
11740
|
},
|
|
11757
11741
|
{
|
|
11758
11742
|
"id": "business-model-canvas",
|
|
11743
|
+
"approach_ids": [
|
|
11744
|
+
"plan"
|
|
11745
|
+
],
|
|
11759
11746
|
"name": "Business Model Canvas",
|
|
11760
11747
|
"version": "1.0.0",
|
|
11761
11748
|
"description": "Nine building blocks that describe how an organisation creates, delivers, and captures value.",
|
|
@@ -11895,6 +11882,9 @@ var UPG_FRAMEWORKS = [
|
|
|
11895
11882
|
},
|
|
11896
11883
|
{
|
|
11897
11884
|
"id": "porter-five-forces",
|
|
11885
|
+
"approach_ids": [
|
|
11886
|
+
"inspect"
|
|
11887
|
+
],
|
|
11898
11888
|
"name": "Porter Five Forces",
|
|
11899
11889
|
"version": "1.0.0",
|
|
11900
11890
|
"description": "Analyse industry competitiveness through five forces: rivalry, new entrants, substitutes, buyer power, and supplier power.",
|
|
@@ -11984,6 +11974,9 @@ var UPG_FRAMEWORKS = [
|
|
|
11984
11974
|
},
|
|
11985
11975
|
{
|
|
11986
11976
|
"id": "swot-analysis",
|
|
11977
|
+
"approach_ids": [
|
|
11978
|
+
"inspect"
|
|
11979
|
+
],
|
|
11987
11980
|
"name": "SWOT Analysis",
|
|
11988
11981
|
"version": "1.0.0",
|
|
11989
11982
|
"description": "Map Strengths, Weaknesses, Opportunities, and Threats in a 2x2 grid. Internal vs external, helpful vs harmful.",
|
|
@@ -12310,6 +12303,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12310
12303
|
"type": "assessment",
|
|
12311
12304
|
"scale_id": "reach_5",
|
|
12312
12305
|
"required": true,
|
|
12306
|
+
"scope": "framework",
|
|
12313
12307
|
"label": "Reach",
|
|
12314
12308
|
"description": "How many users will this impact per quarter?"
|
|
12315
12309
|
},
|
|
@@ -12318,6 +12312,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12318
12312
|
"type": "assessment",
|
|
12319
12313
|
"scale_id": "impact_5",
|
|
12320
12314
|
"required": true,
|
|
12315
|
+
"scope": "framework",
|
|
12321
12316
|
"label": "Impact",
|
|
12322
12317
|
"description": "How much will this impact each user, on the impact scale?"
|
|
12323
12318
|
},
|
|
@@ -12326,6 +12321,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12326
12321
|
"type": "assessment",
|
|
12327
12322
|
"scale_id": "confidence_5",
|
|
12328
12323
|
"required": true,
|
|
12324
|
+
"scope": "framework",
|
|
12329
12325
|
"label": "Confidence",
|
|
12330
12326
|
"description": "How confident are you in the reach, impact, and effort estimates?"
|
|
12331
12327
|
},
|
|
@@ -12334,6 +12330,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12334
12330
|
"type": "assessment",
|
|
12335
12331
|
"scale_id": "effort_5",
|
|
12336
12332
|
"required": true,
|
|
12333
|
+
"scope": "framework",
|
|
12337
12334
|
"label": "Effort",
|
|
12338
12335
|
"description": "How much work is required to build and ship this, on the effort scale?"
|
|
12339
12336
|
}
|
|
@@ -12420,6 +12417,9 @@ var UPG_FRAMEWORKS = [
|
|
|
12420
12417
|
},
|
|
12421
12418
|
{
|
|
12422
12419
|
"id": "build-measure-learn",
|
|
12420
|
+
"approach_ids": [
|
|
12421
|
+
"reflect"
|
|
12422
|
+
],
|
|
12423
12423
|
"name": "Build-Measure-Learn",
|
|
12424
12424
|
"version": "1.0.0",
|
|
12425
12425
|
"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.",
|
|
@@ -12555,6 +12555,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12555
12555
|
"property": "functional_response",
|
|
12556
12556
|
"type": "enum",
|
|
12557
12557
|
"required": true,
|
|
12558
|
+
"scope": "framework",
|
|
12558
12559
|
"label": "Functional Response",
|
|
12559
12560
|
"description": "How users feel when the feature IS present",
|
|
12560
12561
|
"enum_values": [
|
|
@@ -12569,6 +12570,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12569
12570
|
"property": "dysfunctional_response",
|
|
12570
12571
|
"type": "enum",
|
|
12571
12572
|
"required": true,
|
|
12573
|
+
"scope": "framework",
|
|
12572
12574
|
"label": "Dysfunctional Response",
|
|
12573
12575
|
"description": "How users feel when the feature IS NOT present",
|
|
12574
12576
|
"enum_values": [
|
|
@@ -12583,6 +12585,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12583
12585
|
"property": "delighter_count",
|
|
12584
12586
|
"type": "number",
|
|
12585
12587
|
"required": false,
|
|
12588
|
+
"scope": "framework",
|
|
12586
12589
|
"label": "Delighter classifications",
|
|
12587
12590
|
"description": "Count of survey responses classifying this feature as a delighter (attractive)"
|
|
12588
12591
|
},
|
|
@@ -12590,6 +12593,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12590
12593
|
"property": "performance_count",
|
|
12591
12594
|
"type": "number",
|
|
12592
12595
|
"required": false,
|
|
12596
|
+
"scope": "framework",
|
|
12593
12597
|
"label": "Performance classifications",
|
|
12594
12598
|
"description": "Count of survey responses classifying this feature as performance (one-dimensional)"
|
|
12595
12599
|
},
|
|
@@ -12597,6 +12601,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12597
12601
|
"property": "must_be_count",
|
|
12598
12602
|
"type": "number",
|
|
12599
12603
|
"required": false,
|
|
12604
|
+
"scope": "framework",
|
|
12600
12605
|
"label": "Must-be classifications",
|
|
12601
12606
|
"description": "Count of survey responses classifying this feature as must-be (basic)"
|
|
12602
12607
|
},
|
|
@@ -12604,6 +12609,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12604
12609
|
"property": "indifferent_count",
|
|
12605
12610
|
"type": "number",
|
|
12606
12611
|
"required": false,
|
|
12612
|
+
"scope": "framework",
|
|
12607
12613
|
"label": "Indifferent classifications",
|
|
12608
12614
|
"description": "Count of survey responses classifying this feature as indifferent"
|
|
12609
12615
|
}
|
|
@@ -12796,6 +12802,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12796
12802
|
"property": "moscow",
|
|
12797
12803
|
"type": "enum",
|
|
12798
12804
|
"required": true,
|
|
12805
|
+
"scope": "framework",
|
|
12799
12806
|
"label": "MoSCoW priority",
|
|
12800
12807
|
"description": "Which scope bucket this requirement falls into for the current release",
|
|
12801
12808
|
"enum_values": [
|
|
@@ -12806,16 +12813,7 @@ var UPG_FRAMEWORKS = [
|
|
|
12806
12813
|
]
|
|
12807
12814
|
}
|
|
12808
12815
|
]
|
|
12809
|
-
}
|
|
12810
|
-
"computed_properties": [
|
|
12811
|
-
{
|
|
12812
|
-
"property": "must_have_ratio",
|
|
12813
|
-
"expression": "must_count / total_count",
|
|
12814
|
-
"entity_type": "feature",
|
|
12815
|
-
"label": "Must-have Ratio",
|
|
12816
|
-
"format": "percentage"
|
|
12817
|
-
}
|
|
12818
|
-
]
|
|
12816
|
+
}
|
|
12819
12817
|
},
|
|
12820
12818
|
"structure": {
|
|
12821
12819
|
"pattern": "table"
|
|
@@ -12979,6 +12977,9 @@ var UPG_FRAMEWORKS = [
|
|
|
12979
12977
|
},
|
|
12980
12978
|
{
|
|
12981
12979
|
"id": "c4-model",
|
|
12980
|
+
"approach_ids": [
|
|
12981
|
+
"trace"
|
|
12982
|
+
],
|
|
12982
12983
|
"name": "C4 Model",
|
|
12983
12984
|
"version": "1.0.0",
|
|
12984
12985
|
"description": "Visualise software architecture at four levels of abstraction: System Context, Container, Component, and Code. Each level zooms in to reveal more detail.",
|
|
@@ -13071,6 +13072,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13071
13072
|
},
|
|
13072
13073
|
{
|
|
13073
13074
|
"id": "adr-log",
|
|
13075
|
+
"approach_ids": [
|
|
13076
|
+
"inspect"
|
|
13077
|
+
],
|
|
13074
13078
|
"name": "ADR Log",
|
|
13075
13079
|
"version": "1.0.0",
|
|
13076
13080
|
"description": "Architecture Decision Records: log decisions with context, options, and rationale.",
|
|
@@ -13184,6 +13188,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13184
13188
|
},
|
|
13185
13189
|
{
|
|
13186
13190
|
"id": "atomic-design",
|
|
13191
|
+
"approach_ids": [
|
|
13192
|
+
"trace"
|
|
13193
|
+
],
|
|
13187
13194
|
"name": "Atomic Design",
|
|
13188
13195
|
"version": "1.0.0",
|
|
13189
13196
|
"description": "Atoms, Molecules, Organisms, Templates, Pages: a methodology for creating design systems from the smallest elements up.",
|
|
@@ -13281,6 +13288,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13281
13288
|
},
|
|
13282
13289
|
{
|
|
13283
13290
|
"id": "double-diamond",
|
|
13291
|
+
"approach_ids": [
|
|
13292
|
+
"plan"
|
|
13293
|
+
],
|
|
13284
13294
|
"name": "Double Diamond",
|
|
13285
13295
|
"version": "1.0.0",
|
|
13286
13296
|
"description": "Discover, Define, Develop, Deliver: a four-phase divergent/convergent design process.",
|
|
@@ -13371,6 +13381,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13371
13381
|
},
|
|
13372
13382
|
{
|
|
13373
13383
|
"id": "dora-metrics",
|
|
13384
|
+
"approach_ids": [
|
|
13385
|
+
"inspect"
|
|
13386
|
+
],
|
|
13374
13387
|
"name": "DORA Metrics",
|
|
13375
13388
|
"version": "1.0.0",
|
|
13376
13389
|
"description": "Four key metrics for software delivery performance: deployment frequency, lead time, change failure rate, and time to restore.",
|
|
@@ -13430,16 +13443,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13430
13443
|
]
|
|
13431
13444
|
}
|
|
13432
13445
|
]
|
|
13433
|
-
}
|
|
13434
|
-
"computed_properties": [
|
|
13435
|
-
{
|
|
13436
|
-
"property": "stability_index",
|
|
13437
|
-
"expression": "change_failure_rate * mean_time_to_recovery",
|
|
13438
|
-
"entity_type": "metric",
|
|
13439
|
-
"label": "Stability Index",
|
|
13440
|
-
"format": "number"
|
|
13441
|
-
}
|
|
13442
|
-
]
|
|
13446
|
+
}
|
|
13443
13447
|
},
|
|
13444
13448
|
"structure": {
|
|
13445
13449
|
"pattern": "collection"
|
|
@@ -13568,6 +13572,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13568
13572
|
},
|
|
13569
13573
|
{
|
|
13570
13574
|
"id": "pirate-metrics-aarrr",
|
|
13575
|
+
"approach_ids": [
|
|
13576
|
+
"trace"
|
|
13577
|
+
],
|
|
13571
13578
|
"name": "Pirate Metrics AARRR",
|
|
13572
13579
|
"version": "1.0.0",
|
|
13573
13580
|
"description": "Track user lifecycle across five stages: Acquisition, Activation, Retention, Revenue, and Referral.",
|
|
@@ -13601,7 +13608,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13601
13608
|
"required_properties": {
|
|
13602
13609
|
"metric": [
|
|
13603
13610
|
{
|
|
13604
|
-
"property": "
|
|
13611
|
+
"property": "metric_category",
|
|
13605
13612
|
"type": "enum",
|
|
13606
13613
|
"required": true,
|
|
13607
13614
|
"label": "Lifecycle stage",
|
|
@@ -13615,16 +13622,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13615
13622
|
]
|
|
13616
13623
|
}
|
|
13617
13624
|
]
|
|
13618
|
-
}
|
|
13619
|
-
"computed_properties": [
|
|
13620
|
-
{
|
|
13621
|
-
"property": "conversion_rate",
|
|
13622
|
-
"expression": "(stage_exits / stage_entries) * 100",
|
|
13623
|
-
"entity_type": "metric",
|
|
13624
|
-
"label": "Stage Conversion",
|
|
13625
|
-
"format": "percentage"
|
|
13626
|
-
}
|
|
13627
|
-
]
|
|
13625
|
+
}
|
|
13628
13626
|
},
|
|
13629
13627
|
"structure": {
|
|
13630
13628
|
"pattern": "funnel",
|
|
@@ -13688,6 +13686,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13688
13686
|
},
|
|
13689
13687
|
{
|
|
13690
13688
|
"id": "north-star-metric",
|
|
13689
|
+
"approach_ids": [
|
|
13690
|
+
"plan"
|
|
13691
|
+
],
|
|
13691
13692
|
"name": "North Star Metric",
|
|
13692
13693
|
"version": "1.0.0",
|
|
13693
13694
|
"description": "One metric that best captures the core value you deliver. Supported by 3-5 input metrics that drive it.",
|
|
@@ -13721,7 +13722,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13721
13722
|
"required_properties": {
|
|
13722
13723
|
"metric": [
|
|
13723
13724
|
{
|
|
13724
|
-
"property": "
|
|
13725
|
+
"property": "designation",
|
|
13725
13726
|
"type": "enum",
|
|
13726
13727
|
"required": true,
|
|
13727
13728
|
"label": "Metric role",
|
|
@@ -13739,16 +13740,7 @@ var UPG_FRAMEWORKS = [
|
|
|
13739
13740
|
"description": "How strongly this input metric moves the North Star (input metrics only)"
|
|
13740
13741
|
}
|
|
13741
13742
|
]
|
|
13742
|
-
}
|
|
13743
|
-
"computed_properties": [
|
|
13744
|
-
{
|
|
13745
|
-
"property": "nsm_impact",
|
|
13746
|
-
"expression": "input_metric_value * leverage",
|
|
13747
|
-
"entity_type": "metric",
|
|
13748
|
-
"label": "NSM Impact",
|
|
13749
|
-
"format": "number"
|
|
13750
|
-
}
|
|
13751
|
-
]
|
|
13743
|
+
}
|
|
13752
13744
|
},
|
|
13753
13745
|
"structure": {
|
|
13754
13746
|
"pattern": "collection"
|
|
@@ -13784,6 +13776,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13784
13776
|
},
|
|
13785
13777
|
{
|
|
13786
13778
|
"id": "marketing-mix-4ps",
|
|
13779
|
+
"approach_ids": [
|
|
13780
|
+
"plan"
|
|
13781
|
+
],
|
|
13787
13782
|
"name": "Marketing Mix 4Ps",
|
|
13788
13783
|
"version": "1.0.0",
|
|
13789
13784
|
"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).",
|
|
@@ -13877,6 +13872,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13877
13872
|
},
|
|
13878
13873
|
{
|
|
13879
13874
|
"id": "bullseye-framework",
|
|
13875
|
+
"approach_ids": [
|
|
13876
|
+
"plan"
|
|
13877
|
+
],
|
|
13880
13878
|
"name": "Bullseye Framework",
|
|
13881
13879
|
"version": "1.0.0",
|
|
13882
13880
|
"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.",
|
|
@@ -13963,6 +13961,9 @@ var UPG_FRAMEWORKS = [
|
|
|
13963
13961
|
},
|
|
13964
13962
|
{
|
|
13965
13963
|
"id": "product-led-growth-framework",
|
|
13964
|
+
"approach_ids": [
|
|
13965
|
+
"plan"
|
|
13966
|
+
],
|
|
13966
13967
|
"name": "PLG Framework",
|
|
13967
13968
|
"version": "1.0.0",
|
|
13968
13969
|
"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.",
|
|
@@ -14145,6 +14146,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14145
14146
|
},
|
|
14146
14147
|
{
|
|
14147
14148
|
"id": "raci-matrix",
|
|
14149
|
+
"approach_ids": [
|
|
14150
|
+
"inspect"
|
|
14151
|
+
],
|
|
14148
14152
|
"name": "RACI Matrix",
|
|
14149
14153
|
"version": "1.0.0",
|
|
14150
14154
|
"description": "Assign roles: Responsible, Accountable, Consulted, Informed for each activity.",
|
|
@@ -14196,16 +14200,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14196
14200
|
"role": "item"
|
|
14197
14201
|
}
|
|
14198
14202
|
],
|
|
14199
|
-
"required_properties": {}
|
|
14200
|
-
"computed_properties": [
|
|
14201
|
-
{
|
|
14202
|
-
"property": "coverage_score",
|
|
14203
|
-
"expression": "assigned_count / total_activities",
|
|
14204
|
-
"entity_type": "team",
|
|
14205
|
-
"label": "RACI Coverage",
|
|
14206
|
-
"format": "percentage"
|
|
14207
|
-
}
|
|
14208
|
-
]
|
|
14203
|
+
"required_properties": {}
|
|
14209
14204
|
},
|
|
14210
14205
|
"structure": {
|
|
14211
14206
|
"pattern": "matrix"
|
|
@@ -14429,6 +14424,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14429
14424
|
},
|
|
14430
14425
|
{
|
|
14431
14426
|
"id": "team-health-check",
|
|
14427
|
+
"approach_ids": [
|
|
14428
|
+
"inspect"
|
|
14429
|
+
],
|
|
14432
14430
|
"name": "Team Health Check",
|
|
14433
14431
|
"version": "1.0.0",
|
|
14434
14432
|
"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.",
|
|
@@ -14486,16 +14484,7 @@ var UPG_FRAMEWORKS = [
|
|
|
14486
14484
|
"role": "item"
|
|
14487
14485
|
}
|
|
14488
14486
|
],
|
|
14489
|
-
"required_properties": {}
|
|
14490
|
-
"computed_properties": [
|
|
14491
|
-
{
|
|
14492
|
-
"property": "health_index",
|
|
14493
|
-
"expression": "(green_count - red_count) / total_indicators",
|
|
14494
|
-
"entity_type": "team",
|
|
14495
|
-
"label": "Health Index",
|
|
14496
|
-
"format": "number"
|
|
14497
|
-
}
|
|
14498
|
-
]
|
|
14487
|
+
"required_properties": {}
|
|
14499
14488
|
},
|
|
14500
14489
|
"structure": {
|
|
14501
14490
|
"pattern": "table"
|
|
@@ -14552,6 +14541,9 @@ var UPG_FRAMEWORKS = [
|
|
|
14552
14541
|
},
|
|
14553
14542
|
{
|
|
14554
14543
|
"id": "raid-log",
|
|
14544
|
+
"approach_ids": [
|
|
14545
|
+
"inspect"
|
|
14546
|
+
],
|
|
14555
14547
|
"name": "RAID Log",
|
|
14556
14548
|
"version": "1.0.0",
|
|
14557
14549
|
"description": "A project management register tracking Risks, Assumptions, Issues, and Dependencies, the four categories most likely to derail a project if left unmanaged.",
|
|
@@ -14571,6 +14563,11 @@ var UPG_FRAMEWORKS = [
|
|
|
14571
14563
|
"entityTypeId": "risk_register",
|
|
14572
14564
|
"description": "Risk or assumption logged with likelihood, impact, owner, and mitigation strategy"
|
|
14573
14565
|
},
|
|
14566
|
+
{
|
|
14567
|
+
"label": "Risk",
|
|
14568
|
+
"entityTypeId": "risk",
|
|
14569
|
+
"description": "Individual risk scored by probability and impact; severity = probability * impact"
|
|
14570
|
+
},
|
|
14574
14571
|
{
|
|
14575
14572
|
"label": "Dependency",
|
|
14576
14573
|
"entityTypeId": "dependency",
|
|
@@ -14593,6 +14590,10 @@ var UPG_FRAMEWORKS = [
|
|
|
14593
14590
|
"type": "risk_register",
|
|
14594
14591
|
"role": "item"
|
|
14595
14592
|
},
|
|
14593
|
+
{
|
|
14594
|
+
"type": "risk",
|
|
14595
|
+
"role": "scored_item"
|
|
14596
|
+
},
|
|
14596
14597
|
{
|
|
14597
14598
|
"type": "dependency",
|
|
14598
14599
|
"role": "item"
|
|
@@ -14606,7 +14607,24 @@ var UPG_FRAMEWORKS = [
|
|
|
14606
14607
|
"role": "item"
|
|
14607
14608
|
}
|
|
14608
14609
|
],
|
|
14609
|
-
"required_properties": {
|
|
14610
|
+
"required_properties": {
|
|
14611
|
+
"risk": [
|
|
14612
|
+
{
|
|
14613
|
+
"property": "probability",
|
|
14614
|
+
"type": "number",
|
|
14615
|
+
"required": true,
|
|
14616
|
+
"label": "Probability",
|
|
14617
|
+
"description": "Likelihood the risk materialises (risk.probability assessment)"
|
|
14618
|
+
},
|
|
14619
|
+
{
|
|
14620
|
+
"property": "impact",
|
|
14621
|
+
"type": "number",
|
|
14622
|
+
"required": true,
|
|
14623
|
+
"label": "Impact",
|
|
14624
|
+
"description": "Consequence severity if the risk materialises (risk.impact assessment)"
|
|
14625
|
+
}
|
|
14626
|
+
]
|
|
14627
|
+
},
|
|
14610
14628
|
"computed_properties": [
|
|
14611
14629
|
{
|
|
14612
14630
|
"property": "severity",
|
|
@@ -14667,106 +14685,1008 @@ var UPG_FRAMEWORKS = [
|
|
|
14667
14685
|
"Formal programme management would create overhead without value"
|
|
14668
14686
|
]
|
|
14669
14687
|
}
|
|
14670
|
-
}
|
|
14671
|
-
];
|
|
14672
|
-
var UPG_FRAMEWORKS_BY_ID = Object.fromEntries(
|
|
14673
|
-
UPG_FRAMEWORKS.map((fw) => [fw.id, fw])
|
|
14674
|
-
);
|
|
14675
|
-
var UPG_FRAMEWORKS_BY_CATEGORY = {};
|
|
14676
|
-
for (const fw of UPG_FRAMEWORKS) {
|
|
14677
|
-
if (!UPG_FRAMEWORKS_BY_CATEGORY[fw.category]) UPG_FRAMEWORKS_BY_CATEGORY[fw.category] = [];
|
|
14678
|
-
UPG_FRAMEWORKS_BY_CATEGORY[fw.category].push(fw);
|
|
14679
|
-
}
|
|
14680
|
-
var PRIORITY_LABELS = [
|
|
14681
|
-
// ── need (CONSOLIDATED: replaces pain_point + user_need) ─────────────────────
|
|
14682
|
-
{
|
|
14683
|
-
id: "need",
|
|
14684
|
-
canonical_label: "Need",
|
|
14685
|
-
alt_labels: [
|
|
14686
|
-
"pain point",
|
|
14687
|
-
"pain",
|
|
14688
|
-
"user need",
|
|
14689
|
-
"customer need",
|
|
14690
|
-
"problem",
|
|
14691
|
-
"struggle",
|
|
14692
|
-
"customer pain",
|
|
14693
|
-
"frustration",
|
|
14694
|
-
"gap",
|
|
14695
|
-
"unmet need",
|
|
14696
|
-
"user problem"
|
|
14697
|
-
],
|
|
14698
|
-
framework_labels: {
|
|
14699
|
-
lean_canvas: "Problem",
|
|
14700
|
-
design_thinking: "Pain Point",
|
|
14701
|
-
ost: "Opportunity (need)",
|
|
14702
|
-
jtbd: "Struggle",
|
|
14703
|
-
vpc: "Customer Pain"
|
|
14704
|
-
},
|
|
14705
|
-
designations: {
|
|
14706
|
-
pain: "Pain Point",
|
|
14707
|
-
gap: "Need",
|
|
14708
|
-
desire: "Desire",
|
|
14709
|
-
constraint: "Constraint"
|
|
14710
|
-
}
|
|
14711
|
-
},
|
|
14712
|
-
// ── opportunity ──────────────────────────────────────────────────────────────
|
|
14713
|
-
{
|
|
14714
|
-
id: "opportunity",
|
|
14715
|
-
canonical_label: "Opportunity",
|
|
14716
|
-
alt_labels: ["product opportunity", "market opportunity", "user opportunity"],
|
|
14717
|
-
framework_labels: {
|
|
14718
|
-
ost: "Opportunity"
|
|
14719
|
-
}
|
|
14720
|
-
},
|
|
14721
|
-
// ── solution ─────────────────────────────────────────────────────────────────
|
|
14722
|
-
{
|
|
14723
|
-
id: "solution",
|
|
14724
|
-
canonical_label: "Solution",
|
|
14725
|
-
alt_labels: ["proposed solution", "solution idea", "concept", "approach"],
|
|
14726
|
-
framework_labels: {
|
|
14727
|
-
ost: "Solution",
|
|
14728
|
-
design_thinking: "Solution",
|
|
14729
|
-
lean_canvas: "Solution",
|
|
14730
|
-
rice: "Scored Solution"
|
|
14731
|
-
}
|
|
14732
14688
|
},
|
|
14733
|
-
// ── experiment (CONSOLIDATED: absorbs ab_test, growth_experiment, pricing_experiment) ──
|
|
14734
14689
|
{
|
|
14735
|
-
id: "
|
|
14736
|
-
|
|
14737
|
-
|
|
14738
|
-
"test",
|
|
14739
|
-
"validation",
|
|
14740
|
-
"ab test",
|
|
14741
|
-
"a/b test",
|
|
14742
|
-
"split test",
|
|
14743
|
-
"growth experiment",
|
|
14744
|
-
"pricing experiment",
|
|
14745
|
-
"usability test",
|
|
14746
|
-
"discovery experiment"
|
|
14690
|
+
"id": "ice-scoring",
|
|
14691
|
+
"approach_ids": [
|
|
14692
|
+
"prioritise"
|
|
14747
14693
|
],
|
|
14748
|
-
|
|
14749
|
-
|
|
14750
|
-
|
|
14751
|
-
|
|
14694
|
+
"name": "ICE Scoring",
|
|
14695
|
+
"version": "1.0.0",
|
|
14696
|
+
"description": "Rate ideas by Impact, Confidence, and Ease on a 1-10 scale. Multiply for a composite score. Fast and lightweight.",
|
|
14697
|
+
"category": "prioritization",
|
|
14698
|
+
"origin": {
|
|
14699
|
+
"type": "practitioner",
|
|
14700
|
+
"attribution": "Sean Ellis",
|
|
14701
|
+
"description": "Created by Sean Ellis as a lightweight growth experiment scoring method. Widely adopted in growth teams.",
|
|
14702
|
+
"year": 2010,
|
|
14703
|
+
"license": "open_attribution"
|
|
14752
14704
|
},
|
|
14753
|
-
|
|
14754
|
-
|
|
14755
|
-
|
|
14756
|
-
|
|
14757
|
-
|
|
14758
|
-
|
|
14759
|
-
|
|
14760
|
-
|
|
14761
|
-
|
|
14762
|
-
|
|
14763
|
-
|
|
14764
|
-
|
|
14765
|
-
|
|
14766
|
-
|
|
14767
|
-
|
|
14768
|
-
|
|
14769
|
-
|
|
14705
|
+
"tags": [
|
|
14706
|
+
"prioritization",
|
|
14707
|
+
"table"
|
|
14708
|
+
],
|
|
14709
|
+
"slots": [
|
|
14710
|
+
{
|
|
14711
|
+
"label": "Items to score",
|
|
14712
|
+
"entityTypeId": "feature",
|
|
14713
|
+
"description": "Features or experiments being evaluated"
|
|
14714
|
+
},
|
|
14715
|
+
{
|
|
14716
|
+
"label": "Impact",
|
|
14717
|
+
"entityTypeId": "outcome",
|
|
14718
|
+
"description": "How much will this move the needle?"
|
|
14719
|
+
},
|
|
14720
|
+
{
|
|
14721
|
+
"label": "Confidence",
|
|
14722
|
+
"entityTypeId": "assumption",
|
|
14723
|
+
"description": "How sure are we about the impact?"
|
|
14724
|
+
},
|
|
14725
|
+
{
|
|
14726
|
+
"label": "Ease",
|
|
14727
|
+
"entityTypeId": "feature",
|
|
14728
|
+
"description": "How easy is this to implement?"
|
|
14729
|
+
}
|
|
14730
|
+
],
|
|
14731
|
+
"data": {
|
|
14732
|
+
"entity_types": [
|
|
14733
|
+
{
|
|
14734
|
+
"type": "feature",
|
|
14735
|
+
"role": "scored_item"
|
|
14736
|
+
},
|
|
14737
|
+
{
|
|
14738
|
+
"type": "outcome",
|
|
14739
|
+
"role": "item"
|
|
14740
|
+
},
|
|
14741
|
+
{
|
|
14742
|
+
"type": "assumption",
|
|
14743
|
+
"role": "item"
|
|
14744
|
+
}
|
|
14745
|
+
],
|
|
14746
|
+
"required_properties": {
|
|
14747
|
+
"feature": [
|
|
14748
|
+
{
|
|
14749
|
+
"property": "impact",
|
|
14750
|
+
"type": "number",
|
|
14751
|
+
"required": true,
|
|
14752
|
+
"scope": "framework",
|
|
14753
|
+
"label": "Impact",
|
|
14754
|
+
"description": "Expected impact on the target metric (1-10)"
|
|
14755
|
+
},
|
|
14756
|
+
{
|
|
14757
|
+
"property": "confidence",
|
|
14758
|
+
"type": "number",
|
|
14759
|
+
"required": true,
|
|
14760
|
+
"scope": "framework",
|
|
14761
|
+
"label": "Confidence",
|
|
14762
|
+
"description": "Confidence in the impact estimate (1-10)"
|
|
14763
|
+
},
|
|
14764
|
+
{
|
|
14765
|
+
"property": "ease",
|
|
14766
|
+
"type": "number",
|
|
14767
|
+
"required": true,
|
|
14768
|
+
"scope": "framework",
|
|
14769
|
+
"label": "Ease",
|
|
14770
|
+
"description": "Ease of implementation (1-10)"
|
|
14771
|
+
}
|
|
14772
|
+
]
|
|
14773
|
+
},
|
|
14774
|
+
"computed_properties": [
|
|
14775
|
+
{
|
|
14776
|
+
"property": "ice_score",
|
|
14777
|
+
"expression": "impact * confidence * ease",
|
|
14778
|
+
"entity_type": "feature",
|
|
14779
|
+
"label": "ICE Score",
|
|
14780
|
+
"format": "number"
|
|
14781
|
+
}
|
|
14782
|
+
]
|
|
14783
|
+
},
|
|
14784
|
+
"structure": {
|
|
14785
|
+
"pattern": "table"
|
|
14786
|
+
},
|
|
14787
|
+
"presentation": {
|
|
14788
|
+
"layout": {
|
|
14789
|
+
"type": "table",
|
|
14790
|
+
"columns": [
|
|
14791
|
+
{
|
|
14792
|
+
"property": "title",
|
|
14793
|
+
"label": "Items to score",
|
|
14794
|
+
"sortable": true
|
|
14795
|
+
},
|
|
14796
|
+
{
|
|
14797
|
+
"property": "impact",
|
|
14798
|
+
"label": "Impact",
|
|
14799
|
+
"sortable": true
|
|
14800
|
+
},
|
|
14801
|
+
{
|
|
14802
|
+
"property": "confidence",
|
|
14803
|
+
"label": "Confidence",
|
|
14804
|
+
"sortable": true
|
|
14805
|
+
},
|
|
14806
|
+
{
|
|
14807
|
+
"property": "ease",
|
|
14808
|
+
"label": "Ease",
|
|
14809
|
+
"sortable": true
|
|
14810
|
+
}
|
|
14811
|
+
]
|
|
14812
|
+
},
|
|
14813
|
+
"sort_by": {
|
|
14814
|
+
"property": "title",
|
|
14815
|
+
"direction": "asc"
|
|
14816
|
+
},
|
|
14817
|
+
"colour_by": "type",
|
|
14818
|
+
"card_fields": [
|
|
14819
|
+
"title",
|
|
14820
|
+
"description",
|
|
14821
|
+
"status"
|
|
14822
|
+
]
|
|
14823
|
+
},
|
|
14824
|
+
"education": {
|
|
14825
|
+
"purpose": "Provide a lightweight scoring model for early-stage ideas when detailed effort estimates are unavailable. Faster than RICE and useful for brainstorm triage.",
|
|
14826
|
+
"core_question": "Which ideas should we investigate further based on their potential impact, confidence in our assumptions, and implementation ease?",
|
|
14827
|
+
"when_to_use": [
|
|
14828
|
+
"You have more ideas or features than capacity to build them",
|
|
14829
|
+
"Stakeholders disagree on what to build next",
|
|
14830
|
+
"You need a transparent, defensible prioritisation process"
|
|
14831
|
+
],
|
|
14832
|
+
"when_not_to_use": [
|
|
14833
|
+
"You have a single obvious next step with no contention",
|
|
14834
|
+
"The backlog is small enough to sequence intuitively"
|
|
14835
|
+
]
|
|
14836
|
+
}
|
|
14837
|
+
},
|
|
14838
|
+
{
|
|
14839
|
+
"id": "wsjf",
|
|
14840
|
+
"approach_ids": [
|
|
14841
|
+
"prioritise"
|
|
14842
|
+
],
|
|
14843
|
+
"name": "WSJF (Weighted Shortest Job First)",
|
|
14844
|
+
"version": "1.0.0",
|
|
14845
|
+
"description": "Prioritise work by dividing Cost of Delay (user value + time criticality + risk reduction) by job duration to maximise economic throughput.",
|
|
14846
|
+
"category": "planning",
|
|
14847
|
+
"origin": {
|
|
14848
|
+
"type": "practitioner",
|
|
14849
|
+
"attribution": "Reinertsen / SAFe",
|
|
14850
|
+
"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.",
|
|
14851
|
+
"url": "https://www.scaledagileframework.com/wsjf/",
|
|
14852
|
+
"year": 2011,
|
|
14853
|
+
"license": "open_attribution"
|
|
14854
|
+
},
|
|
14855
|
+
"tags": [
|
|
14856
|
+
"planning",
|
|
14857
|
+
"table"
|
|
14858
|
+
],
|
|
14859
|
+
"slots": [
|
|
14860
|
+
{
|
|
14861
|
+
"label": "Backlog Items",
|
|
14862
|
+
"entityTypeId": "feature",
|
|
14863
|
+
"description": "Backlog Items: feature entries to evaluate"
|
|
14864
|
+
},
|
|
14865
|
+
{
|
|
14866
|
+
"label": "User/Business Value",
|
|
14867
|
+
"entityTypeId": "metric",
|
|
14868
|
+
"description": "User/Business Value: metric entries to evaluate"
|
|
14869
|
+
},
|
|
14870
|
+
{
|
|
14871
|
+
"label": "Time Criticality",
|
|
14872
|
+
"entityTypeId": "metric",
|
|
14873
|
+
"description": "How much value decays if delivery is delayed (deadlines, competition, seasonal windows)"
|
|
14874
|
+
},
|
|
14875
|
+
{
|
|
14876
|
+
"label": "Risk Reduction / Opportunity Enablement",
|
|
14877
|
+
"entityTypeId": "metric",
|
|
14878
|
+
"description": "Risk Reduction / Opportunity Enablement: metric entries to evaluate"
|
|
14879
|
+
},
|
|
14880
|
+
{
|
|
14881
|
+
"label": "Job Size",
|
|
14882
|
+
"entityTypeId": "metric",
|
|
14883
|
+
"description": "Estimated effort (story points, t-shirt size, or person-weeks)"
|
|
14884
|
+
}
|
|
14885
|
+
],
|
|
14886
|
+
"data": {
|
|
14887
|
+
"entity_types": [
|
|
14888
|
+
{
|
|
14889
|
+
"type": "feature",
|
|
14890
|
+
"role": "scored_item"
|
|
14891
|
+
},
|
|
14892
|
+
{
|
|
14893
|
+
"type": "metric",
|
|
14894
|
+
"role": "item"
|
|
14895
|
+
}
|
|
14896
|
+
],
|
|
14897
|
+
"required_properties": {
|
|
14898
|
+
"feature": [
|
|
14899
|
+
{
|
|
14900
|
+
"property": "user_value",
|
|
14901
|
+
"type": "number",
|
|
14902
|
+
"required": true,
|
|
14903
|
+
"scope": "framework",
|
|
14904
|
+
"label": "User/Business Value",
|
|
14905
|
+
"description": "Relative value to users and the business if delivered"
|
|
14906
|
+
},
|
|
14907
|
+
{
|
|
14908
|
+
"property": "time_criticality",
|
|
14909
|
+
"type": "number",
|
|
14910
|
+
"required": true,
|
|
14911
|
+
"scope": "framework",
|
|
14912
|
+
"label": "Time Criticality",
|
|
14913
|
+
"description": "How much value decays if delivery is delayed (deadlines, competition, seasonal windows)"
|
|
14914
|
+
},
|
|
14915
|
+
{
|
|
14916
|
+
"property": "risk_reduction",
|
|
14917
|
+
"type": "number",
|
|
14918
|
+
"required": true,
|
|
14919
|
+
"scope": "framework",
|
|
14920
|
+
"label": "Risk Reduction / Opportunity Enablement",
|
|
14921
|
+
"description": "Value from reducing risk or enabling future opportunities"
|
|
14922
|
+
},
|
|
14923
|
+
{
|
|
14924
|
+
"property": "job_size",
|
|
14925
|
+
"type": "number",
|
|
14926
|
+
"required": true,
|
|
14927
|
+
"scope": "framework",
|
|
14928
|
+
"label": "Job Size",
|
|
14929
|
+
"description": "Estimated effort (story points, t-shirt size, or person-weeks)"
|
|
14930
|
+
}
|
|
14931
|
+
]
|
|
14932
|
+
},
|
|
14933
|
+
"computed_properties": [
|
|
14934
|
+
{
|
|
14935
|
+
"property": "wsjf_score",
|
|
14936
|
+
"expression": "(user_value + time_criticality + risk_reduction) / job_size",
|
|
14937
|
+
"entity_type": "feature",
|
|
14938
|
+
"label": "WSJF Score",
|
|
14939
|
+
"format": "number"
|
|
14940
|
+
}
|
|
14941
|
+
]
|
|
14942
|
+
},
|
|
14943
|
+
"structure": {
|
|
14944
|
+
"pattern": "table"
|
|
14945
|
+
},
|
|
14946
|
+
"presentation": {
|
|
14947
|
+
"layout": {
|
|
14948
|
+
"type": "table",
|
|
14949
|
+
"columns": [
|
|
14950
|
+
{
|
|
14951
|
+
"property": "title",
|
|
14952
|
+
"label": "Backlog Items",
|
|
14953
|
+
"sortable": true
|
|
14954
|
+
},
|
|
14955
|
+
{
|
|
14956
|
+
"property": "user_value",
|
|
14957
|
+
"label": "User/Business Value",
|
|
14958
|
+
"sortable": true
|
|
14959
|
+
},
|
|
14960
|
+
{
|
|
14961
|
+
"property": "time_criticality",
|
|
14962
|
+
"label": "Time Criticality",
|
|
14963
|
+
"sortable": true
|
|
14964
|
+
},
|
|
14965
|
+
{
|
|
14966
|
+
"property": "risk_reduction",
|
|
14967
|
+
"label": "Risk Reduction / Opportunity Enablement",
|
|
14968
|
+
"sortable": true
|
|
14969
|
+
},
|
|
14970
|
+
{
|
|
14971
|
+
"property": "job_size",
|
|
14972
|
+
"label": "Job Size",
|
|
14973
|
+
"sortable": true
|
|
14974
|
+
},
|
|
14975
|
+
{
|
|
14976
|
+
"property": "wsjf_score",
|
|
14977
|
+
"label": "WSJF Score",
|
|
14978
|
+
"sortable": true
|
|
14979
|
+
}
|
|
14980
|
+
]
|
|
14981
|
+
},
|
|
14982
|
+
"sort_by": {
|
|
14983
|
+
"property": "title",
|
|
14984
|
+
"direction": "asc"
|
|
14985
|
+
},
|
|
14986
|
+
"colour_by": "type",
|
|
14987
|
+
"card_fields": [
|
|
14988
|
+
"title",
|
|
14989
|
+
"description",
|
|
14990
|
+
"status"
|
|
14991
|
+
]
|
|
14992
|
+
},
|
|
14993
|
+
"education": {
|
|
14994
|
+
"purpose": "Prioritise work by dividing the Cost of Delay by job duration, ensuring the most time-sensitive, valuable items are done first.",
|
|
14995
|
+
"core_question": "Considering the cost of waiting, which items should we start now to maximise economic benefit?",
|
|
14996
|
+
"when_to_use": [
|
|
14997
|
+
"You need to coordinate work across multiple teams or time horizons",
|
|
14998
|
+
"Stakeholders need visibility into what is coming and when",
|
|
14999
|
+
"You want to balance commitments with flexibility"
|
|
15000
|
+
],
|
|
15001
|
+
"when_not_to_use": [
|
|
15002
|
+
"The team is small enough that informal coordination works",
|
|
15003
|
+
"Plans would create false precision about uncertain outcomes"
|
|
15004
|
+
]
|
|
15005
|
+
}
|
|
15006
|
+
},
|
|
15007
|
+
{
|
|
15008
|
+
"id": "cost-of-delay",
|
|
15009
|
+
"approach_ids": [
|
|
15010
|
+
"prioritise"
|
|
15011
|
+
],
|
|
15012
|
+
"name": "Cost of Delay",
|
|
15013
|
+
"version": "1.0.0",
|
|
15014
|
+
"description": "Quantify the economic cost of not shipping a feature to drive priority decisions. Combines urgency with value.",
|
|
15015
|
+
"category": "prioritization",
|
|
15016
|
+
"origin": {
|
|
15017
|
+
"type": "practitioner",
|
|
15018
|
+
"attribution": "Don Reinertsen",
|
|
15019
|
+
"description": "Formalised in The Principles of Product Development Flow (Celeritas Publishing). Foundational to lean product economics.",
|
|
15020
|
+
"year": 2009,
|
|
15021
|
+
"license": "public_domain"
|
|
15022
|
+
},
|
|
15023
|
+
"tags": [
|
|
15024
|
+
"prioritization",
|
|
15025
|
+
"table"
|
|
15026
|
+
],
|
|
15027
|
+
"slots": [
|
|
15028
|
+
{
|
|
15029
|
+
"label": "Items to evaluate",
|
|
15030
|
+
"entityTypeId": "feature",
|
|
15031
|
+
"description": "Features or initiatives being assessed"
|
|
15032
|
+
},
|
|
15033
|
+
{
|
|
15034
|
+
"label": "User-Business Value",
|
|
15035
|
+
"entityTypeId": "outcome",
|
|
15036
|
+
"description": "Revenue, retention, or strategic value"
|
|
15037
|
+
},
|
|
15038
|
+
{
|
|
15039
|
+
"label": "Time Criticality",
|
|
15040
|
+
"entityTypeId": "metric",
|
|
15041
|
+
"description": "How much value decays with delay"
|
|
15042
|
+
},
|
|
15043
|
+
{
|
|
15044
|
+
"label": "Risk Reduction",
|
|
15045
|
+
"entityTypeId": "risk",
|
|
15046
|
+
"description": "What risk does this mitigate?"
|
|
15047
|
+
}
|
|
15048
|
+
],
|
|
15049
|
+
"data": {
|
|
15050
|
+
"entity_types": [
|
|
15051
|
+
{
|
|
15052
|
+
"type": "feature",
|
|
15053
|
+
"role": "scored_item"
|
|
15054
|
+
},
|
|
15055
|
+
{
|
|
15056
|
+
"type": "metric",
|
|
15057
|
+
"role": "item"
|
|
15058
|
+
},
|
|
15059
|
+
{
|
|
15060
|
+
"type": "outcome",
|
|
15061
|
+
"role": "item"
|
|
15062
|
+
},
|
|
15063
|
+
{
|
|
15064
|
+
"type": "risk",
|
|
15065
|
+
"role": "item"
|
|
15066
|
+
}
|
|
15067
|
+
],
|
|
15068
|
+
"required_properties": {
|
|
15069
|
+
"feature": [
|
|
15070
|
+
{
|
|
15071
|
+
"property": "cost_of_delay",
|
|
15072
|
+
"type": "number",
|
|
15073
|
+
"required": true,
|
|
15074
|
+
"scope": "framework",
|
|
15075
|
+
"label": "Cost of Delay",
|
|
15076
|
+
"description": "Weekly revenue impact of not shipping"
|
|
15077
|
+
},
|
|
15078
|
+
{
|
|
15079
|
+
"property": "job_size",
|
|
15080
|
+
"type": "number",
|
|
15081
|
+
"required": true,
|
|
15082
|
+
"scope": "framework",
|
|
15083
|
+
"label": "Job Size",
|
|
15084
|
+
"description": "Weeks of development effort"
|
|
15085
|
+
}
|
|
15086
|
+
]
|
|
15087
|
+
},
|
|
15088
|
+
"computed_properties": [
|
|
15089
|
+
{
|
|
15090
|
+
"property": "wsjf_score",
|
|
15091
|
+
"expression": "cost_of_delay / job_size",
|
|
15092
|
+
"entity_type": "feature",
|
|
15093
|
+
"label": "WSJF Score",
|
|
15094
|
+
"format": "number"
|
|
15095
|
+
}
|
|
15096
|
+
]
|
|
15097
|
+
},
|
|
15098
|
+
"structure": {
|
|
15099
|
+
"pattern": "table"
|
|
15100
|
+
},
|
|
15101
|
+
"presentation": {
|
|
15102
|
+
"layout": {
|
|
15103
|
+
"type": "table",
|
|
15104
|
+
"columns": [
|
|
15105
|
+
{
|
|
15106
|
+
"property": "title",
|
|
15107
|
+
"label": "Items to evaluate",
|
|
15108
|
+
"sortable": true
|
|
15109
|
+
},
|
|
15110
|
+
{
|
|
15111
|
+
"property": "cost_of_delay",
|
|
15112
|
+
"label": "User-Business Value",
|
|
15113
|
+
"sortable": true
|
|
15114
|
+
},
|
|
15115
|
+
{
|
|
15116
|
+
"property": "job_size",
|
|
15117
|
+
"label": "Job Size",
|
|
15118
|
+
"sortable": true
|
|
15119
|
+
},
|
|
15120
|
+
{
|
|
15121
|
+
"property": "wsjf_score",
|
|
15122
|
+
"label": "CoD Score",
|
|
15123
|
+
"sortable": true
|
|
15124
|
+
}
|
|
15125
|
+
]
|
|
15126
|
+
},
|
|
15127
|
+
"sort_by": {
|
|
15128
|
+
"property": "title",
|
|
15129
|
+
"direction": "asc"
|
|
15130
|
+
},
|
|
15131
|
+
"colour_by": "type",
|
|
15132
|
+
"card_fields": [
|
|
15133
|
+
"title",
|
|
15134
|
+
"description",
|
|
15135
|
+
"status"
|
|
15136
|
+
]
|
|
15137
|
+
},
|
|
15138
|
+
"education": {
|
|
15139
|
+
"purpose": "Quantify the economic impact of not delivering a feature by a given date, making urgency visible and enabling time-sensitive prioritisation.",
|
|
15140
|
+
"core_question": "How much value are we losing every week this feature is not in production, and does that urgency justify fast-tracking it?",
|
|
15141
|
+
"when_to_use": [
|
|
15142
|
+
"You have more ideas or features than capacity to build them",
|
|
15143
|
+
"Stakeholders disagree on what to build next",
|
|
15144
|
+
"You need a transparent, defensible prioritisation process"
|
|
15145
|
+
],
|
|
15146
|
+
"when_not_to_use": [
|
|
15147
|
+
"You have a single obvious next step with no contention",
|
|
15148
|
+
"The backlog is small enough to sequence intuitively"
|
|
15149
|
+
]
|
|
15150
|
+
}
|
|
15151
|
+
},
|
|
15152
|
+
{
|
|
15153
|
+
"id": "five-whys",
|
|
15154
|
+
"approach_ids": [
|
|
15155
|
+
"reflect",
|
|
15156
|
+
"inspect"
|
|
15157
|
+
],
|
|
15158
|
+
"name": "Five Whys",
|
|
15159
|
+
"version": "1.0.0",
|
|
15160
|
+
"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.',
|
|
15161
|
+
"category": "team_process",
|
|
15162
|
+
"origin": {
|
|
15163
|
+
"type": "practitioner",
|
|
15164
|
+
"attribution": "Sakichi Toyoda / Toyota Production System",
|
|
15165
|
+
"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.",
|
|
15166
|
+
"year": 1930,
|
|
15167
|
+
"license": "public_domain"
|
|
15168
|
+
},
|
|
15169
|
+
"tags": [
|
|
15170
|
+
"team_process",
|
|
15171
|
+
"reflection",
|
|
15172
|
+
"root_cause",
|
|
15173
|
+
"tree"
|
|
15174
|
+
],
|
|
15175
|
+
"slots": [
|
|
15176
|
+
{
|
|
15177
|
+
"label": "Symptom",
|
|
15178
|
+
"entityTypeId": "need",
|
|
15179
|
+
"description": "The observed problem the analysis starts from."
|
|
15180
|
+
},
|
|
15181
|
+
{
|
|
15182
|
+
"label": "Why chain",
|
|
15183
|
+
"entityTypeId": "insight",
|
|
15184
|
+
"description": 'Each "why?" answer along the chain, typically five iterations deep.'
|
|
15185
|
+
},
|
|
15186
|
+
{
|
|
15187
|
+
"label": "Root cause",
|
|
15188
|
+
"entityTypeId": "insight",
|
|
15189
|
+
"description": "The terminal answer at the bottom of the chain: the underlying cause to address."
|
|
15190
|
+
}
|
|
15191
|
+
],
|
|
15192
|
+
"data": {
|
|
15193
|
+
"entity_types": [
|
|
15194
|
+
{
|
|
15195
|
+
"type": "need",
|
|
15196
|
+
"role": "root"
|
|
15197
|
+
},
|
|
15198
|
+
{
|
|
15199
|
+
"type": "insight",
|
|
15200
|
+
"role": "branch"
|
|
15201
|
+
}
|
|
15202
|
+
],
|
|
15203
|
+
"required_properties": {}
|
|
15204
|
+
},
|
|
15205
|
+
"structure": {
|
|
15206
|
+
"pattern": "tree"
|
|
15207
|
+
},
|
|
15208
|
+
"presentation": {
|
|
15209
|
+
"layout": {
|
|
15210
|
+
"type": "tree",
|
|
15211
|
+
"direction": "TB"
|
|
15212
|
+
},
|
|
15213
|
+
"sort_by": {
|
|
15214
|
+
"property": "title",
|
|
15215
|
+
"direction": "asc"
|
|
15216
|
+
},
|
|
15217
|
+
"card_fields": [
|
|
15218
|
+
"title",
|
|
15219
|
+
"description"
|
|
15220
|
+
]
|
|
15221
|
+
},
|
|
15222
|
+
"education": {
|
|
15223
|
+
"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.',
|
|
15224
|
+
"core_question": "Why is this happening, and why is THAT happening, until we reach a cause we can act on?",
|
|
15225
|
+
"when_to_use": [
|
|
15226
|
+
"A problem keeps recurring after surface fixes",
|
|
15227
|
+
"Post-incident review where the obvious cause feels too obvious",
|
|
15228
|
+
"Designing a fix and you want to confirm you understand the actual driver"
|
|
15229
|
+
],
|
|
15230
|
+
"when_not_to_use": [
|
|
15231
|
+
"The problem has multiple independent root causes (use a fishbone or richer RCA tool)",
|
|
15232
|
+
"You need quantitative attribution rather than a single-thread narrative",
|
|
15233
|
+
'Five linear "whys" oversimplify a systems problem with feedback loops'
|
|
15234
|
+
]
|
|
15235
|
+
}
|
|
15236
|
+
},
|
|
15237
|
+
{
|
|
15238
|
+
"id": "pre-mortem",
|
|
15239
|
+
"approach_ids": [
|
|
15240
|
+
"reflect"
|
|
15241
|
+
],
|
|
15242
|
+
"name": "Pre-mortem",
|
|
15243
|
+
"version": "1.0.0",
|
|
15244
|
+
"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.",
|
|
15245
|
+
"category": "team_process",
|
|
15246
|
+
"origin": {
|
|
15247
|
+
"type": "practitioner",
|
|
15248
|
+
"attribution": "Gary Klein",
|
|
15249
|
+
"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.",
|
|
15250
|
+
"url": "https://hbr.org/2007/09/performing-a-project-premortem",
|
|
15251
|
+
"year": 2007,
|
|
15252
|
+
"license": "published_methodology"
|
|
15253
|
+
},
|
|
15254
|
+
"tags": [
|
|
15255
|
+
"team_process",
|
|
15256
|
+
"reflection",
|
|
15257
|
+
"risk",
|
|
15258
|
+
"collection"
|
|
15259
|
+
],
|
|
15260
|
+
"slots": [
|
|
15261
|
+
{
|
|
15262
|
+
"label": "Imagined failures",
|
|
15263
|
+
"entityTypeId": "risk",
|
|
15264
|
+
"description": "Plausible failure modes named as if they had already occurred."
|
|
15265
|
+
},
|
|
15266
|
+
{
|
|
15267
|
+
"label": "Causes",
|
|
15268
|
+
"entityTypeId": "insight",
|
|
15269
|
+
"description": "For each imagined failure, the contributing causes the team can foresee."
|
|
15270
|
+
},
|
|
15271
|
+
{
|
|
15272
|
+
"label": "Mitigations",
|
|
15273
|
+
"entityTypeId": "initiative",
|
|
15274
|
+
"description": "Mitigation actions the team will take before failure can occur."
|
|
15275
|
+
}
|
|
15276
|
+
],
|
|
15277
|
+
"data": {
|
|
15278
|
+
"entity_types": [
|
|
15279
|
+
{
|
|
15280
|
+
"type": "risk",
|
|
15281
|
+
"role": "bucket"
|
|
15282
|
+
},
|
|
15283
|
+
{
|
|
15284
|
+
"type": "insight",
|
|
15285
|
+
"role": "bucket"
|
|
15286
|
+
},
|
|
15287
|
+
{
|
|
15288
|
+
"type": "initiative",
|
|
15289
|
+
"role": "bucket"
|
|
15290
|
+
}
|
|
15291
|
+
],
|
|
15292
|
+
"required_properties": {}
|
|
15293
|
+
},
|
|
15294
|
+
"structure": {
|
|
15295
|
+
"pattern": "collection"
|
|
15296
|
+
},
|
|
15297
|
+
"presentation": {
|
|
15298
|
+
"layout": {
|
|
15299
|
+
"type": "grid",
|
|
15300
|
+
"groupBy": "type"
|
|
15301
|
+
},
|
|
15302
|
+
"sort_by": {
|
|
15303
|
+
"property": "title",
|
|
15304
|
+
"direction": "asc"
|
|
15305
|
+
},
|
|
15306
|
+
"colour_by": "group",
|
|
15307
|
+
"card_fields": [
|
|
15308
|
+
"title",
|
|
15309
|
+
"description"
|
|
15310
|
+
]
|
|
15311
|
+
},
|
|
15312
|
+
"education": {
|
|
15313
|
+
"purpose": "Surface project risks early by inverting hindsight: imagine the project has already failed and ask why, while there is still time to mitigate.",
|
|
15314
|
+
"core_question": "It is six months from now and the project has failed catastrophically. What happened, and why?",
|
|
15315
|
+
"when_to_use": [
|
|
15316
|
+
"Kicking off a project with significant downside or irreversible commitment",
|
|
15317
|
+
"A plan looks too clean and the team senses unspoken concerns",
|
|
15318
|
+
"Stakeholders disagree on risk; the exercise externalises and ranks them"
|
|
15319
|
+
],
|
|
15320
|
+
"when_not_to_use": [
|
|
15321
|
+
"The work is small, reversible, and cheap to course-correct",
|
|
15322
|
+
"The team is in execution mode and reflective ceremonies will derail momentum",
|
|
15323
|
+
"Risk surfacing has become performative: the team names risks but never mitigates them"
|
|
15324
|
+
]
|
|
15325
|
+
}
|
|
15326
|
+
},
|
|
15327
|
+
{
|
|
15328
|
+
"id": "red-team",
|
|
15329
|
+
"approach_ids": [
|
|
15330
|
+
"reflect",
|
|
15331
|
+
"inspect"
|
|
15332
|
+
],
|
|
15333
|
+
"name": "Red Team",
|
|
15334
|
+
"version": "1.0.0",
|
|
15335
|
+
"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.",
|
|
15336
|
+
"category": "team_process",
|
|
15337
|
+
"origin": {
|
|
15338
|
+
"type": "practitioner",
|
|
15339
|
+
"attribution": "US Department of Defense (Cold War era); broadened by security and intelligence practice",
|
|
15340
|
+
"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.`,
|
|
15341
|
+
"year": 1960,
|
|
15342
|
+
"license": "public_domain"
|
|
15343
|
+
},
|
|
15344
|
+
"tags": [
|
|
15345
|
+
"team_process",
|
|
15346
|
+
"reflection",
|
|
15347
|
+
"adversarial",
|
|
15348
|
+
"collection"
|
|
15349
|
+
],
|
|
15350
|
+
"slots": [
|
|
15351
|
+
{
|
|
15352
|
+
"label": "Target",
|
|
15353
|
+
"entityTypeId": "initiative",
|
|
15354
|
+
"description": "The plan, design, or proposal under adversarial review."
|
|
15355
|
+
},
|
|
15356
|
+
{
|
|
15357
|
+
"label": "Attack vectors",
|
|
15358
|
+
"entityTypeId": "risk",
|
|
15359
|
+
"description": "The angles the red team uses to probe weaknesses."
|
|
15360
|
+
},
|
|
15361
|
+
{
|
|
15362
|
+
"label": "Findings",
|
|
15363
|
+
"entityTypeId": "insight",
|
|
15364
|
+
"description": "Weaknesses, blind spots, or unstated assumptions surfaced by the review."
|
|
15365
|
+
}
|
|
15366
|
+
],
|
|
15367
|
+
"data": {
|
|
15368
|
+
"entity_types": [
|
|
15369
|
+
{
|
|
15370
|
+
"type": "initiative",
|
|
15371
|
+
"role": "root"
|
|
15372
|
+
},
|
|
15373
|
+
{
|
|
15374
|
+
"type": "risk",
|
|
15375
|
+
"role": "bucket"
|
|
15376
|
+
},
|
|
15377
|
+
{
|
|
15378
|
+
"type": "insight",
|
|
15379
|
+
"role": "bucket"
|
|
15380
|
+
}
|
|
15381
|
+
],
|
|
15382
|
+
"required_properties": {}
|
|
15383
|
+
},
|
|
15384
|
+
"structure": {
|
|
15385
|
+
"pattern": "collection"
|
|
15386
|
+
},
|
|
15387
|
+
"presentation": {
|
|
15388
|
+
"layout": {
|
|
15389
|
+
"type": "grid",
|
|
15390
|
+
"groupBy": "type"
|
|
15391
|
+
},
|
|
15392
|
+
"sort_by": {
|
|
15393
|
+
"property": "title",
|
|
15394
|
+
"direction": "asc"
|
|
15395
|
+
},
|
|
15396
|
+
"colour_by": "group",
|
|
15397
|
+
"card_fields": [
|
|
15398
|
+
"title",
|
|
15399
|
+
"description"
|
|
15400
|
+
]
|
|
15401
|
+
},
|
|
15402
|
+
"education": {
|
|
15403
|
+
"purpose": "Stress-test a plan against an explicit adversary by assigning reviewers to attack rather than agree, so weaknesses surface before reality finds them.",
|
|
15404
|
+
"core_question": "If a competent adversary wanted this to fail, where would they push first, and would we hold?",
|
|
15405
|
+
"when_to_use": [
|
|
15406
|
+
"A high-stakes decision, launch, or security posture needs hardening",
|
|
15407
|
+
"Inside-out thinking is dominant and dissent has gone quiet",
|
|
15408
|
+
"Risk register is suspiciously short for the size of the bet"
|
|
15409
|
+
],
|
|
15410
|
+
"when_not_to_use": [
|
|
15411
|
+
"Early-stage exploration where adversarial framing would crush a fragile idea prematurely",
|
|
15412
|
+
"Team trust is too low: red-teaming will read as personal attack rather than role-play",
|
|
15413
|
+
"The work is small enough that a lightweight devil's-advocate pass is sufficient"
|
|
15414
|
+
]
|
|
15415
|
+
}
|
|
15416
|
+
},
|
|
15417
|
+
{
|
|
15418
|
+
"id": "devils-advocate",
|
|
15419
|
+
"approach_ids": [
|
|
15420
|
+
"reflect"
|
|
15421
|
+
],
|
|
15422
|
+
"name": "Devil's Advocate",
|
|
15423
|
+
"version": "1.0.0",
|
|
15424
|
+
"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.",
|
|
15425
|
+
"category": "team_process",
|
|
15426
|
+
"origin": {
|
|
15427
|
+
"type": "practitioner",
|
|
15428
|
+
"attribution": "Roman Catholic Church (advocatus diaboli); broadened by decision-quality practice",
|
|
15429
|
+
"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.",
|
|
15430
|
+
"year": 1587,
|
|
15431
|
+
"license": "public_domain"
|
|
15432
|
+
},
|
|
15433
|
+
"tags": [
|
|
15434
|
+
"team_process",
|
|
15435
|
+
"reflection",
|
|
15436
|
+
"decision_quality",
|
|
15437
|
+
"collection"
|
|
15438
|
+
],
|
|
15439
|
+
"slots": [
|
|
15440
|
+
{
|
|
15441
|
+
"label": "Proposal",
|
|
15442
|
+
"entityTypeId": "initiative",
|
|
15443
|
+
"description": "The plan or recommendation under consideration."
|
|
15444
|
+
},
|
|
15445
|
+
{
|
|
15446
|
+
"label": "Opposing arguments",
|
|
15447
|
+
"entityTypeId": "insight",
|
|
15448
|
+
"description": "The case against the proposal, voiced by the assigned contrarian regardless of personal view."
|
|
15449
|
+
},
|
|
15450
|
+
{
|
|
15451
|
+
"label": "Counter-evidence",
|
|
15452
|
+
"entityTypeId": "evidence",
|
|
15453
|
+
"description": "Data points the contrarian raises that the proposal does not yet account for."
|
|
15454
|
+
}
|
|
15455
|
+
],
|
|
15456
|
+
"data": {
|
|
15457
|
+
"entity_types": [
|
|
15458
|
+
{
|
|
15459
|
+
"type": "initiative",
|
|
15460
|
+
"role": "root"
|
|
15461
|
+
},
|
|
15462
|
+
{
|
|
15463
|
+
"type": "insight",
|
|
15464
|
+
"role": "bucket"
|
|
15465
|
+
},
|
|
15466
|
+
{
|
|
15467
|
+
"type": "evidence",
|
|
15468
|
+
"role": "bucket"
|
|
15469
|
+
}
|
|
15470
|
+
],
|
|
15471
|
+
"required_properties": {}
|
|
15472
|
+
},
|
|
15473
|
+
"structure": {
|
|
15474
|
+
"pattern": "collection"
|
|
15475
|
+
},
|
|
15476
|
+
"presentation": {
|
|
15477
|
+
"layout": {
|
|
15478
|
+
"type": "grid",
|
|
15479
|
+
"groupBy": "type"
|
|
15480
|
+
},
|
|
15481
|
+
"sort_by": {
|
|
15482
|
+
"property": "title",
|
|
15483
|
+
"direction": "asc"
|
|
15484
|
+
},
|
|
15485
|
+
"colour_by": "group",
|
|
15486
|
+
"card_fields": [
|
|
15487
|
+
"title",
|
|
15488
|
+
"description"
|
|
15489
|
+
]
|
|
15490
|
+
},
|
|
15491
|
+
"education": {
|
|
15492
|
+
"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.",
|
|
15493
|
+
"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?",
|
|
15494
|
+
"when_to_use": [
|
|
15495
|
+
"A decision is heading toward consensus and you suspect groupthink",
|
|
15496
|
+
"Stakes are high and the team has not heard a serious counter-argument",
|
|
15497
|
+
"Cultural norms make raw dissent costly; assigning the role lowers the social cost"
|
|
15498
|
+
],
|
|
15499
|
+
"when_not_to_use": [
|
|
15500
|
+
"Genuine disagreement already exists in the room (let it surface; do not theatricalise it)",
|
|
15501
|
+
"The decision is small enough that the ceremony costs more than the insight returned",
|
|
15502
|
+
"The assigned contrarian will be punished socially for the role; set the norms first or skip"
|
|
15503
|
+
]
|
|
15504
|
+
}
|
|
15505
|
+
},
|
|
15506
|
+
{
|
|
15507
|
+
"id": "second-order-thinking",
|
|
15508
|
+
"approach_ids": [
|
|
15509
|
+
"reflect"
|
|
15510
|
+
],
|
|
15511
|
+
"name": "Second-order Thinking",
|
|
15512
|
+
"version": "1.0.0",
|
|
15513
|
+
"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.',
|
|
15514
|
+
"category": "team_process",
|
|
15515
|
+
"origin": {
|
|
15516
|
+
"type": "practitioner",
|
|
15517
|
+
"attribution": "Howard Marks / Charlie Munger",
|
|
15518
|
+
"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.`,
|
|
15519
|
+
"url": "https://www.oaktreecapital.com/insights/memo/dare-to-be-great-ii",
|
|
15520
|
+
"year": 2011,
|
|
15521
|
+
"license": "published_methodology"
|
|
15522
|
+
},
|
|
15523
|
+
"tags": [
|
|
15524
|
+
"team_process",
|
|
15525
|
+
"reflection",
|
|
15526
|
+
"consequences",
|
|
15527
|
+
"tree"
|
|
15528
|
+
],
|
|
15529
|
+
"slots": [
|
|
15530
|
+
{
|
|
15531
|
+
"label": "First-order move",
|
|
15532
|
+
"entityTypeId": "decision",
|
|
15533
|
+
"description": "The decision or move under consideration."
|
|
15534
|
+
},
|
|
15535
|
+
{
|
|
15536
|
+
"label": "Second-order consequences",
|
|
15537
|
+
"entityTypeId": "insight",
|
|
15538
|
+
"description": "Downstream effects that follow from the first-order move."
|
|
15539
|
+
},
|
|
15540
|
+
{
|
|
15541
|
+
"label": "Higher-order consequences",
|
|
15542
|
+
"entityTypeId": "insight",
|
|
15543
|
+
"description": "Third-, fourth-, fifth-order ripples: second-order consequences of the second-order consequences."
|
|
15544
|
+
}
|
|
15545
|
+
],
|
|
15546
|
+
"data": {
|
|
15547
|
+
"entity_types": [
|
|
15548
|
+
{
|
|
15549
|
+
"type": "decision",
|
|
15550
|
+
"role": "root"
|
|
15551
|
+
},
|
|
15552
|
+
{
|
|
15553
|
+
"type": "insight",
|
|
15554
|
+
"role": "branch"
|
|
15555
|
+
}
|
|
15556
|
+
],
|
|
15557
|
+
"required_properties": {}
|
|
15558
|
+
},
|
|
15559
|
+
"structure": {
|
|
15560
|
+
"pattern": "tree"
|
|
15561
|
+
},
|
|
15562
|
+
"presentation": {
|
|
15563
|
+
"layout": {
|
|
15564
|
+
"type": "tree",
|
|
15565
|
+
"direction": "TB"
|
|
15566
|
+
},
|
|
15567
|
+
"sort_by": {
|
|
15568
|
+
"property": "title",
|
|
15569
|
+
"direction": "asc"
|
|
15570
|
+
},
|
|
15571
|
+
"card_fields": [
|
|
15572
|
+
"title",
|
|
15573
|
+
"description"
|
|
15574
|
+
]
|
|
15575
|
+
},
|
|
15576
|
+
"education": {
|
|
15577
|
+
"purpose": 'Resist first-order reasoning by chaining "and then what?" until non-obvious downstream consequences come into view.',
|
|
15578
|
+
"core_question": "If we make this move and it works, what does the world look like next, and is that the world we want?",
|
|
15579
|
+
"when_to_use": [
|
|
15580
|
+
"A decision has feedback loops, market reactions, or behavioural ripples",
|
|
15581
|
+
"The first-order case is compelling, which is exactly when downstream effects bite",
|
|
15582
|
+
"Considering an irreversible or large-scale commitment"
|
|
15583
|
+
],
|
|
15584
|
+
"when_not_to_use": [
|
|
15585
|
+
"Routine, reversible, low-blast-radius decisions where deliberation costs more than mistakes",
|
|
15586
|
+
"Higher-order branches diverge into pure speculation with no anchor in evidence",
|
|
15587
|
+
"Time pressure makes a deeper trace expensive and the first-order call is good enough"
|
|
15588
|
+
]
|
|
15589
|
+
}
|
|
15590
|
+
}
|
|
15591
|
+
];
|
|
15592
|
+
var UPG_FRAMEWORKS_BY_ID = Object.fromEntries(
|
|
15593
|
+
UPG_FRAMEWORKS.map((fw) => [fw.id, fw])
|
|
15594
|
+
);
|
|
15595
|
+
var UPG_FRAMEWORKS_BY_CATEGORY = {};
|
|
15596
|
+
for (const fw of UPG_FRAMEWORKS) {
|
|
15597
|
+
if (!UPG_FRAMEWORKS_BY_CATEGORY[fw.category]) UPG_FRAMEWORKS_BY_CATEGORY[fw.category] = [];
|
|
15598
|
+
UPG_FRAMEWORKS_BY_CATEGORY[fw.category].push(fw);
|
|
15599
|
+
}
|
|
15600
|
+
var PRIORITY_LABELS = [
|
|
15601
|
+
// ── need (CONSOLIDATED: replaces pain_point + user_need) ─────────────────────
|
|
15602
|
+
{
|
|
15603
|
+
id: "need",
|
|
15604
|
+
canonical_label: "Need",
|
|
15605
|
+
alt_labels: [
|
|
15606
|
+
"pain point",
|
|
15607
|
+
"pain",
|
|
15608
|
+
"user need",
|
|
15609
|
+
"customer need",
|
|
15610
|
+
"problem",
|
|
15611
|
+
"struggle",
|
|
15612
|
+
"customer pain",
|
|
15613
|
+
"frustration",
|
|
15614
|
+
"gap",
|
|
15615
|
+
"unmet need",
|
|
15616
|
+
"user problem"
|
|
15617
|
+
],
|
|
15618
|
+
framework_labels: {
|
|
15619
|
+
lean_canvas: "Problem",
|
|
15620
|
+
design_thinking: "Pain Point",
|
|
15621
|
+
ost: "Opportunity (need)",
|
|
15622
|
+
jtbd: "Struggle",
|
|
15623
|
+
vpc: "Customer Pain"
|
|
15624
|
+
},
|
|
15625
|
+
designations: {
|
|
15626
|
+
pain: "Pain Point",
|
|
15627
|
+
gap: "Need",
|
|
15628
|
+
desire: "Desire",
|
|
15629
|
+
constraint: "Constraint"
|
|
15630
|
+
}
|
|
15631
|
+
},
|
|
15632
|
+
// ── opportunity ──────────────────────────────────────────────────────────────
|
|
15633
|
+
{
|
|
15634
|
+
id: "opportunity",
|
|
15635
|
+
canonical_label: "Opportunity",
|
|
15636
|
+
alt_labels: ["product opportunity", "market opportunity", "user opportunity"],
|
|
15637
|
+
framework_labels: {
|
|
15638
|
+
ost: "Opportunity"
|
|
15639
|
+
}
|
|
15640
|
+
},
|
|
15641
|
+
// ── solution ─────────────────────────────────────────────────────────────────
|
|
15642
|
+
{
|
|
15643
|
+
id: "solution",
|
|
15644
|
+
canonical_label: "Solution",
|
|
15645
|
+
alt_labels: ["proposed solution", "solution idea", "concept", "approach"],
|
|
15646
|
+
framework_labels: {
|
|
15647
|
+
ost: "Solution",
|
|
15648
|
+
design_thinking: "Solution",
|
|
15649
|
+
lean_canvas: "Solution",
|
|
15650
|
+
rice: "Scored Solution"
|
|
15651
|
+
}
|
|
15652
|
+
},
|
|
15653
|
+
// ── experiment (CONSOLIDATED: absorbs ab_test, growth_experiment, pricing_experiment) ──
|
|
15654
|
+
{
|
|
15655
|
+
id: "experiment",
|
|
15656
|
+
canonical_label: "Experiment",
|
|
15657
|
+
alt_labels: [
|
|
15658
|
+
"test",
|
|
15659
|
+
"validation",
|
|
15660
|
+
"ab test",
|
|
15661
|
+
"a/b test",
|
|
15662
|
+
"split test",
|
|
15663
|
+
"growth experiment",
|
|
15664
|
+
"pricing experiment",
|
|
15665
|
+
"usability test",
|
|
15666
|
+
"discovery experiment"
|
|
15667
|
+
],
|
|
15668
|
+
framework_labels: {
|
|
15669
|
+
ost: "Experiment",
|
|
15670
|
+
design_thinking: "Test",
|
|
15671
|
+
lean_startup: "Experiment"
|
|
15672
|
+
},
|
|
15673
|
+
designations: {
|
|
15674
|
+
discovery: "Discovery Experiment",
|
|
15675
|
+
ab_test: "A/B Test",
|
|
15676
|
+
growth: "Growth Experiment",
|
|
15677
|
+
pricing: "Pricing Experiment",
|
|
15678
|
+
usability: "Usability Test"
|
|
15679
|
+
}
|
|
15680
|
+
},
|
|
15681
|
+
// ── hypothesis ───────────────────────────────────────────────────────────────
|
|
15682
|
+
{
|
|
15683
|
+
id: "hypothesis",
|
|
15684
|
+
canonical_label: "Hypothesis",
|
|
15685
|
+
alt_labels: ["bet", "testable assumption", "leap of faith"],
|
|
15686
|
+
framework_labels: {
|
|
15687
|
+
lean_startup: "Hypothesis",
|
|
15688
|
+
running_lean: "Riskiest Assumption",
|
|
15689
|
+
lean_canvas: "Riskiest Assumption"
|
|
14770
15690
|
}
|
|
14771
15691
|
},
|
|
14772
15692
|
// ── metric (CONSOLIDATED: absorbs kpi, north_star_metric, input_metric, metric_definition) ──
|
|
@@ -15606,17 +16526,6 @@ function seqStep(order, phase, entity_types, prompt_hint, options) {
|
|
|
15606
16526
|
...options?.next_sequence_on_gap ? { next_sequence_on_gap: options.next_sequence_on_gap } : {}
|
|
15607
16527
|
};
|
|
15608
16528
|
}
|
|
15609
|
-
function domainGuideStep(domain_id, phase, name, prompt_hint, options) {
|
|
15610
|
-
return {
|
|
15611
|
-
kind: "domain_guide",
|
|
15612
|
-
order: 1,
|
|
15613
|
-
phase,
|
|
15614
|
-
name,
|
|
15615
|
-
prompt_hint,
|
|
15616
|
-
domain_id,
|
|
15617
|
-
...options?.next_sequence_on_gap ? { next_sequence_on_gap: options.next_sequence_on_gap } : {}
|
|
15618
|
-
};
|
|
15619
|
-
}
|
|
15620
16529
|
var STRATEGY_OUTCOMES_PLAYBOOK = {
|
|
15621
16530
|
id: "playbook:strategy-outcomes",
|
|
15622
16531
|
name: "Strategy & Outcomes",
|
|
@@ -15625,7 +16534,10 @@ var STRATEGY_OUTCOMES_PLAYBOOK = {
|
|
|
15625
16534
|
region: "strategy_outcomes",
|
|
15626
16535
|
is_canonical: true,
|
|
15627
16536
|
related_framework_ids: ["okr-framework", "three-horizons", "north-star-metric", "metrics-tree", "wardley-map"],
|
|
15628
|
-
|
|
16537
|
+
// DT-PB-3: anchor is `outcome`, not `objective`. The creation_sequence
|
|
16538
|
+
// creates outcome (step 3) before objective (step 4), and outcome is the
|
|
16539
|
+
// strategy region's gravitational centre (objectives translate outcomes).
|
|
16540
|
+
target_anchor_entity: "outcome",
|
|
15629
16541
|
creation_sequence: [
|
|
15630
16542
|
seqStep(
|
|
15631
16543
|
1,
|
|
@@ -15668,7 +16580,7 @@ var STRATEGY_OUTCOMES_PLAYBOOK = {
|
|
|
15668
16580
|
"Assumptions & Decisions",
|
|
15669
16581
|
["assumption", "decision"],
|
|
15670
16582
|
"Capture the bets you are making (assumptions) and the choices you have ratified (decisions). These guard the work against silent drift.",
|
|
15671
|
-
{ next_sequence_on_gap: "playbook:discovery-validation
|
|
16583
|
+
{ next_sequence_on_gap: "playbook:discovery-research-validation" }
|
|
15672
16584
|
)
|
|
15673
16585
|
]
|
|
15674
16586
|
};
|
|
@@ -15781,25 +16693,12 @@ var DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK = {
|
|
|
15781
16693
|
seqStep(
|
|
15782
16694
|
8,
|
|
15783
16695
|
"Test",
|
|
15784
|
-
|
|
15785
|
-
|
|
15786
|
-
|
|
15787
|
-
|
|
15788
|
-
|
|
15789
|
-
|
|
15790
|
-
id: "playbook:discovery-validation-hypothesis-cycle",
|
|
15791
|
-
name: "Hypothesis Validation",
|
|
15792
|
-
version: "0.1.0",
|
|
15793
|
-
description: "Tight hypothesis \u2192 experiment \u2192 evidence \u2192 learning loop. Run after research has surfaced an opportunity.",
|
|
15794
|
-
region: "discovery_research_validation",
|
|
15795
|
-
framework_id: "build-measure-learn",
|
|
15796
|
-
target_anchor_entity: "hypothesis",
|
|
15797
|
-
creation_sequence: [
|
|
15798
|
-
domainGuideStep(
|
|
15799
|
-
"validation",
|
|
15800
|
-
"Validation",
|
|
15801
|
-
"Frame & test",
|
|
15802
|
-
"Run the validation creation sequence: hypothesis, experiment, evidence, learning."
|
|
16696
|
+
// DT-PB-1: was `experiment` — which resolves to NO canonical edge with
|
|
16697
|
+
// hypothesis or test_plan, forcing an orphan. `experiment_run` is the
|
|
16698
|
+
// hypothesis-linked test unit (experiment_run_validates_hypothesis,
|
|
16699
|
+
// test_plan_ran_as_experiment_run, experiment_run_yields_evidence).
|
|
16700
|
+
["experiment_run", "test_plan", "evidence"],
|
|
16701
|
+
"Validate with targeted experiment runs. Close the loop between research and action."
|
|
15803
16702
|
)
|
|
15804
16703
|
]
|
|
15805
16704
|
};
|
|
@@ -15846,8 +16745,8 @@ var MARKET_COMPETITIVE_PLAYBOOK = {
|
|
|
15846
16745
|
seqStep(
|
|
15847
16746
|
6,
|
|
15848
16747
|
"Moves",
|
|
15849
|
-
["
|
|
15850
|
-
"Look where competitors are weak and trends are strong. That intersection is where your moves live
|
|
16748
|
+
["competitive_battle_card"],
|
|
16749
|
+
"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.)"
|
|
15851
16750
|
)
|
|
15852
16751
|
]
|
|
15853
16752
|
};
|
|
@@ -15911,54 +16810,6 @@ var EXPERIENCE_DESIGN_BRAND_PLAYBOOK = {
|
|
|
15911
16810
|
)
|
|
15912
16811
|
]
|
|
15913
16812
|
};
|
|
15914
|
-
var EXPERIENCE_UX_DOMAIN_ONLY_PLAYBOOK = {
|
|
15915
|
-
id: "playbook:experience-ux-domain-only",
|
|
15916
|
-
name: "UX Design (compact)",
|
|
15917
|
-
version: "0.1.0",
|
|
15918
|
-
description: "Compact UX-only path. Quick when research and design system are managed separately.",
|
|
15919
|
-
region: "experience_design_brand",
|
|
15920
|
-
target_anchor_entity: "user_journey",
|
|
15921
|
-
creation_sequence: [
|
|
15922
|
-
domainGuideStep(
|
|
15923
|
-
"ux_design",
|
|
15924
|
-
"UX",
|
|
15925
|
-
"Journey to screen",
|
|
15926
|
-
"Run the ux_design creation sequence: journey, steps, screens, flows, wireframes, prototypes."
|
|
15927
|
-
)
|
|
15928
|
-
]
|
|
15929
|
-
};
|
|
15930
|
-
var EXPERIENCE_DESIGN_SYSTEM_PLAYBOOK = {
|
|
15931
|
-
id: "playbook:experience-design-system",
|
|
15932
|
-
name: "Design System",
|
|
15933
|
-
version: "0.1.0",
|
|
15934
|
-
description: "Codify the shared design language: tokens, components, patterns, guidelines.",
|
|
15935
|
-
region: "experience_design_brand",
|
|
15936
|
-
creation_sequence: [
|
|
15937
|
-
domainGuideStep(
|
|
15938
|
-
"design_system",
|
|
15939
|
-
"Design System",
|
|
15940
|
-
"System foundations",
|
|
15941
|
-
"Run the design_system creation sequence: tokens, components, patterns, guidelines.",
|
|
15942
|
-
{ next_sequence_on_gap: "playbook:experience-ux-domain-only" }
|
|
15943
|
-
)
|
|
15944
|
-
]
|
|
15945
|
-
};
|
|
15946
|
-
var EXPERIENCE_CONTENT_PLAYBOOK = {
|
|
15947
|
-
id: "playbook:experience-content",
|
|
15948
|
-
name: "Content Strategy",
|
|
15949
|
-
version: "0.1.0",
|
|
15950
|
-
description: "Plan what to publish: strategy, themes, calendar, individual pieces tied to audience and channels.",
|
|
15951
|
-
region: "experience_design_brand",
|
|
15952
|
-
creation_sequence: [
|
|
15953
|
-
domainGuideStep(
|
|
15954
|
-
"content",
|
|
15955
|
-
"Content",
|
|
15956
|
-
"Content plan",
|
|
15957
|
-
"Run the content creation sequence: strategy, themes, calendar, pieces.",
|
|
15958
|
-
{ next_sequence_on_gap: "playbook:business-growth-funnel" }
|
|
15959
|
-
)
|
|
15960
|
-
]
|
|
15961
|
-
};
|
|
15962
16813
|
var PRODUCT_DELIVERY_PLAYBOOK = {
|
|
15963
16814
|
id: "playbook:product-delivery",
|
|
15964
16815
|
name: "Product Delivery",
|
|
@@ -16007,22 +16858,6 @@ var PRODUCT_DELIVERY_PLAYBOOK = {
|
|
|
16007
16858
|
)
|
|
16008
16859
|
]
|
|
16009
16860
|
};
|
|
16010
|
-
var PRODUCT_FEEDBACK_SYNTHESIS_PLAYBOOK = {
|
|
16011
|
-
id: "playbook:product-feedback-synthesis",
|
|
16012
|
-
name: "Feedback Synthesis",
|
|
16013
|
-
version: "0.1.0",
|
|
16014
|
-
description: "Capture and cluster qualitative signal: feedback items, themes, NPS, support tickets.",
|
|
16015
|
-
region: "product_delivery",
|
|
16016
|
-
creation_sequence: [
|
|
16017
|
-
domainGuideStep(
|
|
16018
|
-
"feedback",
|
|
16019
|
-
"Feedback",
|
|
16020
|
-
"Signal capture",
|
|
16021
|
-
"Run the feedback creation sequence: items, themes, NPS, support data.",
|
|
16022
|
-
{ next_sequence_on_gap: "playbook:discovery-validation-hypothesis-cycle" }
|
|
16023
|
-
)
|
|
16024
|
-
]
|
|
16025
|
-
};
|
|
16026
16861
|
var ENGINEERING_PLATFORM_PLAYBOOK = {
|
|
16027
16862
|
id: "playbook:engineering-platform",
|
|
16028
16863
|
name: "Engineering & Platform",
|
|
@@ -16083,21 +16918,6 @@ var ENGINEERING_PLATFORM_PLAYBOOK = {
|
|
|
16083
16918
|
)
|
|
16084
16919
|
]
|
|
16085
16920
|
};
|
|
16086
|
-
var ENGINEERING_ARCHITECTURE_ONLY_PLAYBOOK = {
|
|
16087
|
-
id: "playbook:engineering-architecture-only",
|
|
16088
|
-
name: "Architecture (compact)",
|
|
16089
|
-
version: "0.1.0",
|
|
16090
|
-
description: "Compact architecture-only path. Quick when build/deploy/security are managed separately.",
|
|
16091
|
-
region: "engineering_platform",
|
|
16092
|
-
creation_sequence: [
|
|
16093
|
-
domainGuideStep(
|
|
16094
|
-
"engineering",
|
|
16095
|
-
"Engineering",
|
|
16096
|
-
"System shape",
|
|
16097
|
-
"Run the engineering creation sequence: bounded contexts, services, data, decisions."
|
|
16098
|
-
)
|
|
16099
|
-
]
|
|
16100
|
-
};
|
|
16101
16921
|
var BUSINESS_GTM_GROWTH_PLAYBOOK = {
|
|
16102
16922
|
id: "playbook:business-gtm-growth",
|
|
16103
16923
|
name: "Business, GTM & Growth",
|
|
@@ -16152,70 +16972,6 @@ var BUSINESS_GTM_GROWTH_PLAYBOOK = {
|
|
|
16152
16972
|
)
|
|
16153
16973
|
]
|
|
16154
16974
|
};
|
|
16155
|
-
var BUSINESS_MODEL_BMC_PLAYBOOK = {
|
|
16156
|
-
id: "playbook:business-model-bmc",
|
|
16157
|
-
name: "Business Model (BMC)",
|
|
16158
|
-
version: "0.1.0",
|
|
16159
|
-
description: "Design the business model with Business Model Canvas: value props, customer segments, revenue streams, cost structure.",
|
|
16160
|
-
region: "business_gtm_growth",
|
|
16161
|
-
framework_id: "business-model-canvas",
|
|
16162
|
-
creation_sequence: [
|
|
16163
|
-
domainGuideStep(
|
|
16164
|
-
"business_model",
|
|
16165
|
-
"Business",
|
|
16166
|
-
"Model canvas",
|
|
16167
|
-
"Run the business_model creation sequence: value props, segments, revenue, costs.",
|
|
16168
|
-
{ next_sequence_on_gap: "playbook:business-pricing" }
|
|
16169
|
-
)
|
|
16170
|
-
]
|
|
16171
|
-
};
|
|
16172
|
-
var BUSINESS_PRICING_PLAYBOOK = {
|
|
16173
|
-
id: "playbook:business-pricing",
|
|
16174
|
-
name: "Pricing",
|
|
16175
|
-
version: "0.1.0",
|
|
16176
|
-
description: "Design the revenue engine: pricing strategy, tiers, trials, paywalls, discounts.",
|
|
16177
|
-
region: "business_gtm_growth",
|
|
16178
|
-
creation_sequence: [
|
|
16179
|
-
domainGuideStep(
|
|
16180
|
-
"pricing",
|
|
16181
|
-
"Revenue",
|
|
16182
|
-
"Pricing model",
|
|
16183
|
-
"Run the pricing creation sequence: strategy, tiers, discounts, trial, paywall."
|
|
16184
|
-
)
|
|
16185
|
-
]
|
|
16186
|
-
};
|
|
16187
|
-
var BUSINESS_GROWTH_FUNNEL_PLAYBOOK = {
|
|
16188
|
-
id: "playbook:business-growth-funnel",
|
|
16189
|
-
name: "Growth Funnel (AARRR)",
|
|
16190
|
-
version: "0.1.0",
|
|
16191
|
-
description: "Map the growth engine using Pirate Metrics: funnels, channels, campaigns, loops, cohorts.",
|
|
16192
|
-
region: "business_gtm_growth",
|
|
16193
|
-
framework_id: "pirate-metrics-aarrr",
|
|
16194
|
-
creation_sequence: [
|
|
16195
|
-
domainGuideStep(
|
|
16196
|
-
"growth",
|
|
16197
|
-
"Growth",
|
|
16198
|
-
"Funnel model",
|
|
16199
|
-
"Run the growth creation sequence: funnel, channels, campaigns, cohorts."
|
|
16200
|
-
)
|
|
16201
|
-
]
|
|
16202
|
-
};
|
|
16203
|
-
var BUSINESS_MARKETING_PLAYBOOK = {
|
|
16204
|
-
id: "playbook:business-marketing",
|
|
16205
|
-
name: "Marketing",
|
|
16206
|
-
version: "0.1.0",
|
|
16207
|
-
description: "Shape the demand engine: positioning, messaging, SEO keywords, campaigns, channels.",
|
|
16208
|
-
region: "business_gtm_growth",
|
|
16209
|
-
creation_sequence: [
|
|
16210
|
-
domainGuideStep(
|
|
16211
|
-
"marketing",
|
|
16212
|
-
"Marketing",
|
|
16213
|
-
"Demand engine",
|
|
16214
|
-
"Run the marketing creation sequence: positioning, messaging, SEO keywords, campaigns, channels.",
|
|
16215
|
-
{ next_sequence_on_gap: "playbook:experience-content" }
|
|
16216
|
-
)
|
|
16217
|
-
]
|
|
16218
|
-
};
|
|
16219
16975
|
var BUSINESS_GROWTH_METRIC_DRIVEN_PLAYBOOK = {
|
|
16220
16976
|
id: "playbook:business-growth-metric-driven",
|
|
16221
16977
|
name: "Metric-Driven Growth",
|
|
@@ -16403,8 +17159,8 @@ var OPERATIONS_QUALITY_PLAYBOOK = {
|
|
|
16403
17159
|
seqStep(
|
|
16404
17160
|
5,
|
|
16405
17161
|
"Quality Gates",
|
|
16406
|
-
["test_suite", "test_case", "regression_test", "qa_session"],
|
|
16407
|
-
"Establish what does not ship until tests pass. Define the test pyramid: unit, integration, end-to-end."
|
|
17162
|
+
["test_suite", "test_case", "regression_test", "qa_session", "feature", "bug"],
|
|
17163
|
+
"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)."
|
|
16408
17164
|
),
|
|
16409
17165
|
seqStep(
|
|
16410
17166
|
6,
|
|
@@ -16420,21 +17176,6 @@ var OPERATIONS_QUALITY_PLAYBOOK = {
|
|
|
16420
17176
|
)
|
|
16421
17177
|
]
|
|
16422
17178
|
};
|
|
16423
|
-
var OPERATIONS_TEAM_RITUALS_PLAYBOOK = {
|
|
16424
|
-
id: "playbook:operations-team-rituals",
|
|
16425
|
-
name: "Team & Rituals",
|
|
16426
|
-
version: "0.1.0",
|
|
16427
|
-
description: "Capture how the team works: retrospectives, roles, rituals, working agreements, decisions.",
|
|
16428
|
-
region: "operations_quality",
|
|
16429
|
-
creation_sequence: [
|
|
16430
|
-
domainGuideStep(
|
|
16431
|
-
"team_org",
|
|
16432
|
-
"Team",
|
|
16433
|
-
"Team rhythm",
|
|
16434
|
-
"Run the team_org creation sequence: retrospectives, roles, rituals, working agreements."
|
|
16435
|
-
)
|
|
16436
|
-
]
|
|
16437
|
-
};
|
|
16438
17179
|
var UPG_PLAYBOOKS = [
|
|
16439
17180
|
// Region 1 - strategy_outcomes
|
|
16440
17181
|
STRATEGY_OUTCOMES_PLAYBOOK,
|
|
@@ -16442,33 +17183,22 @@ var UPG_PLAYBOOKS = [
|
|
|
16442
17183
|
USERS_NEEDS_PLAYBOOK,
|
|
16443
17184
|
// Region 3 - discovery_research_validation
|
|
16444
17185
|
DISCOVERY_RESEARCH_VALIDATION_PLAYBOOK,
|
|
16445
|
-
DISCOVERY_VALIDATION_HYPOTHESIS_PLAYBOOK,
|
|
16446
17186
|
// Region 4 - market_competitive
|
|
16447
17187
|
MARKET_COMPETITIVE_PLAYBOOK,
|
|
16448
17188
|
// Region 5 - experience_design_brand
|
|
16449
17189
|
EXPERIENCE_DESIGN_BRAND_PLAYBOOK,
|
|
16450
|
-
EXPERIENCE_UX_DOMAIN_ONLY_PLAYBOOK,
|
|
16451
|
-
EXPERIENCE_DESIGN_SYSTEM_PLAYBOOK,
|
|
16452
|
-
EXPERIENCE_CONTENT_PLAYBOOK,
|
|
16453
17190
|
// Region 6 - product_delivery
|
|
16454
17191
|
PRODUCT_DELIVERY_PLAYBOOK,
|
|
16455
|
-
PRODUCT_FEEDBACK_SYNTHESIS_PLAYBOOK,
|
|
16456
17192
|
// Region 7 - engineering_platform
|
|
16457
17193
|
ENGINEERING_PLATFORM_PLAYBOOK,
|
|
16458
|
-
ENGINEERING_ARCHITECTURE_ONLY_PLAYBOOK,
|
|
16459
17194
|
// Region 8 - business_gtm_growth
|
|
16460
17195
|
BUSINESS_GTM_GROWTH_PLAYBOOK,
|
|
16461
|
-
BUSINESS_MODEL_BMC_PLAYBOOK,
|
|
16462
|
-
BUSINESS_PRICING_PLAYBOOK,
|
|
16463
|
-
BUSINESS_GROWTH_FUNNEL_PLAYBOOK,
|
|
16464
|
-
BUSINESS_MARKETING_PLAYBOOK,
|
|
16465
17196
|
BUSINESS_GROWTH_METRIC_DRIVEN_PLAYBOOK,
|
|
16466
17197
|
BUSINESS_MARKETING_AUDIENCE_FIRST_PLAYBOOK,
|
|
16467
17198
|
// Region 9 - analytics_data
|
|
16468
17199
|
ANALYTICS_DATA_PLAYBOOK,
|
|
16469
17200
|
// Region 10 - operations_quality
|
|
16470
|
-
OPERATIONS_QUALITY_PLAYBOOK
|
|
16471
|
-
OPERATIONS_TEAM_RITUALS_PLAYBOOK
|
|
17201
|
+
OPERATIONS_QUALITY_PLAYBOOK
|
|
16472
17202
|
];
|
|
16473
17203
|
var _playbookById = new Map(
|
|
16474
17204
|
UPG_PLAYBOOKS.map((p) => [p.id, p])
|
|
@@ -17138,6 +17868,9 @@ function getVisibleTypes(lens) {
|
|
|
17138
17868
|
}
|
|
17139
17869
|
return [...typeSet];
|
|
17140
17870
|
}
|
|
17871
|
+
function getLensIds() {
|
|
17872
|
+
return UPG_LENSES.map((l) => l.id);
|
|
17873
|
+
}
|
|
17141
17874
|
var UPG_DOMAIN_RINGS = [
|
|
17142
17875
|
{
|
|
17143
17876
|
id: "nucleus",
|
|
@@ -20418,7 +21151,7 @@ var UPG_ANTI_PATTERNS = [
|
|
|
20418
21151
|
]
|
|
20419
21152
|
},
|
|
20420
21153
|
why_it_matters: "Without any chain link, every downstream artefact (need, opportunity, feature) loses its anchor. Features end up addressing demographics instead of struggles.",
|
|
20421
|
-
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.",
|
|
21154
|
+
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.",
|
|
20422
21155
|
stages: ["concept", "validation", "build", "beta", "launch", "growth", "mature"],
|
|
20423
21156
|
severity: "high",
|
|
20424
21157
|
source: { kind: "practitioner", attribution: "Clayton Christensen, Jobs to Be Done" }
|
|
@@ -20558,7 +21291,7 @@ var UPG_ANTI_PATTERNS = [
|
|
|
20558
21291
|
]
|
|
20559
21292
|
},
|
|
20560
21293
|
why_it_matters: "OKRs without measurable key results cannot be tracked, debated, or learned from. The graph carries intent but not accountability.",
|
|
20561
|
-
remediation: "For each `objective`, define 2\u20134 `key_result` entities and link via `objective_achieved_through_key_result`. Use `/upg-okr` to author.",
|
|
21294
|
+
remediation: "For each `objective`, define 2\u20134 `key_result` entities and link via `objective_achieved_through_key_result`. Use `/upg-new-okr` to author.",
|
|
20562
21295
|
stages: ["validation", "build", "beta", "launch", "growth", "mature"],
|
|
20563
21296
|
severity: "high",
|
|
20564
21297
|
source: { kind: "book", citation: "Measure What Matters, John Doerr (2017)" }
|
|
@@ -20618,7 +21351,7 @@ var UPG_ANTI_PATTERNS = [
|
|
|
20618
21351
|
}
|
|
20619
21352
|
},
|
|
20620
21353
|
why_it_matters: 'A graph with one persona past validation is usually carrying an unexamined "everyone is the same user" assumption.',
|
|
20621
|
-
remediation: "Add personas representing the next 1\u20132 most distinct user segments. Use `/upg-persona`.",
|
|
21354
|
+
remediation: "Add personas representing the next 1\u20132 most distinct user segments. Use `/upg-new-persona`.",
|
|
20622
21355
|
stages: ["validation", "build", "beta", "launch", "growth", "mature"],
|
|
20623
21356
|
severity: "medium",
|
|
20624
21357
|
source: { kind: "practitioner", attribution: "Alan Cooper, The Inmates Are Running the Asylum" }
|
|
@@ -20636,7 +21369,7 @@ var UPG_ANTI_PATTERNS = [
|
|
|
20636
21369
|
]
|
|
20637
21370
|
},
|
|
20638
21371
|
why_it_matters: "Build-only graphs commit the team to delivery without a learning loop. Every shipped feature becomes a permanent assumption.",
|
|
20639
|
-
remediation: "Spin up at least one `experiment_plan` or `hypothesis` per quarter's build batch. Use `/upg-
|
|
21372
|
+
remediation: "Spin up at least one `experiment_plan` or `hypothesis` per quarter's build batch. Use `/upg-new-discovery` or `/upg-new-hypothesis`.",
|
|
20640
21373
|
stages: ["build", "beta", "launch", "growth"],
|
|
20641
21374
|
severity: "high",
|
|
20642
21375
|
source: { kind: "practitioner", attribution: "Marty Cagan, Inspired (continuous discovery)" }
|
|
@@ -20874,25 +21607,54 @@ var UPG_PRODUCT_STAGE_COERCION_MAP = Object.freeze({
|
|
|
20874
21607
|
// check happens before the coercion lookup.
|
|
20875
21608
|
});
|
|
20876
21609
|
var UPG_PRODUCT_STAGES_SET = new Set(UPG_PRODUCT_STAGES);
|
|
21610
|
+
function coerceProductStage(value) {
|
|
21611
|
+
if (value === void 0 || value === null) {
|
|
21612
|
+
return { canonical: void 0, originalValue: value, wasCoerced: false, wasUnknown: false };
|
|
21613
|
+
}
|
|
21614
|
+
if (typeof value !== "string") {
|
|
21615
|
+
return { canonical: void 0, originalValue: value, wasCoerced: false, wasUnknown: true };
|
|
21616
|
+
}
|
|
21617
|
+
if (UPG_PRODUCT_STAGES_SET.has(value)) {
|
|
21618
|
+
return { canonical: value, originalValue: value, wasCoerced: false, wasUnknown: false };
|
|
21619
|
+
}
|
|
21620
|
+
const lower = value.toLowerCase();
|
|
21621
|
+
const mapped = UPG_PRODUCT_STAGE_COERCION_MAP[lower];
|
|
21622
|
+
if (mapped) {
|
|
21623
|
+
return { canonical: mapped, originalValue: value, wasCoerced: true, wasUnknown: false };
|
|
21624
|
+
}
|
|
21625
|
+
return { canonical: void 0, originalValue: value, wasCoerced: false, wasUnknown: true };
|
|
21626
|
+
}
|
|
20877
21627
|
var REFLECT_MODES = [
|
|
20878
21628
|
"assumptions",
|
|
20879
21629
|
"alternatives",
|
|
20880
21630
|
"blind-spots",
|
|
20881
21631
|
"load-bearing"
|
|
20882
21632
|
];
|
|
21633
|
+
function deriveFrameworkExamples() {
|
|
21634
|
+
const byApproach = {
|
|
21635
|
+
plan: [],
|
|
21636
|
+
inspect: [],
|
|
21637
|
+
prioritise: [],
|
|
21638
|
+
trace: [],
|
|
21639
|
+
reflect: []
|
|
21640
|
+
};
|
|
21641
|
+
for (const fw of UPG_FRAMEWORKS) {
|
|
21642
|
+
for (const approachId of fw.approach_ids ?? []) {
|
|
21643
|
+
if (approachId in byApproach) {
|
|
21644
|
+
byApproach[approachId].push(fw.id);
|
|
21645
|
+
}
|
|
21646
|
+
}
|
|
21647
|
+
}
|
|
21648
|
+
return byApproach;
|
|
21649
|
+
}
|
|
21650
|
+
var FRAMEWORK_EXAMPLES = deriveFrameworkExamples();
|
|
20883
21651
|
var PLAN = {
|
|
20884
21652
|
id: "plan",
|
|
20885
21653
|
label: "Plan",
|
|
20886
21654
|
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.',
|
|
20887
21655
|
question_answered: "what should I build next?",
|
|
20888
21656
|
signature_hint: "({ region?: UPGRegionId }) \u2192 { missing_entities, coverage_score }",
|
|
20889
|
-
framework_id_examples:
|
|
20890
|
-
"now-next-later",
|
|
20891
|
-
"moscow",
|
|
20892
|
-
"wardley-map",
|
|
20893
|
-
"okr-framework",
|
|
20894
|
-
"three-horizons"
|
|
20895
|
-
]
|
|
21657
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.plan
|
|
20896
21658
|
};
|
|
20897
21659
|
var INSPECT = {
|
|
20898
21660
|
id: "inspect",
|
|
@@ -20900,28 +21662,15 @@ var INSPECT = {
|
|
|
20900
21662
|
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).',
|
|
20901
21663
|
question_answered: "what's broken?",
|
|
20902
21664
|
signature_hint: "({ region?: UPGRegionId, entities?: entity_ids[] }) \u2192 { violations: [{ severity, kind, entity_id, description, fix_hint }] }",
|
|
20903
|
-
framework_id_examples:
|
|
20904
|
-
"heuristic-evaluation",
|
|
20905
|
-
"tech-debt-tracker",
|
|
20906
|
-
"accessibility-maturity-model",
|
|
20907
|
-
"cognitive-walkthrough",
|
|
20908
|
-
"blameless-postmortem"
|
|
20909
|
-
]
|
|
21665
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.inspect
|
|
20910
21666
|
};
|
|
20911
21667
|
var PRIORITISE = {
|
|
20912
21668
|
id: "prioritise",
|
|
20913
21669
|
label: "Prioritise",
|
|
20914
|
-
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,
|
|
21670
|
+
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).`,
|
|
20915
21671
|
question_answered: "what's most important?",
|
|
20916
21672
|
signature_hint: "({ candidates: entity_ids[], framework_id }) \u2192 { ranked: [{ entity_id, score, rationale }], framework_used }",
|
|
20917
|
-
framework_id_examples:
|
|
20918
|
-
"rice-scoring",
|
|
20919
|
-
"ice-scoring",
|
|
20920
|
-
"kano-model",
|
|
20921
|
-
"cost-of-delay",
|
|
20922
|
-
"moscow",
|
|
20923
|
-
"wsjf"
|
|
20924
|
-
]
|
|
21673
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.prioritise
|
|
20925
21674
|
};
|
|
20926
21675
|
var TRACE = {
|
|
20927
21676
|
id: "trace",
|
|
@@ -20929,34 +21678,15 @@ var TRACE = {
|
|
|
20929
21678
|
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.',
|
|
20930
21679
|
question_answered: "walk a meaningful path through existing graph",
|
|
20931
21680
|
signature_hint: "({ anchor: entity_id, path: UPGEntityType[], edges_override?: (string | null)[] }) \u2192 { trail: [{ depth, entity_id, edge_type_in }], reached: entity_id[] }",
|
|
20932
|
-
framework_id_examples:
|
|
20933
|
-
"opportunity-solution-tree",
|
|
20934
|
-
"strategic-cascade",
|
|
20935
|
-
"metrics-tree",
|
|
20936
|
-
"user-journey-map",
|
|
20937
|
-
"impact-map",
|
|
20938
|
-
"dependency-map"
|
|
20939
|
-
]
|
|
21681
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.trace
|
|
20940
21682
|
};
|
|
20941
21683
|
var REFLECT = {
|
|
20942
21684
|
id: "reflect",
|
|
20943
21685
|
label: "Reflect",
|
|
20944
|
-
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.
|
|
21686
|
+
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.',
|
|
20945
21687
|
question_answered: "what should I be questioning?",
|
|
20946
21688
|
signature_hint: "({ scope?: UPGRegionId | entity_id | null, mode?: 'assumptions' | 'alternatives' | 'blind-spots' | 'load-bearing' }) \u2192 { prompts: [{ kind, question, target_entities? }] }",
|
|
20947
|
-
framework_id_examples:
|
|
20948
|
-
// Reflection classics: the five canonical reflect frameworks.
|
|
20949
|
-
"five-whys",
|
|
20950
|
-
"pre-mortem",
|
|
20951
|
-
"red-team",
|
|
20952
|
-
"devils-advocate",
|
|
20953
|
-
"second-order-thinking",
|
|
20954
|
-
// Reflective ceremonies + reflective JTBD lens already in the catalog.
|
|
20955
|
-
"retrospective",
|
|
20956
|
-
"four-forces-of-progress",
|
|
20957
|
-
"assumption-canvas",
|
|
20958
|
-
"win-loss-analysis"
|
|
20959
|
-
]
|
|
21689
|
+
framework_id_examples: FRAMEWORK_EXAMPLES.reflect
|
|
20960
21690
|
};
|
|
20961
21691
|
var UPG_APPROACHES = [PLAN, INSPECT, PRIORITISE, TRACE, REFLECT];
|
|
20962
21692
|
var UPG_APPROACHES_BY_ID = Object.fromEntries(
|
|
@@ -22884,7 +23614,7 @@ function portfolioBody(doc) {
|
|
|
22884
23614
|
function computeBodyChecksum(doc) {
|
|
22885
23615
|
const body = isPortfolio(doc) ? portfolioBody(doc) : singleBody(doc);
|
|
22886
23616
|
const content = JSON.stringify(body);
|
|
22887
|
-
return
|
|
23617
|
+
return createHash(INTEGRITY_HASH_PRIMITIVE).update(content).digest("hex").slice(0, INTEGRITY_DIGEST_HEX);
|
|
22888
23618
|
}
|
|
22889
23619
|
function isPortfolio(doc) {
|
|
22890
23620
|
return doc.type === "portfolio" || "cross_edges" in doc;
|
|
@@ -22950,7 +23680,7 @@ function serializePortfolioWithHeader(doc, opts) {
|
|
|
22950
23680
|
header.integrity = { algorithm: INTEGRITY_ALGORITHM, body: computeBodyChecksum(doc) };
|
|
22951
23681
|
return JSON.stringify({ $upg: header, ...body }, null, 2) + "\n";
|
|
22952
23682
|
}
|
|
22953
|
-
var UPG_VERSION = "0.8.
|
|
23683
|
+
var UPG_VERSION = "0.8.2";
|
|
22954
23684
|
var MARKDOWN_FORMAT_VERSION = "0.1";
|
|
22955
23685
|
var UPG_TYPES = getTypes();
|
|
22956
23686
|
var UPG_TYPES_SET = new Set(UPG_TYPES);
|
|
@@ -23010,6 +23740,52 @@ var UPG_DOMAIN_COUNT = UPG_DOMAINS.length;
|
|
|
23010
23740
|
var UPG_EDGE_COUNT = UPG_EDGE_TYPES.length;
|
|
23011
23741
|
var UPG_META_COUNT = UPG_ENTITY_META.length;
|
|
23012
23742
|
|
|
23743
|
+
// src/lib/server-context.ts
|
|
23744
|
+
function text(s) {
|
|
23745
|
+
return { content: [{ type: "text", text: s }] };
|
|
23746
|
+
}
|
|
23747
|
+
function textError(s) {
|
|
23748
|
+
return { content: [{ type: "text", text: s }], isError: true };
|
|
23749
|
+
}
|
|
23750
|
+
var CANONICAL_LENS_IDS = getLensIds();
|
|
23751
|
+
function isCanonicalLens(id) {
|
|
23752
|
+
return typeof id === "string" && CANONICAL_LENS_IDS.includes(id);
|
|
23753
|
+
}
|
|
23754
|
+
function createSessionContext() {
|
|
23755
|
+
return {
|
|
23756
|
+
lens: "product",
|
|
23757
|
+
skills_invoked: [],
|
|
23758
|
+
recommendations_given: [],
|
|
23759
|
+
focus_area: null,
|
|
23760
|
+
custom: {}
|
|
23761
|
+
};
|
|
23762
|
+
}
|
|
23763
|
+
function createQueryCache() {
|
|
23764
|
+
return { entries: /* @__PURE__ */ new Map(), counter: 0 };
|
|
23765
|
+
}
|
|
23766
|
+
function syncFilePath(upgPath) {
|
|
23767
|
+
const dir = path.dirname(upgPath);
|
|
23768
|
+
const base = path.basename(upgPath, ".upg");
|
|
23769
|
+
return path.join(dir, `${base}.upg-sync`);
|
|
23770
|
+
}
|
|
23771
|
+
async function readSyncState(upgPath) {
|
|
23772
|
+
const p = syncFilePath(upgPath);
|
|
23773
|
+
try {
|
|
23774
|
+
const raw = await fsp.readFile(p, "utf-8");
|
|
23775
|
+
return JSON.parse(raw);
|
|
23776
|
+
} catch {
|
|
23777
|
+
return null;
|
|
23778
|
+
}
|
|
23779
|
+
}
|
|
23780
|
+
async function writeSyncState(upgPath, state) {
|
|
23781
|
+
const p = syncFilePath(upgPath);
|
|
23782
|
+
await fsp.writeFile(p, JSON.stringify(state, null, 2) + "\n", "utf-8");
|
|
23783
|
+
}
|
|
23784
|
+
async function hashFile(filePath) {
|
|
23785
|
+
const content = await fsp.readFile(filePath, "utf-8");
|
|
23786
|
+
return createHash2("sha256").update(content).digest("hex");
|
|
23787
|
+
}
|
|
23788
|
+
|
|
23013
23789
|
// src/tools/context.ts
|
|
23014
23790
|
import { computeGraphDigest } from "@unified-product-graph/sdk";
|
|
23015
23791
|
function lensAwareLabel(entityType, lensId) {
|
|
@@ -23067,7 +23843,7 @@ Lens: ${sessionContext.lens}`
|
|
|
23067
23843
|
lines.push(` - [${sev}] ${b.title}`);
|
|
23068
23844
|
}
|
|
23069
23845
|
}
|
|
23070
|
-
} else if (sessionContext.lens === "
|
|
23846
|
+
} else if (sessionContext.lens === "ux_design") {
|
|
23071
23847
|
const screens = nodes.filter((n) => n.type === "screen");
|
|
23072
23848
|
const components = nodes.filter((n) => n.type === "design_component");
|
|
23073
23849
|
const flows = nodes.filter((n) => n.type === "user_flow");
|
|
@@ -23182,7 +23958,7 @@ var getGraphDigest = (args, ctx) => {
|
|
|
23182
23958
|
const blockedFeatures = allNodes.filter((n) => blockedFeatureIds.has(n.id)).map((n) => n.title);
|
|
23183
23959
|
const openInvestigations = allNodes.filter((n) => n.type === "investigation" && n.status !== "resolved").length;
|
|
23184
23960
|
lensDigest = { open_bugs: openBugs, blockers: blockerEdges.length, in_flight_features: inFlightFeatures, active_debt: activeDebt, blocked_features: blockedFeatures, open_investigations: openInvestigations };
|
|
23185
|
-
} else if (sessionContext.lens === "
|
|
23961
|
+
} else if (sessionContext.lens === "ux_design") {
|
|
23186
23962
|
const screens = allNodes.filter((n) => n.type === "screen").length;
|
|
23187
23963
|
const components = allNodes.filter((n) => n.type === "design_component").length;
|
|
23188
23964
|
const flows = allNodes.filter((n) => n.type === "user_flow").length;
|
|
@@ -23300,7 +24076,12 @@ var updateSessionContext = (args, ctx) => {
|
|
|
23300
24076
|
if (focusArea !== void 0) {
|
|
23301
24077
|
sessionContext.focus_area = focusArea;
|
|
23302
24078
|
}
|
|
23303
|
-
if (lensArg
|
|
24079
|
+
if (lensArg !== void 0) {
|
|
24080
|
+
if (!isCanonicalLens(lensArg)) {
|
|
24081
|
+
return textError(
|
|
24082
|
+
`Invalid lens "${lensArg}". Canonical lenses: ${CANONICAL_LENS_IDS.join(", ")}`
|
|
24083
|
+
);
|
|
24084
|
+
}
|
|
23304
24085
|
sessionContext.lens = lensArg;
|
|
23305
24086
|
if (persistLens && store) {
|
|
23306
24087
|
const doc = store.getDocument();
|
|
@@ -24110,7 +24891,7 @@ var updateNode = (args, ctx) => {
|
|
|
24110
24891
|
const existingNode = store.getNode(nid);
|
|
24111
24892
|
if (existingNode) {
|
|
24112
24893
|
const sw = validateStatusAgainstLifecycle(existingNode.type, args.status);
|
|
24113
|
-
if (sw)
|
|
24894
|
+
if (sw) return textError(sw);
|
|
24114
24895
|
}
|
|
24115
24896
|
}
|
|
24116
24897
|
let unknownProperties = [];
|
|
@@ -24143,10 +24924,18 @@ var updateNode = (args, ctx) => {
|
|
|
24143
24924
|
});
|
|
24144
24925
|
if (lengthWarnings.length > 0) warnings.push(...lengthWarnings);
|
|
24145
24926
|
try {
|
|
24146
|
-
|
|
24927
|
+
let updated = store.updateNode(nid, patch);
|
|
24928
|
+
let removedKeys;
|
|
24929
|
+
const unsetArg = args.unset_properties;
|
|
24930
|
+
if (Array.isArray(unsetArg) && unsetArg.length > 0) {
|
|
24931
|
+
const r = store.unsetNodeProperties(nid, unsetArg);
|
|
24932
|
+
updated = r.node;
|
|
24933
|
+
if (r.removed.length > 0) removedKeys = r.removed;
|
|
24934
|
+
}
|
|
24147
24935
|
const result = { node: updated };
|
|
24148
24936
|
if (warnings.length > 0) result.warning = warnings.join(" | ");
|
|
24149
24937
|
if (unknownProperties.length > 0) result.unknown_properties = unknownProperties;
|
|
24938
|
+
if (removedKeys && removedKeys.length > 0) result.unset = removedKeys;
|
|
24150
24939
|
return text(JSON.stringify(result, null, 2));
|
|
24151
24940
|
} catch (err) {
|
|
24152
24941
|
return textError(err.message);
|
|
@@ -24468,7 +25257,7 @@ var deduplicateNodes = (args, ctx) => {
|
|
|
24468
25257
|
// src/tools/edges.ts
|
|
24469
25258
|
import { edgeId as edgeId2 } from "@unified-product-graph/sdk";
|
|
24470
25259
|
import { inferEdgeTypeWithTier } from "@unified-product-graph/sdk";
|
|
24471
|
-
import {
|
|
25260
|
+
import { validateExplicitEdgeType } from "@unified-product-graph/sdk";
|
|
24472
25261
|
import { buildResolverHints } from "@unified-product-graph/sdk";
|
|
24473
25262
|
import {
|
|
24474
25263
|
createEdge as createEdgeLib,
|
|
@@ -24575,13 +25364,13 @@ var batchCreateEdges = (args, ctx) => {
|
|
|
24575
25364
|
);
|
|
24576
25365
|
}
|
|
24577
25366
|
if (e.type) {
|
|
24578
|
-
const
|
|
25367
|
+
const typeCheck = validateExplicitEdgeType(
|
|
24579
25368
|
e.type,
|
|
24580
25369
|
sourceNode.type,
|
|
24581
25370
|
targetNode.type
|
|
24582
25371
|
);
|
|
24583
|
-
if (
|
|
24584
|
-
return textError(`Edge at index ${i}: ${
|
|
25372
|
+
if (typeCheck.errors.length > 0) {
|
|
25373
|
+
return textError(`Edge at index ${i}: ${typeCheck.errors.join(" ")}`);
|
|
24585
25374
|
}
|
|
24586
25375
|
resolvedEdgeTypes.push(e.type);
|
|
24587
25376
|
} else {
|
|
@@ -25029,10 +25818,11 @@ var listLocalProducts = (_args, _ctx) => {
|
|
|
25029
25818
|
try {
|
|
25030
25819
|
const raw = fs.readFileSync(filePath, "utf-8");
|
|
25031
25820
|
const doc = JSON.parse(raw);
|
|
25821
|
+
const coerced = coerceProductStage(doc.product?.stage);
|
|
25032
25822
|
products.push({
|
|
25033
25823
|
file: path3.relative(cwd, filePath),
|
|
25034
25824
|
title: doc.product?.title ?? "(untitled)",
|
|
25035
|
-
stage:
|
|
25825
|
+
stage: coerced.canonical ?? null,
|
|
25036
25826
|
nodes: Array.isArray(doc.nodes) ? doc.nodes.length : 0,
|
|
25037
25827
|
edges: Array.isArray(doc.edges) ? doc.edges.length : 0
|
|
25038
25828
|
});
|
|
@@ -25408,7 +26198,7 @@ import {
|
|
|
25408
26198
|
// src/tools/validation.ts
|
|
25409
26199
|
import { computeSchemaDriftSummary } from "@unified-product-graph/sdk";
|
|
25410
26200
|
import { collectAntiPatternInputs } from "@unified-product-graph/sdk";
|
|
25411
|
-
import { validateEdgeTypePair
|
|
26201
|
+
import { validateEdgeTypePair } from "@unified-product-graph/sdk";
|
|
25412
26202
|
import { checkPropertyTypes as checkPropertyTypes2 } from "@unified-product-graph/sdk";
|
|
25413
26203
|
var CANONICAL_NODE_FIELDS = /* @__PURE__ */ new Set([
|
|
25414
26204
|
"id",
|
|
@@ -25700,7 +26490,7 @@ var validateGraph = (args, ctx) => {
|
|
|
25700
26490
|
const sourceNode = nodeById.get(edge.source);
|
|
25701
26491
|
const targetNode = nodeById.get(edge.target);
|
|
25702
26492
|
if (!sourceNode || !targetNode) continue;
|
|
25703
|
-
const pairCheck =
|
|
26493
|
+
const pairCheck = validateEdgeTypePair(
|
|
25704
26494
|
edge.type,
|
|
25705
26495
|
sourceNode.type,
|
|
25706
26496
|
targetNode.type
|
|
@@ -25954,10 +26744,13 @@ function approachEnvelope(approachId, scope, payload) {
|
|
|
25954
26744
|
}
|
|
25955
26745
|
var plan = (args, ctx) => {
|
|
25956
26746
|
const region = args.region;
|
|
25957
|
-
const
|
|
26747
|
+
const exhaustive = args.exhaustive;
|
|
26748
|
+
const result = executePlan(ctx.store, { region, exhaustive });
|
|
25958
26749
|
return approachEnvelope("plan", region ?? null, {
|
|
25959
|
-
params: { region: region ?? null },
|
|
26750
|
+
params: { region: region ?? null, exhaustive: exhaustive ?? false },
|
|
25960
26751
|
region: result.region,
|
|
26752
|
+
plan_scope: result.scope,
|
|
26753
|
+
scoped_regions: result.scoped_regions,
|
|
25961
26754
|
missing_entities: result.missing_entities,
|
|
25962
26755
|
coverage_score: result.coverage_score,
|
|
25963
26756
|
expected_count: result.expected_count,
|
|
@@ -26979,9 +27772,14 @@ function auditOne(name) {
|
|
|
26979
27772
|
};
|
|
26980
27773
|
}
|
|
26981
27774
|
function allSkillNames() {
|
|
26982
|
-
const
|
|
26983
|
-
|
|
26984
|
-
|
|
27775
|
+
const names = /* @__PURE__ */ new Set();
|
|
27776
|
+
for (const dir of [sourceSkillsDir(), deployedSkillsDir()]) {
|
|
27777
|
+
if (!existsSync2(dir)) continue;
|
|
27778
|
+
for (const d of readdirSync2(dir, { withFileTypes: true })) {
|
|
27779
|
+
if (d.isDirectory() || d.isSymbolicLink()) names.add(d.name);
|
|
27780
|
+
}
|
|
27781
|
+
}
|
|
27782
|
+
return [...names].sort();
|
|
26985
27783
|
}
|
|
26986
27784
|
var skillAudit = (args) => {
|
|
26987
27785
|
const filter = typeof args?.name === "string" && args.name.length > 0 ? args.name : null;
|
|
@@ -27171,6 +27969,11 @@ var TOOL_DEFINITIONS = [
|
|
|
27171
27969
|
properties: {
|
|
27172
27970
|
type: "object",
|
|
27173
27971
|
description: "Merged with existing properties"
|
|
27972
|
+
},
|
|
27973
|
+
unset_properties: {
|
|
27974
|
+
type: "array",
|
|
27975
|
+
items: { type: "string" },
|
|
27976
|
+
description: "Property keys to DELETE. Applied after the `properties` merge, so one call can set some keys and drop others. Writing `{ key: null }` only stores a literal null; use this to actually remove a key. Unknown keys are ignored."
|
|
27174
27977
|
}
|
|
27175
27978
|
},
|
|
27176
27979
|
required: ["node_id"]
|
|
@@ -27621,7 +28424,7 @@ var TOOL_DEFINITIONS = [
|
|
|
27621
28424
|
},
|
|
27622
28425
|
{
|
|
27623
28426
|
name: "get_playbook",
|
|
27624
|
-
description: 'Return one `UPGPlaybook` by id (e.g. "playbook:strategy-outcomes", "playbook:business-
|
|
28427
|
+
description: 'Return one `UPGPlaybook` by id (e.g. "playbook:strategy-outcomes", "playbook:business-gtm-growth"). Includes the ordered `creation_sequence` with step kinds and prompts. IDs are namespace-prefixed `playbook:*`. For approaches, use `get_approach`.',
|
|
27625
28428
|
inputSchema: {
|
|
27626
28429
|
type: "object",
|
|
27627
28430
|
properties: {
|
|
@@ -27653,17 +28456,18 @@ var TOOL_DEFINITIONS = [
|
|
|
27653
28456
|
},
|
|
27654
28457
|
{
|
|
27655
28458
|
name: "plan",
|
|
27656
|
-
description: 'Plan approach: path of arrival to "what should I build next?". Returns the Plan record + invocation params wrapped in `{ approach_id, scope, generated_at, approach, params }`. The LLM consumes `signature_hint` and synthesises `{ missing_entities, coverage_score }` against the live graph. Optional `region` narrows scope.',
|
|
28459
|
+
description: 'Plan approach: path of arrival to "what should I build next?". Returns the Plan record + invocation params wrapped in `{ approach_id, scope, generated_at, approach, params }`. The LLM consumes `signature_hint` and synthesises `{ missing_entities, coverage_score }` against the live graph. Optional `region` narrows scope; omit `region` to scope to the product\'s ACTIVE regions; pass `exhaustive:true` to score the full type universe (UPG-601).',
|
|
27657
28460
|
inputSchema: {
|
|
27658
28461
|
type: "object",
|
|
27659
28462
|
properties: {
|
|
27660
|
-
region: { type: "string", description:
|
|
28463
|
+
region: { type: "string", description: `Optional UPGRegionId or atomic-domain id. Narrows planning scope to a single region (e.g. "users_needs", "business_gtm_growth"). Omit to scope to the product's active regions.` },
|
|
28464
|
+
exhaustive: { type: "boolean", description: "If true, score against the entire 312-type universe (every domain creation sequence). Off by default; whole-universe gap scoring is noisy for a focused product. Only applies when `region` is omitted." }
|
|
27661
28465
|
}
|
|
27662
28466
|
}
|
|
27663
28467
|
},
|
|
27664
28468
|
{
|
|
27665
28469
|
name: "inspect",
|
|
27666
|
-
description: '[LLM-mediated] This tool returns a routing envelope, not computed results. For user-facing inspection, invoke the /upg-
|
|
28470
|
+
description: '[LLM-mediated] This tool returns a routing envelope, not computed results. For user-facing inspection, invoke the /upg-show-entity skill instead of calling this tool directly. Inspect approach: path of arrival to "what\'s broken?". Returns the Inspect record + invocation params in the family-resemblance envelope. The LLM consumes `signature_hint` and emits `{ violations: [{ severity, kind, entity_id, description, fix_hint }] }` against `UPG_ANTI_PATTERNS` + the live graph. Optional `region` or `entities[]` scope the audit.',
|
|
27667
28471
|
inputSchema: {
|
|
27668
28472
|
type: "object",
|
|
27669
28473
|
properties: {
|
|
@@ -28167,10 +28971,10 @@ var TOOL_DEFINITIONS = [
|
|
|
28167
28971
|
inputSchema: {
|
|
28168
28972
|
type: "object",
|
|
28169
28973
|
properties: {
|
|
28170
|
-
skill_invoked: { type: "string", description: 'Register that this skill was just invoked (e.g. "upg-status")' },
|
|
28171
|
-
recommendation: { type: "string", description: 'Record a recommendation given to the user (e.g. "Run /upg-strategy to fill strategy gap")' },
|
|
28974
|
+
skill_invoked: { type: "string", description: 'Register that this skill was just invoked (e.g. "upg-show-status")' },
|
|
28975
|
+
recommendation: { type: "string", description: 'Record a recommendation given to the user (e.g. "Run /upg-new-strategy to fill strategy gap")' },
|
|
28172
28976
|
focus_area: { type: "string", description: 'Set the current focus area (e.g. "strategy", "validation", "user_research")' },
|
|
28173
|
-
lens: { type: "string", enum: [
|
|
28977
|
+
lens: { type: "string", enum: [...CANONICAL_LENS_IDS], description: "Switch the active lens. Changes what context, skills, and gaps are surfaced first. Canonical lens ids (derived from core): product, ux_design, engineering, growth, business, research, marketing, full." },
|
|
28174
28978
|
persist_lens: { type: "boolean", description: "If true, also save the lens to the .upg file so it persists across sessions" },
|
|
28175
28979
|
custom: { type: "object", description: "Arbitrary key-value pairs for cross-skill state" }
|
|
28176
28980
|
}
|
|
@@ -28498,7 +29302,7 @@ function createServer(store) {
|
|
|
28498
29302
|
{
|
|
28499
29303
|
const doc = store.getDocument();
|
|
28500
29304
|
const persistedLens = doc.product?.lens;
|
|
28501
|
-
if (persistedLens &&
|
|
29305
|
+
if (persistedLens && isCanonicalLens(persistedLens)) {
|
|
28502
29306
|
sessionContext.lens = persistedLens;
|
|
28503
29307
|
}
|
|
28504
29308
|
}
|
|
@@ -28677,7 +29481,7 @@ async function runMcpServer() {
|
|
|
28677
29481
|
Deprecated types found in your graph:
|
|
28678
29482
|
${lines.join("\n")}
|
|
28679
29483
|
`);
|
|
28680
|
-
process.stderr.write(`Run /upg-
|
|
29484
|
+
process.stderr.write(`Run /upg-fix-types to update them.
|
|
28681
29485
|
|
|
28682
29486
|
`);
|
|
28683
29487
|
}
|