@unified-product-graph/cli 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/README.md +247 -0
- package/dist/cli.cjs +141010 -0
- package/package.json +65 -0
- package/skills/README.md +10 -0
- package/skills/upg/SKILL.md +245 -0
- package/skills/upg-analytics/SKILL.md +135 -0
- package/skills/upg-capture/SKILL.md +274 -0
- package/skills/upg-connect/SKILL.md +167 -0
- package/skills/upg-context/SKILL.md +506 -0
- package/skills/upg-context-intelligence/SKILL.md +227 -0
- package/skills/upg-design-system/SKILL.md +265 -0
- package/skills/upg-diff/SKILL.md +150 -0
- package/skills/upg-discover/SKILL.md +290 -0
- package/skills/upg-explore/SKILL-DETAIL.md +481 -0
- package/skills/upg-explore/SKILL.md +297 -0
- package/skills/upg-export/SKILL.md +385 -0
- package/skills/upg-feedback/SKILL.md +141 -0
- package/skills/upg-gaps/SKILL.md +376 -0
- package/skills/upg-hypothesis/SKILL.md +190 -0
- package/skills/upg-impact/SKILL.md +229 -0
- package/skills/upg-import/SKILL.md +189 -0
- package/skills/upg-init/SKILL.md +410 -0
- package/skills/upg-inspect/SKILL.md +167 -0
- package/skills/upg-journey/SKILL.md +207 -0
- package/skills/upg-launch/SKILL-DETAIL.md +392 -0
- package/skills/upg-launch/SKILL.md +141 -0
- package/skills/upg-migrate/SKILL.md +146 -0
- package/skills/upg-okr/SKILL-DETAIL.md +351 -0
- package/skills/upg-okr/SKILL.md +88 -0
- package/skills/upg-persona/SKILL.md +230 -0
- package/skills/upg-prioritise/SKILL.md +195 -0
- package/skills/upg-pull/SKILL-DETAIL.md +398 -0
- package/skills/upg-pull/SKILL.md +57 -0
- package/skills/upg-push/SKILL-DETAIL.md +385 -0
- package/skills/upg-push/SKILL.md +113 -0
- package/skills/upg-reflect/SKILL.md +201 -0
- package/skills/upg-research/SKILL.md +336 -0
- package/skills/upg-rollback/SKILL.md +163 -0
- package/skills/upg-run/SKILL.md +126 -0
- package/skills/upg-schema-changelog/SKILL.md +231 -0
- package/skills/upg-schema-consolidate/SKILL.md +243 -0
- package/skills/upg-schema-edges/SKILL.md +287 -0
- package/skills/upg-schema-evolve/SKILL.md +313 -0
- package/skills/upg-schema-health/SKILL.md +279 -0
- package/skills/upg-schema-update/SKILL.md +206 -0
- package/skills/upg-snapshot/SKILL.md +108 -0
- package/skills/upg-status/SKILL.md +340 -0
- package/skills/upg-strategy/SKILL.md +334 -0
- package/skills/upg-template/SKILL.md +145 -0
- package/skills/upg-trace/SKILL.md +197 -0
- package/skills/upg-tree/SKILL.md +233 -0
- package/skills/upg-verify/SKILL.md +223 -0
- package/skills/upg-workspace/SKILL.md +103 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upg-hypothesis
|
|
3
|
+
description: "Structured Hypothesis Creation"
|
|
4
|
+
user-invocable: true
|
|
5
|
+
argument-hint: "[description]"
|
|
6
|
+
category: cognitive
|
|
7
|
+
approaches: [plan]
|
|
8
|
+
playbooks: [discovery-validation-hypothesis-cycle]
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# /upg-hypothesis — Structured Hypothesis Creation
|
|
12
|
+
|
|
13
|
+
Note: In user-facing conversation, use "bet" or "design experiment" instead of "hypothesis" — the word triggers "formal/academic" anxiety for non-PM users. The canonical entity type is `hypothesis` (re-promoted at v0.4.0 — the "claim" suffix was redundant). Evidence attaches via `hypothesis_has_evidence` with `evidence.direction` carrying supports/refutes/neutral.
|
|
14
|
+
|
|
15
|
+
You are a Unified Product Graph validation specialist. Your job is to guide the user through creating a well-structured hypothesis using the "We believe / Will result in / We know when" format, then help them design an experiment to test it.
|
|
16
|
+
|
|
17
|
+
**Before producing any output, load the design system:** `/upg-context` (interaction principles, design system, lens rules) and `/upg-context-intelligence` (benchmarks, user personas, product philosophy).
|
|
18
|
+
|
|
19
|
+
## Tools
|
|
20
|
+
|
|
21
|
+
Use the `mcp__unified-product-graph__*` MCP tools (create_node, create_edge, search_nodes, list_nodes, get_node).
|
|
22
|
+
|
|
23
|
+
## Phase Map
|
|
24
|
+
|
|
25
|
+
| Phase | Label | Steps |
|
|
26
|
+
|-------|-------|-------|
|
|
27
|
+
| 1 of 4 | What's your bet | Steps 1-2 |
|
|
28
|
+
| 2 of 4 | Structuring it | Steps 2b-2c |
|
|
29
|
+
| 3 of 4 | What's riskiest | Steps 3-4 |
|
|
30
|
+
| 4 of 4 | How to test it | Steps 5-6 |
|
|
31
|
+
|
|
32
|
+
## Context
|
|
33
|
+
|
|
34
|
+
This follows the Hypothesis-Driven Development pattern from the Validation atomic domain inside the Discovery & Validation region of the Unified Product Graph. Every product decision should be framed as a testable bet — not an opinion, not a feature request, but a structured hypothesis with clear success criteria.
|
|
35
|
+
|
|
36
|
+
**Reference:** Eric Ries, "The Lean Startup" (2011); Barry O'Reilly, "Lean Enterprise" (2015)
|
|
37
|
+
|
|
38
|
+
## Guided Flow
|
|
39
|
+
|
|
40
|
+
### Step 1: Find the Context
|
|
41
|
+
**Phase 1 of 4 — What's your bet** (~5 minutes total)
|
|
42
|
+
|
|
43
|
+
First, understand what this hypothesis is about:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
search_nodes({ query: "<user's topic>" })
|
|
47
|
+
list_nodes({ type: "solution" })
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
If there's an existing solution or opportunity this hypothesis relates to, note it for connection later.
|
|
51
|
+
|
|
52
|
+
Ask: **"What's the bet you're making? What change or approach do you believe will work?"**
|
|
53
|
+
|
|
54
|
+
### Step 2: Structure the Hypothesis
|
|
55
|
+
|
|
56
|
+
Guide them through the three-part format:
|
|
57
|
+
|
|
58
|
+
**"We believe that..."** (the change)
|
|
59
|
+
Ask: **"Complete this sentence: 'We believe that [doing/building/changing X]...'"**
|
|
60
|
+
|
|
61
|
+
This should be specific and actionable:
|
|
62
|
+
- Good: "We believe that adding a guided onboarding wizard with 3 steps"
|
|
63
|
+
- Bad: "We believe that improving onboarding"
|
|
64
|
+
|
|
65
|
+
**"Will result in..."** (the measurable outcome)
|
|
66
|
+
Ask: **"...will result in what measurable change?"**
|
|
67
|
+
|
|
68
|
+
This should be a metric, not a feeling:
|
|
69
|
+
- Good: "...will result in a 25% reduction in Day-1 drop-off"
|
|
70
|
+
- Bad: "...will result in better user experience"
|
|
71
|
+
|
|
72
|
+
**"We will know when..."** (the success criteria)
|
|
73
|
+
Ask: **"How will you know this worked? What specific metric and threshold?"**
|
|
74
|
+
|
|
75
|
+
This should be falsifiable:
|
|
76
|
+
- Good: "We will know when the Day-1 activation rate exceeds 60% for a cohort of 200+ users"
|
|
77
|
+
- Bad: "We will know when users are happier"
|
|
78
|
+
|
|
79
|
+
### Step 3: Assess the Risk
|
|
80
|
+
|
|
81
|
+
Ask: **"What's the riskiest assumption in this hypothesis? What's the one thing that, if wrong, kills the whole bet?"**
|
|
82
|
+
|
|
83
|
+
Use this to set the `we_test_by` property and to inform experiment design.
|
|
84
|
+
|
|
85
|
+
### Step 3b: Vibe Check and Thresholds
|
|
86
|
+
|
|
87
|
+
Show the assembled hypothesis and ask: "Here's your bet — anything you'd change before I save it?"
|
|
88
|
+
|
|
89
|
+
Then ask for success/failure thresholds: "What would convince you this is working? What number or signal?"
|
|
90
|
+
|
|
91
|
+
### Step 4: Create the Hypothesis
|
|
92
|
+
|
|
93
|
+
**Before creating the hypothesis, check if a solution node exists:**
|
|
94
|
+
- If the hypothesis relates to an opportunity: ask "Does a solution already exist for this opportunity? If not, should I create one first?" Wait for the answer. If yes, create the solution node first, then attach the hypothesis to the solution.
|
|
95
|
+
- The hierarchy is: opportunity → solution → hypothesis. Don't skip the solution layer.
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
create_node({
|
|
99
|
+
type: "hypothesis",
|
|
100
|
+
title: "<concise hypothesis — e.g. 'Onboarding wizard reduces Day-1 drop-off'>",
|
|
101
|
+
description: "<full narrative combining all three parts>",
|
|
102
|
+
properties: {
|
|
103
|
+
we_believe: "<the change>",
|
|
104
|
+
will_result_in: "<the measurable outcome>",
|
|
105
|
+
we_know_when: "<the success signal and threshold>",
|
|
106
|
+
},
|
|
107
|
+
// Canonical lifecycle on UPGBaseNode.status (top-level, not in properties).
|
|
108
|
+
// hypothesis enum: drafted | active | validated | invalidated | archived.
|
|
109
|
+
// The legacy `we_test_by` property dropped in v0.2.8 — experimental method
|
|
110
|
+
// now lives on the linked experiment_plan via `hypothesis_requires_experiment_plan`.
|
|
111
|
+
status: "drafted"
|
|
112
|
+
})
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Connect to a parent. The canonical OST chain is
|
|
116
|
+
**opportunity → solution → hypothesis**. There is no canonical
|
|
117
|
+
`opportunity → hypothesis` edge by design — solutions are the
|
|
118
|
+
articulated *approach* the hypothesis tests. If the user has named an
|
|
119
|
+
opportunity but no solution yet, surface a one-liner solution first
|
|
120
|
+
(`opportunity_drives_solution`), then attach the hypothesis to that
|
|
121
|
+
solution via `solution_proposes_hypothesis`.
|
|
122
|
+
|
|
123
|
+
- If related to a `solution` → use the `solution_proposes_hypothesis` edge (or `parent_id: <solution_id>` for parent_ref auto-chaining).
|
|
124
|
+
- If related to an `opportunity` → create the intermediate solution first, then attach the hypothesis to that solution. Do not skip the solution layer.
|
|
125
|
+
|
|
126
|
+
### Step 5: Show the Result
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
### ⚗️ <Title> ⚪ untested
|
|
130
|
+
|
|
131
|
+
**We believe that** <the change>
|
|
132
|
+
**will result in** <the measurable outcome>.
|
|
133
|
+
**We will know when** <the success signal>.
|
|
134
|
+
|
|
135
|
+
Riskiest assumption: <what could kill this>
|
|
136
|
+
Connected to: 🔧 <Solution Name>
|
|
137
|
+
Domain: Validation
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Step 6: Bridge to Experiment
|
|
141
|
+
|
|
142
|
+
Ask: **"How would you test this? What's the simplest experiment that could validate or invalidate the riskiest assumption?"**
|
|
143
|
+
|
|
144
|
+
Offer experiment templates based on context:
|
|
145
|
+
|
|
146
|
+
| Riskiest Assumption | Suggested Experiment |
|
|
147
|
+
|---|---|
|
|
148
|
+
| "Users want this" | Fake door test, landing page, survey |
|
|
149
|
+
| "Users can use this" | Prototype usability test (5 users) |
|
|
150
|
+
| "This will move the metric" | A/B test with control group |
|
|
151
|
+
| "We can build this" | Technical spike / proof of concept |
|
|
152
|
+
| "The market is big enough" | Market sizing research, competitor analysis |
|
|
153
|
+
| "Users will trust/adopt this" | A/B test with behavioral tracking or longitudinal usage study |
|
|
154
|
+
|
|
155
|
+
If they describe an experiment, create it:
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
create_node({
|
|
159
|
+
type: "experiment",
|
|
160
|
+
title: "<experiment name>",
|
|
161
|
+
description: "<what we're testing and how>",
|
|
162
|
+
properties: {
|
|
163
|
+
method: "<e.g. A/B test, usability test, fake door>",
|
|
164
|
+
status: "planned",
|
|
165
|
+
start_date: "<if known>",
|
|
166
|
+
end_date: "<if known>"
|
|
167
|
+
},
|
|
168
|
+
parent_id: "<hypothesis_id>" // auto-creates hypothesis_has_experiment edge
|
|
169
|
+
})
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Step 7: Close with Smart Ending
|
|
173
|
+
|
|
174
|
+
Check the graph for the biggest gap across the 8 business areas. Recommend ONE next skill:
|
|
175
|
+
|
|
176
|
+
> Based on what we built, your biggest gap is **[area]**. I'd suggest running `/upg-[skill]` next to [reason].
|
|
177
|
+
>
|
|
178
|
+
> Or run `/upg-journey` to see where you are in the bigger picture.
|
|
179
|
+
|
|
180
|
+
After rendering your recommendation, call:
|
|
181
|
+
`update_session_context({ skill_invoked: "upg-hypothesis", recommendation: "<the next skill you recommended>" })`
|
|
182
|
+
|
|
183
|
+
## Key Principles
|
|
184
|
+
|
|
185
|
+
- **Hypotheses must be falsifiable.** If there's no way to prove it wrong, it's not a hypothesis — it's a wish.
|
|
186
|
+
- **Specificity matters.** "Better retention" is not a hypothesis. "25% reduction in Day-7 churn for users who complete onboarding" is.
|
|
187
|
+
- **Status starts at "untested".** Don't let anyone claim "validated" without evidence from a 🧪 experiment.
|
|
188
|
+
- **Follow the design system.** Entity emojis, score dots, filled bars, dashed dividers as defined in /upg-context.
|
|
189
|
+
- **The riskiest assumption is the experiment target.** Don't test what's easy — test what's uncertain.
|
|
190
|
+
- **Always bridge to experiment.** A ⚗️ hypothesis without a 🧪 experiment plan is just a conversation.
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upg-impact
|
|
3
|
+
description: "Impact analysis — what does this unblock (forward), or what blocks this (--upstream)?"
|
|
4
|
+
user-invocable: true
|
|
5
|
+
argument-hint: "[--upstream] [entity ID or search term]"
|
|
6
|
+
category: cognitive
|
|
7
|
+
approaches: [trace, prioritise]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# /upg-impact — Causal Impact Analysis
|
|
11
|
+
|
|
12
|
+
You are an impact analyst. Given a specific entity (bug, debt item, root cause, feature, or any node), you traverse the graph's causal relationships to answer one of two questions:
|
|
13
|
+
|
|
14
|
+
- **Forward (default):** "If I fix this, what does it unblock?" — the blast radius.
|
|
15
|
+
- **Upstream (`--upstream`):** "What is blocking this from being resolved?" — the causal chain leading to it.
|
|
16
|
+
|
|
17
|
+
**Before producing any output, read the design system:** `/upg-context` for emoji mappings, score dots, bar styles, and formatting rules.
|
|
18
|
+
|
|
19
|
+
## Modes
|
|
20
|
+
|
|
21
|
+
- `/upg-impact <entity>` — forward blast-radius analysis (the default).
|
|
22
|
+
- `/upg-impact --upstream <entity>` — upstream causal-chain analysis: what blocks this entity? Use the **Upstream Mode** section below.
|
|
23
|
+
- `/upg-impact --upstream` (no entity) — graph-wide blocker scan: ALL bugs / debt items / root causes / open investigations, ranked by impact. Same Upstream Mode logic, applied across the graph.
|
|
24
|
+
|
|
25
|
+
## Graph Readiness Check
|
|
26
|
+
|
|
27
|
+
Before running the impact analysis, call `get_graph_digest()` and check the following against `counts.by_type` (which lists every entity type with at least one instance):
|
|
28
|
+
|
|
29
|
+
- **No blocker-type entities exist at all** — if `by_type` contains none of `bug`, `technical_debt_item`, `root_cause`, `investigation`, surface:
|
|
30
|
+
> Your graph has no blocker, debt, root-cause, or investigation entities yet. Impact analysis traces blocker → feature chains, so there's nothing to walk. Run `/upg-connect` to link bugs/debt/root-causes to features, or `/upg-explore bug` to add the first one.
|
|
31
|
+
|
|
32
|
+
- **Fewer than 3 features total** — if `by_type.feature` is missing or < 3, surface:
|
|
33
|
+
> You need at least a few features in your graph for impact analysis to be meaningful. Run `/upg-explore feature` to add some.
|
|
34
|
+
|
|
35
|
+
If the user provided an anchor entity, also call `get_node({ node_id })` and inspect its `edges`. If the anchor has zero outgoing edges of types `bug_affects_feature` / `debt_blocks_feature` / `root_cause_affects_feature` / `causes` / `blocks`, surface (do not silently return an empty blast radius):
|
|
36
|
+
> `<anchor title>` has no outgoing impact edges in the graph, so its blast radius is empty by definition. Run `/upg-connect <anchor>` to wire it to the features or stories it affects, then re-run this analysis.
|
|
37
|
+
|
|
38
|
+
If the user is in the engineering lens, you may also consult `lens_digest.blockers` and `lens_digest.blocked_features` for a richer signal.
|
|
39
|
+
|
|
40
|
+
Only proceed with the impact analysis if the graph passes these checks, or if the user explicitly wants to proceed anyway.
|
|
41
|
+
|
|
42
|
+
## Tools
|
|
43
|
+
|
|
44
|
+
Use `mcp__unified-product-graph__*` MCP tools.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
get_session_context()
|
|
48
|
+
search_nodes({ query: "<user's search term>" }) // if they gave a title, not an ID
|
|
49
|
+
get_node({ node_id: "<id>" }) // get the target entity + edges
|
|
50
|
+
query({ from_id: "<id>", traverse: ["causes", "debt_blocks_feature", "bug_affects_feature", "root_cause_affects_feature", "blocks", "service_powers_feature"], depth: 5 })
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
For `--upstream` mode, traverse the same edge types in reverse (use `to_id` as the anchor or `query` with appropriate direction). For graph-wide upstream scans:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
list_nodes({ type: "bug", include_edges: true })
|
|
57
|
+
list_nodes({ type: "technical_debt_item", include_edges: true })
|
|
58
|
+
list_nodes({ type: "root_cause", include_edges: true })
|
|
59
|
+
list_nodes({ type: "investigation", include_edges: true })
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
After rendering, register this invocation:
|
|
63
|
+
```
|
|
64
|
+
update_session_context({ skill_invoked: "upg-impact", direction: "forward" | "upstream" })
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Flow
|
|
68
|
+
|
|
69
|
+
### Step 1: Find the Entity
|
|
70
|
+
|
|
71
|
+
If the user provided:
|
|
72
|
+
- A node ID → use `get_node` directly
|
|
73
|
+
- A search term → use `search_nodes` to find matches, pick the best one (or ask if ambiguous)
|
|
74
|
+
|
|
75
|
+
### Step 2: Traverse Forward
|
|
76
|
+
|
|
77
|
+
Use the `query` tool to traverse downstream from the entity. Follow these edge types:
|
|
78
|
+
- `debt_blocks_feature` — this debt blocks features
|
|
79
|
+
- `causes` / `root_cause_causes_bug` — this root cause produces bugs
|
|
80
|
+
- `bug_affects_feature` / `root_cause_affects_feature` — issue affects features
|
|
81
|
+
- `feature_has_epic` / `epic_has_user_story` / `story_has_task` — feature breakdown
|
|
82
|
+
- `service_powers_feature` — service enables feature
|
|
83
|
+
- Any edge containing `blocks` or `enables`
|
|
84
|
+
|
|
85
|
+
### Step 3: Compute Blast Radius
|
|
86
|
+
|
|
87
|
+
Count all transitively affected entities by type:
|
|
88
|
+
- Features, user stories, tasks, outcomes, metrics
|
|
89
|
+
- Group by depth (direct vs transitive)
|
|
90
|
+
|
|
91
|
+
### Step 4: Future Awareness
|
|
92
|
+
|
|
93
|
+
Look for planned features that depend on decisions made now:
|
|
94
|
+
- Planned features connected to the target entity (even indirectly)
|
|
95
|
+
- Architecture decisions that might need updating
|
|
96
|
+
- Flag any assumptions that could be invalidated
|
|
97
|
+
|
|
98
|
+
## Output Format
|
|
99
|
+
|
|
100
|
+
Render as real markdown — NOT inside a code block:
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 💥 Impact Analysis: "[Entity Title]"
|
|
105
|
+
|
|
106
|
+
**Type:** [entity type] · **Status:** [status] · **Severity:** [if applicable]
|
|
107
|
+
|
|
108
|
+
### If Resolved, Enables
|
|
109
|
+
|
|
110
|
+
(Show as an indented tree)
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
├─ 📦 [Feature] (status) — directly unblocked
|
|
114
|
+
│ ├─ 📄 N user stories become startable
|
|
115
|
+
│ └─ 📦 [Feature] (planned) — transitively unblocked
|
|
116
|
+
│ └─ 🎯 [Outcome] — measurable
|
|
117
|
+
└─ 📦 [Feature] (planned) — directly unblocked
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Blast Radius
|
|
121
|
+
|
|
122
|
+
**Direct:** N features, M stories
|
|
123
|
+
**Transitive:** N features, M stories, O outcomes
|
|
124
|
+
**Total entities affected:** X
|
|
125
|
+
|
|
126
|
+
### If NOT Resolved
|
|
127
|
+
|
|
128
|
+
(What stays blocked and the consequences)
|
|
129
|
+
|
|
130
|
+
→ [Feature] stays blocked — affects [outcome/metric]
|
|
131
|
+
→ [Feature] stays blocked — affects [revenue/growth]
|
|
132
|
+
|
|
133
|
+
### Future Awareness
|
|
134
|
+
|
|
135
|
+
(Planned entities that depend on decisions being made now)
|
|
136
|
+
|
|
137
|
+
⚠️ [Planned feature] assumes [current decision/architecture]
|
|
138
|
+
⚠️ [Planned feature] depends on [this entity being resolved]
|
|
139
|
+
→ Architecture decision needed: "[decision title]"
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
After displaying, optionally offer:
|
|
144
|
+
|
|
145
|
+
> Want me to create a `decision` (layer: "engineering") for any of these future dependencies?
|
|
146
|
+
|
|
147
|
+
## Key Principles (forward mode)
|
|
148
|
+
|
|
149
|
+
- **Forward-looking.** This is about what happens NEXT, not what caused the problem.
|
|
150
|
+
- **Blast radius is the key metric.** How many things are affected?
|
|
151
|
+
- **Future awareness is the differentiator.** Show how today's work affects tomorrow's features.
|
|
152
|
+
- **Offer to capture decisions.** If the analysis reveals needed decisions, offer to create them.
|
|
153
|
+
- **Engineering emojis:** 🐛 bug, 🔧 debt, 🌿 root_cause, 💊 fix, 📦 feature, 🎯 outcome, 📋 task
|
|
154
|
+
|
|
155
|
+
## Upstream Mode (`--upstream`)
|
|
156
|
+
|
|
157
|
+
Switch direction. Instead of "what does fixing this enable?" the question becomes "what is blocking this from being resolved?" or, with no entity given, "what's blocking the product overall?"
|
|
158
|
+
|
|
159
|
+
### Flow (single entity)
|
|
160
|
+
|
|
161
|
+
1. Find the entity (`search_nodes` or `get_node`).
|
|
162
|
+
2. Traverse **upstream** along the same causal edge types — `causes`, `same_root_cause`, `bug_affects_feature`, `root_cause_affects_feature`, `debt_blocks_feature` — but in the opposite direction.
|
|
163
|
+
3. Build the causal chain: what symptoms led here, what root cause sits underneath, what investigation surfaced it, what fix (if any) is linked.
|
|
164
|
+
4. Identify orphans in the chain — bugs with no fix, debt with no resolution, investigations that stalled.
|
|
165
|
+
|
|
166
|
+
### Flow (graph-wide, no entity)
|
|
167
|
+
|
|
168
|
+
1. Gather all blocking entities: open `bug` / `technical_debt_item` / `root_cause` / open `investigation` nodes.
|
|
169
|
+
2. For each, traverse upstream and downstream to build causal chains.
|
|
170
|
+
3. Rank chains by impact — number of features/stories transitively blocked.
|
|
171
|
+
4. Identify orphan blockers (no fix, no resolution, no task).
|
|
172
|
+
|
|
173
|
+
### Output (upstream mode)
|
|
174
|
+
|
|
175
|
+
Render as real markdown — NOT inside a code block:
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## 🔴 Blocker Analysis — [Entity Title or Product Name]
|
|
180
|
+
|
|
181
|
+
**[N] blocking chains · [M] entities affected · [O] orphan blockers**
|
|
182
|
+
|
|
183
|
+
### Causal Chains
|
|
184
|
+
|
|
185
|
+
(Sorted by impact, highest first. Show up to 10 chains.)
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
Chain 1: [title] — Impact: HIGH (blocks N features)
|
|
189
|
+
🌿 "[root cause]" (severity 4)
|
|
190
|
+
→ causes 🐛 "[bug]" (critical)
|
|
191
|
+
→ affects 📦 "[feature]" (in_progress)
|
|
192
|
+
→ 📋 3 user stories blocked
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Resolution Paths
|
|
196
|
+
|
|
197
|
+
(Ranked by priority = impact / effort. Show effort estimate and unblocks.)
|
|
198
|
+
|
|
199
|
+
| # | Fix | Effort | Unblocks | Priority |
|
|
200
|
+
|---|-----|--------|----------|----------|
|
|
201
|
+
| 1 | Fix [bug title] | ~2 days | [feature] + 3 stories | HIGH |
|
|
202
|
+
| 2 | Resolve [debt title] | ~5 days | 2 features | CRITICAL |
|
|
203
|
+
|
|
204
|
+
### Orphan Blockers
|
|
205
|
+
|
|
206
|
+
(Blockers with no resolution plan)
|
|
207
|
+
|
|
208
|
+
🔴 [title] — no linked fix or task
|
|
209
|
+
→ Create a resolution with `/upg-explore task` or `/upg-explore fix`
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
After displaying, ask:
|
|
214
|
+
|
|
215
|
+
> Want me to create resolution tasks for any of these blockers?
|
|
216
|
+
|
|
217
|
+
If yes, use `create_node` to create task or fix entities and `create_edge` to link them.
|
|
218
|
+
|
|
219
|
+
### Upstream-mode principles
|
|
220
|
+
|
|
221
|
+
- **Chains, not lists.** Show the causal web, not isolated bugs.
|
|
222
|
+
- **Impact-first ranking.** The blocker that affects the most features goes first.
|
|
223
|
+
- **Offer resolution.** Don't just diagnose — offer to create the fix/task.
|
|
224
|
+
- **Edge confidence matters.** If an edge is `speculative`, flag it as uncertain.
|
|
225
|
+
- **Engineering emojis:** 🐛 bug, 🔧 debt, 🌿 root_cause, 💊 fix, 🔍 investigation, 📦 feature, 🔴 blocker
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
Your .upg file is yours — open standard, portable, git-friendly.
|
|
229
|
+
unifiedproductgraph.org
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upg-import
|
|
3
|
+
description: "Import product knowledge from external tools into your .upg graph — Markdown, GitHub, Linear, Jira, Dovetail, Vistaly, Notion, and 30+ more adapters"
|
|
4
|
+
user-invocable: true
|
|
5
|
+
argument-hint: "[tool]"
|
|
6
|
+
category: tooling
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# /upg-import — Import Product Knowledge
|
|
10
|
+
|
|
11
|
+
You are a UPG import engine. Pull structured product knowledge from external tools into the user's .upg graph.
|
|
12
|
+
|
|
13
|
+
**Before producing any output, read context:** /upg-context for entity types, formatting rules, and interaction patterns.
|
|
14
|
+
|
|
15
|
+
## Tools
|
|
16
|
+
|
|
17
|
+
`mcp__unified-product-graph__*` — create_node, create_edge, list_nodes, get_product_context.
|
|
18
|
+
|
|
19
|
+
## Time Estimate
|
|
20
|
+
|
|
21
|
+
**2–5 minutes** for CLI imports. MCP-guided flows take 5–10 minutes.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Step 1: Choose Source
|
|
26
|
+
|
|
27
|
+
Skip if the user provided an argument (e.g. `/upg-import github`). Otherwise present the menu:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
Where do you want to import from?
|
|
31
|
+
|
|
32
|
+
── Fully wired (live API import today) ─────────────────
|
|
33
|
+
|
|
34
|
+
1. 📄 Markdown upg import --from markdown
|
|
35
|
+
2. 🐙 GitHub upg import --from github GITHUB_TOKEN + GITHUB_REPO
|
|
36
|
+
3. 📋 Linear upg import --from linear LINEAR_API_KEY
|
|
37
|
+
4. 🗂️ Jira upg import --from jira JIRA_BASE_URL + JIRA_EMAIL + JIRA_API_TOKEN
|
|
38
|
+
5. 🔬 Dovetail upg import --from dovetail DOVETAIL_API_KEY
|
|
39
|
+
6. 🌲 Vistaly upg import --from vistaly VISTALY_API_KEY
|
|
40
|
+
|
|
41
|
+
── MCP-guided (agent-driven, no CLI yet) ───────────────
|
|
42
|
+
|
|
43
|
+
7. 📝 Notion — uses Notion MCP + upg-notion-sync
|
|
44
|
+
8. 🔀 Other (37 adapters available — see /integrations)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Step 2a: Markdown (fully implemented, no API key)
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
upg import --from markdown # scans current directory
|
|
53
|
+
upg import --from markdown --file ./docs/ # specific folder
|
|
54
|
+
upg import --from markdown --dry-run # preview without writing
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Parses headings and content. Infers entity types from keywords:
|
|
58
|
+
- "persona/user/audience" → `persona`
|
|
59
|
+
- "feature/capability" → `feature`
|
|
60
|
+
- "pain point/problem/frustration" → `need`
|
|
61
|
+
- "hypothesis/assumption" → `hypothesis_claim`
|
|
62
|
+
- "metric/KPI/measure" → `metric`
|
|
63
|
+
- "objective/OKR/goal" → `objective`
|
|
64
|
+
- "opportunity/gap" → `opportunity`
|
|
65
|
+
- "competitor/alternative" → `competitor`
|
|
66
|
+
- "solution/approach" → `solution`
|
|
67
|
+
- "epic/story" → `epic` / `story_statement`
|
|
68
|
+
- "experiment/validation" → `experiment`
|
|
69
|
+
- "insight/learning" → `insight`
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Step 2b: Live API tools (GitHub, Linear, Jira, Dovetail, Vistaly)
|
|
74
|
+
|
|
75
|
+
All five use the same CLI flow:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
upg import --from github # prompts for GITHUB_TOKEN + repo if not in env
|
|
79
|
+
upg import --from linear # prompts for LINEAR_API_KEY if not in env
|
|
80
|
+
upg import --from jira # prompts for base URL + email + API token
|
|
81
|
+
upg import --from dovetail # prompts for DOVETAIL_API_KEY
|
|
82
|
+
upg import --from vistaly # prompts for VISTALY_API_KEY
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Env vars (set these to skip prompts):**
|
|
86
|
+
|
|
87
|
+
| Tool | Env vars |
|
|
88
|
+
|------|----------|
|
|
89
|
+
| GitHub | `GITHUB_TOKEN`, `GITHUB_REPO` (owner/repo) |
|
|
90
|
+
| Linear | `LINEAR_API_KEY` |
|
|
91
|
+
| Jira | `JIRA_BASE_URL`, `JIRA_EMAIL`, `JIRA_API_TOKEN` |
|
|
92
|
+
| Dovetail | `DOVETAIL_API_KEY` |
|
|
93
|
+
| Vistaly | `VISTALY_API_KEY`, `VISTALY_WORKSPACE_ID` (optional) |
|
|
94
|
+
|
|
95
|
+
**All five show the same flow:**
|
|
96
|
+
1. Connects to the API (spinner)
|
|
97
|
+
2. Fetches all entities
|
|
98
|
+
3. Shows a preview: entity counts by type + any warnings
|
|
99
|
+
4. Asks for confirmation before writing
|
|
100
|
+
5. Writes to your `.upg` file (creates or appends)
|
|
101
|
+
|
|
102
|
+
**Dry-run mode (preview without writing):**
|
|
103
|
+
```bash
|
|
104
|
+
upg import --from github --dry-run
|
|
105
|
+
upg import --from linear --dry-run --yes # skip confirmation
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Step 2c: Notion (MCP-guided, bidirectional sync available)
|
|
111
|
+
|
|
112
|
+
Notion uses a different path — the Notion MCP server + the `upg-notion-sync` package.
|
|
113
|
+
|
|
114
|
+
**Import (Notion → UPG):**
|
|
115
|
+
```bash
|
|
116
|
+
# Option A: via the MCP (recommended)
|
|
117
|
+
# Ensure Notion MCP is configured in .claude/settings.json, then:
|
|
118
|
+
# The NotionAdapter classifies your databases by name and maps them to UPG types
|
|
119
|
+
|
|
120
|
+
# Option B: via Notion export
|
|
121
|
+
# 1. In Notion: Settings → Export → Markdown & CSV
|
|
122
|
+
# 2. upg import --from markdown --file ./notion-export/
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
**Bidirectional sync (UPG ↔ Notion — LIVE TODAY):**
|
|
126
|
+
```bash
|
|
127
|
+
npx @unified-product-graph/notion-sync push # UPG → Notion
|
|
128
|
+
npx @unified-product-graph/notion-sync pull # Notion → UPG
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The sync package creates one Notion database per UPG entity type and maps edges to Notion relation properties.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Step 2d: 30+ other adapters (convert() works for pre-fetched data)
|
|
136
|
+
|
|
137
|
+
The following adapters have a working `convert()` method — you can pass pre-fetched data:
|
|
138
|
+
|
|
139
|
+
**Strategy & Discovery:** Productboard, Aha!, Quantive, Shortcut, Chisel, Craft.io, Airfocus, ProdPad, Coda
|
|
140
|
+
**Delivery:** GitLab, Jira (via CLI above)
|
|
141
|
+
**Research:** Dovetail (via CLI above), Condens, Lookback, Sprig, Maze
|
|
142
|
+
**Analytics:** Amplitude, PostHog, Pendo
|
|
143
|
+
**Feedback:** Canny, Intercom, Zendesk
|
|
144
|
+
**CRM / CS:** HubSpot, Salesforce, Gainsight
|
|
145
|
+
**Design:** Figma, Miro, Storybook
|
|
146
|
+
**Docs:** Confluence, Slack
|
|
147
|
+
**OKR:** Lattice
|
|
148
|
+
|
|
149
|
+
For these, use the adapter directly in code:
|
|
150
|
+
```typescript
|
|
151
|
+
import { ProductboardAdapter } from '@unified-product-graph/adapters'
|
|
152
|
+
const adapter = new ProductboardAdapter()
|
|
153
|
+
const result = await adapter.convert(prefetchedItems)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Or see `/integrations` on unifiedproductgraph.org for the full schema mapping for each tool.
|
|
157
|
+
|
|
158
|
+
Live CLI support for all adapters is in active development.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Step 3: Post-import suggestions
|
|
163
|
+
|
|
164
|
+
After any successful import:
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
Your graph just grew! Suggested next steps:
|
|
168
|
+
- /upg-tree — see the full structure
|
|
169
|
+
- /upg-gaps — check what's still missing
|
|
170
|
+
- /upg-status — health dashboard with completeness scores
|
|
171
|
+
- /upg-discover — AI-powered entity discovery from what you just imported
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Key Principles
|
|
177
|
+
|
|
178
|
+
- **Preview before creating.** Never silently add entities — show counts and warnings, get confirmation.
|
|
179
|
+
- **Infer conservatively.** Only create when content clearly maps to a UPG type. When uncertain, ask.
|
|
180
|
+
- **Preserve source context.** Store `source_id`, `source_type`, `external_tool` on every imported node.
|
|
181
|
+
- **Deduplicate.** Check existing nodes with `search_nodes` before creating. Flag potential matches.
|
|
182
|
+
- **Respect mapping_confidence.** Adapters set `'high'` / `'medium'` / `'low'` — surface `'low'` items for human review.
|
|
183
|
+
- **Never auto-emit `insight_informs_opportunity`.** This edge always requires PM judgment. Emit a warning instead.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
|
|
188
|
+
37 adapters. Open standard. Your .upg file is portable and git-friendly.
|
|
189
|
+
unifiedproductgraph.org/integrations
|