@unified-product-graph/mcp-server 0.8.1 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +1 -1
  3. package/TOOLS.md +79 -16
  4. package/dist/index.js +1440 -290
  5. package/dist/index.js.map +1 -1
  6. package/dist/tools-manifest.json +197 -82
  7. package/package.json +1 -1
  8. package/scripts/claudemd-snippet.md +7 -7
  9. package/scripts/install-skills.sh +2 -2
  10. package/skills/upg/SKILL.md +41 -41
  11. package/skills/{upg-gaps → upg-check-gaps}/SKILL.md +40 -43
  12. package/skills/{upg-schema-health → upg-check-schema}/SKILL.md +7 -7
  13. package/skills/{upg-schema-evolve → upg-check-schema-coverage}/SKILL.md +12 -12
  14. package/skills/{upg-schema-edges → upg-check-schema-edges}/SKILL.md +3 -3
  15. package/skills/{upg-schema-consolidate → upg-check-schema-merge}/SKILL.md +5 -5
  16. package/skills/upg-context/SKILL.md +96 -72
  17. package/skills/upg-context-intelligence/SKILL.md +23 -27
  18. package/skills/upg-design-system/SKILL.md +21 -26
  19. package/skills/{upg-verify → upg-find-untracked}/SKILL.md +7 -12
  20. package/skills/{upg-rollback → upg-fix-rollback}/SKILL.md +6 -12
  21. package/skills/{upg-migrate → upg-fix-types}/SKILL.md +5 -9
  22. package/skills/upg-link/SKILL.md +125 -0
  23. package/skills/{upg-discover → upg-new-discovery}/SKILL.md +42 -58
  24. package/skills/{upg-capture → upg-new-from-session}/SKILL.md +13 -15
  25. package/skills/{upg-template → upg-new-from-template}/SKILL.md +8 -12
  26. package/skills/{upg-init → upg-new-graph}/SKILL.md +50 -82
  27. package/skills/{upg-hypothesis → upg-new-hypothesis}/SKILL.md +27 -36
  28. package/skills/{upg-launch → upg-new-launch}/SKILL-DETAIL.md +36 -92
  29. package/skills/{upg-launch → upg-new-launch}/SKILL.md +8 -18
  30. package/skills/{upg-okr → upg-new-okr}/SKILL-DETAIL.md +28 -46
  31. package/skills/{upg-okr → upg-new-okr}/SKILL.md +3 -3
  32. package/skills/{upg-persona → upg-new-persona}/SKILL.md +35 -67
  33. package/skills/{upg-research → upg-new-research}/SKILL.md +25 -33
  34. package/skills/{upg-schema-update → upg-new-schema-type}/SKILL.md +2 -2
  35. package/skills/{upg-strategy → upg-new-strategy}/SKILL.md +21 -27
  36. package/skills/upg-prioritise/SKILL.md +4 -4
  37. package/skills/upg-reflect/SKILL.md +7 -7
  38. package/skills/{upg-feedback → upg-send-feedback}/SKILL.md +30 -51
  39. package/skills/{upg-diff → upg-show-diff}/SKILL.md +6 -12
  40. package/skills/{upg-inspect → upg-show-entity}/SKILL.md +7 -9
  41. package/skills/{upg-impact → upg-show-impact}/SKILL.md +11 -15
  42. package/skills/{upg-journey → upg-show-journey}/SKILL.md +31 -32
  43. package/skills/{upg-analytics → upg-show-metrics}/SKILL.md +9 -12
  44. package/skills/{upg-schema-changelog → upg-show-schema-changelog}/SKILL.md +5 -5
  45. package/skills/{upg-status → upg-show-status}/SKILL.md +39 -40
  46. package/skills/{upg-tree → upg-show-tree}/SKILL.md +15 -15
  47. package/skills/{upg-export → upg-sync-export}/SKILL.md +10 -13
  48. package/skills/{upg-import → upg-sync-import}/SKILL.md +7 -13
  49. package/skills/{upg-pull → upg-sync-pull}/SKILL-DETAIL.md +13 -17
  50. package/skills/{upg-pull → upg-sync-pull}/SKILL.md +3 -3
  51. package/skills/{upg-push → upg-sync-push}/SKILL-DETAIL.md +4 -10
  52. package/skills/{upg-push → upg-sync-push}/SKILL.md +4 -4
  53. package/skills/{upg-snapshot → upg-sync-snapshot}/SKILL.md +2 -6
  54. package/skills/upg-trace/SKILL.md +7 -7
  55. package/skills/{upg-workspace → upg-use-workspace}/SKILL.md +8 -14
  56. package/skills/{upg-run → upg-walk-playbook}/SKILL.md +10 -10
  57. package/skills/upg-walk-region/SKILL-DETAIL.md +320 -0
  58. package/skills/upg-walk-region/SKILL.md +89 -0
  59. package/skills/upg-connect/SKILL.md +0 -167
  60. package/skills/upg-explore/SKILL-DETAIL.md +0 -481
  61. package/skills/upg-explore/SKILL.md +0 -297
@@ -1,12 +1,12 @@
1
1
  ---
2
- name: upg-push
2
+ name: upg-sync-push
3
3
  description: "Push your local product graph to The Product Creator cloud"
4
4
  user-invocable: true
5
5
  argument-hint: "[product-name]"
6
6
  category: tooling
7
7
  ---
8
8
 
9
- # /upg-push: Push Local Graph to Cloud
9
+ # /upg-sync-push: Push Local Graph to Cloud
10
10
 
11
11
  You are a Unified Product Graph sync engine. Your job is to push the user's local `.upg` graph to The Product Creator cloud, enabling visual canvas, framework trees, team collaboration, and all the features that go beyond what the CLI can offer.
12
12
 
@@ -63,7 +63,7 @@ list_nodes({ limit: 200 })
63
63
  If the local graph is empty or has no product:
64
64
  ```
65
65
  Your local graph is empty; nothing to push yet.
66
- Run /upg-init to bootstrap your first product graph.
66
+ Run /upg-new-graph to bootstrap your first product graph.
67
67
  ```
68
68
 
69
69
  ### Step 2: Check Cloud Connection
@@ -83,7 +83,7 @@ To push your graph to The Product Creator, you need an API key.
83
83
 
84
84
  In .mcp.json, update the upg-cloud server with your API key.
85
85
 
86
- Once configured, run /upg-push again.
86
+ Once configured, run /upg-sync-push again.
87
87
  ```
88
88
 
89
89
  ### Step 3: Check for .upg-sync File
@@ -1,12 +1,12 @@
1
1
  ---
2
- name: upg-snapshot
2
+ name: upg-sync-snapshot
3
3
  description: "Save a named checkpoint of your product graph: version your thinking"
4
4
  user-invocable: true
5
5
  argument-hint: "[message]"
6
6
  category: tooling
7
7
  ---
8
8
 
9
- # /upg-snapshot: Version Your Thinking
9
+ # /upg-sync-snapshot: Version Your Thinking
10
10
 
11
11
  You are a Unified Product Graph versioning tool. Your job is to save a named checkpoint of the product graph; a git commit plus version metadata in the .upg file. Fast, no questions beyond the message.
12
12
 
@@ -102,7 +102,3 @@ Rollback: git checkout HEAD~1 -- product.upg
102
102
  - **Silent on success.** Don't explain what versioning is. Just confirm.
103
103
  - **Graceful on failure.** If git isn't available, still patch the version and say so.
104
104
  - **No graph entity mutations.** This skill versions the file; it does not create or modify graph entities.
105
-
106
- ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
107
- Your `.upg` file is yours: open standard, portable, git-friendly.
108
- unifiedproductgraph.org
@@ -45,9 +45,9 @@ These are examples. The user may want to trace any path in the graph; canonical
45
45
 
46
46
  Before starting the trace, call `get_graph_digest()` and `resolve_edge_for_pair({ source_type, target_type })` for the first hop of the requested path. If:
47
47
  - The canonical edge for the first hop doesn't exist in the graph (zero matching edges): surface:
48
- > Your graph has no `[source_type] → [target_type]` connections yet; the trace would stop at hop 1. Run `/upg-connect` or `/upg-explore` to add the missing links first.
48
+ > Your graph has no `[source_type] → [target_type]` connections yet; the trace would stop at hop 1. Run `/upg-link` or `/upg-walk-region` to add the missing links first.
49
49
  - The graph has fewer than 10 nodes total: surface:
50
- > Your graph is quite sparse. Traces are most useful once you have at least a few connected entities. Run `/upg-init` or `/upg-discover` to build out the foundation.
50
+ > Your graph is quite sparse. Traces are most useful once you have at least a few connected entities. Run `/upg-new-graph` or `/upg-new-discovery` to build out the foundation.
51
51
 
52
52
  If the user wants to proceed despite sparse data, proceed, but note "limited graph depth" in the output.
53
53
 
@@ -152,7 +152,7 @@ has no documented route to a potential solution.
152
152
 
153
153
  For each gap, offer:
154
154
  - "Want me to create a stub opportunity node here so the chain is complete?"
155
- - "Want to flag this for `/upg-gaps` to include in a full graph gap analysis?"
155
+ - "Want to flag this for `/upg-check-gaps` to include in a full graph gap analysis?"
156
156
 
157
157
  ### Step 6: Capture What the Trace Revealed
158
158
 
@@ -173,10 +173,10 @@ Always confirm before writing. Never silently create nodes or edges.
173
173
 
174
174
  Pick ONE next move based on what the trace found:
175
175
 
176
- - **If the path was complete and well-connected:** "Clean chain from [anchor] to [destination]. Want to `/upg-snapshot` to preserve this as a known-good state?"
177
- - **If one or more gaps were found:** "Found [N] gap(s) in the chain. Want to run `/upg-gaps` for a full structural gap audit across the product?"
176
+ - **If the path was complete and well-connected:** "Clean chain from [anchor] to [destination]. Want to `/upg-sync-snapshot` to preserve this as a known-good state?"
177
+ - **If one or more gaps were found:** "Found [N] gap(s) in the chain. Want to run `/upg-check-gaps` for a full structural gap audit across the product?"
178
178
  - **If the trace revealed a strategic disconnect:** "The chain breaks before it reaches [destination]. That might mean the strategy isn't wired to execution yet. Want to run `/upg-reflect` to examine why?"
179
- - **If a hypothesis or experiment was the anchor and no learning exists:** "This hypothesis has no learning yet; the experiment hasn't landed. Want to run `/upg-hypothesis` to check on its test design?"
179
+ - **If a hypothesis or experiment was the anchor and no learning exists:** "This hypothesis has no learning yet; the experiment hasn't landed. Want to run `/upg-new-hypothesis` to check on its test design?"
180
180
  - **If the user discovered they want to walk a different path:** "Want to start a new trace from a different anchor?"
181
181
 
182
182
  After rendering your recommendation, call:
@@ -194,4 +194,4 @@ After rendering your recommendation, call:
194
194
 
195
195
  Trace is one of the 5 canonical UPG approaches (`get_approach({ approach_id: "trace" })`). The approach had no skill home; the MCP `trace` tool existed but no conversational surface orchestrated a guided, multi-hop walk through the graph with gap detection and capture. This skill closes that gap.
196
196
 
197
- It is the only canonical entry point for the Trace approach in the user-invocable surface. Other skills use tracing implicitly (a good `/upg-impact` walks downstream edges), but `/upg-trace` is where the user goes when they explicitly want to plot a route; to test whether the product graph is coherent from anchor to destination.
197
+ It is the only canonical entry point for the Trace approach in the user-invocable surface. Other skills use tracing implicitly (a good `/upg-show-impact` walks downstream edges), but `/upg-trace` is where the user goes when they explicitly want to plot a route; to test whether the product graph is coherent from anchor to destination.
@@ -1,12 +1,12 @@
1
1
  ---
2
- name: upg-workspace
2
+ name: upg-use-workspace
3
3
  description: "Manage your UPG workspace: list products, switch between them, add new ones"
4
4
  user-invocable: true
5
5
  argument-hint: "[list|switch|add|init]"
6
6
  category: tooling
7
7
  ---
8
8
 
9
- # /upg-workspace: Manage Your Product Workspace
9
+ # /upg-use-workspace: Manage Your Product Workspace
10
10
 
11
11
  Manage multiple product graphs. Fast, direct, sub-commands keep it tight. Read `/upg-context` before producing output.
12
12
 
@@ -27,8 +27,8 @@ Check if `.upg/workspace.json` exists (Bash). Call `list_local_products` for ent
27
27
  1. ● My SaaS (active); 42 entities, mvp stage
28
28
  2. ○ Client Project; 12 entities, idea stage
29
29
  3. ○ Internal Tools; 8 entities, idea stage
30
- Switch: /upg-workspace switch <number>
31
- Add: /upg-workspace add
30
+ Switch: /upg-use-workspace switch <number>
31
+ Add: /upg-use-workspace add
32
32
  ```
33
33
 
34
34
  **Single-file mode** (no workspace.json, 1+ files):
@@ -36,9 +36,9 @@ Check if `.upg/workspace.json` exists (Bash). Call `list_local_products` for ent
36
36
  ## Your UPG Workspace
37
37
  📄 Single-file mode (product.upg)
38
38
  ● My SaaS; 42 entities, mvp stage
39
- Want multiple products? Run /upg-workspace init
39
+ Want multiple products? Run /upg-use-workspace init
40
40
  ```
41
- If multiple loose files, number them and suggest `init`. If zero files, point to `/upg-init`.
41
+ If multiple loose files, number them and suggest `init`. If zero files, point to `/upg-new-graph`.
42
42
 
43
43
  ---
44
44
 
@@ -69,8 +69,8 @@ If multiple loose files, number them and suggest `init`. If zero files, point to
69
69
 
70
70
  Upgrades loose .upg files to `.upg/` workspace mode.
71
71
 
72
- - If workspace.json already exists: "You're already in workspace mode. Run `/upg-workspace` to see your products." Done.
73
- - If no .upg files exist: "No .upg files found. Run `/upg-init` first." Done.
72
+ - If workspace.json already exists: "You're already in workspace mode. Run `/upg-use-workspace` to see your products." Done.
73
+ - If no .upg files exist: "No .upg files found. Run `/upg-new-graph` first." Done.
74
74
 
75
75
  Otherwise:
76
76
  1. `mkdir -p .upg` and `mv *.upg .upg/` for each file.
@@ -95,9 +95,3 @@ Otherwise:
95
95
  - Show entity count (nodes) and stage for each product.
96
96
  - No unnecessary questions: `list` and `switch` need zero extra input.
97
97
  - Standard footer on every output:
98
-
99
- ```
100
- ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
101
- Your .upg file is yours: open standard, portable, git-friendly.
102
- unifiedproductgraph.org
103
- ```
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: upg-run
2
+ name: upg-walk-playbook
3
3
  description: "Run any UPG playbook: generic driver for canonical playbooks"
4
4
  user-invocable: true
5
5
  argument-hint: "[playbook-id] (e.g. playbook:strategy-outcomes, playbook:business-gtm-growth, playbook:experience-design-brand)"
@@ -7,23 +7,23 @@ category: cognitive
7
7
  approaches: [plan]
8
8
  ---
9
9
 
10
- # /upg-run: Generic Playbook Driver
10
+ # /upg-walk-playbook: Generic Playbook Driver
11
11
 
12
12
  You are a UPG playbook runner. You take any canonical `UPGPlaybook` record from `@unified-product-graph/core` and walk the user through it; without a hand-crafted skill per playbook.
13
13
 
14
- > Plan called this `/upg-explore` but that name is taken by the single-entity creation skill. `/upg-run` is the playbook driver.
14
+ > Plan called this `/upg-walk-region` but that name is taken by the single-entity creation skill. `/upg-walk-playbook` is the playbook driver.
15
15
 
16
16
  **Before producing any output, read the design system:** `/upg-context` for emoji mappings, formatting rules, and shared interaction patterns.
17
17
 
18
18
  ## How this skill works
19
19
 
20
- Unlike hand-crafted skills, `/upg-run` reads playbook structure at runtime. You do not carry domain-specific conversational voice for each playbook; instead, each step's `prompt_hint` and `name` are your script.
20
+ Unlike hand-crafted skills, `/upg-walk-playbook` reads playbook structure at runtime. You do not carry domain-specific conversational voice for each playbook; instead, each step's `prompt_hint` and `name` are your script.
21
21
 
22
22
  For `kind: 'domain_guide'` steps, the runtime expands them via `DomainUsageGuide[domain_id]`; you then walk the user through the creation sequence, surfacing the domain's anti-patterns and required cross-domain bridges.
23
23
 
24
24
  ## Argument parsing
25
25
 
26
- The user invokes this skill with a playbook id, e.g. `/upg-run playbook:business-gtm-growth`.
26
+ The user invokes this skill with a playbook id, e.g. `/upg-walk-playbook playbook:business-gtm-growth`.
27
27
 
28
28
  If no argument is given, list the canonical ids and ask the user to pick one. Use `mcp__unified-product-graph__list_playbooks` (optionally with `canonical_only: true` to surface the 10 region defaults). v0.3.0 ships 12 playbooks across 10 regions:
29
29
 
@@ -68,7 +68,7 @@ Create each of `step.entity_types` in order. Use `batch_create_nodes` with `pare
68
68
 
69
69
  #### `kind: 'sub_sequence'`
70
70
 
71
- Recursively run `/upg-run` with `step.sub_sequence_id` (which is namespace-prefixed: `playbook:*` or `technique:*`).
71
+ Recursively run `/upg-walk-playbook` with `step.sub_sequence_id` (which is namespace-prefixed: `playbook:*` or `technique:*`).
72
72
 
73
73
  ### 4. Use the step's labels
74
74
 
@@ -104,7 +104,7 @@ When the domain guide's `anti_patterns` match what the user is doing, name it. G
104
104
 
105
105
  ## Boundaries
106
106
 
107
- Playbook definitions are read-only from `@unified-product-graph/core`; use step metadata as the script rather than hand-crafting voice per playbook. The keeper skills (`/upg-persona`, `/upg-research`) keep their own SKILL.md for narrative synthesis the generic driver can't match. Single-entity creation is `/upg-explore`'s job.
107
+ Playbook definitions are read-only from `@unified-product-graph/core`; use step metadata as the script rather than hand-crafting voice per playbook. The keeper skills (`/upg-new-persona`, `/upg-new-research`) keep their own SKILL.md for narrative synthesis the generic driver can't match. Single-entity creation is `/upg-walk-region`'s job.
108
108
 
109
109
  ## End of run
110
110
 
@@ -119,8 +119,8 @@ If the final step (or any completed step) declared `next_sequence_on_gap` **and*
119
119
 
120
120
  > "Done with `playbook:strategy-outcomes`. I noticed discovery research isn't modelled yet; want me to run `playbook:discovery-research-validation` next?"
121
121
 
122
- The user picks yes/no/different playbook. On yes, invoke `/upg-run <chained-id>` directly.
122
+ The user picks yes/no/different playbook. On yes, invoke `/upg-walk-playbook <chained-id>` directly.
123
123
 
124
- If no chain is declared, fall back to suggesting based on graph gaps from `/upg-gaps`.
124
+ If no chain is declared, fall back to suggesting based on graph gaps from `/upg-check-gaps`.
125
125
 
126
- Invite the user to `/upg-status` or `/upg-gaps` to see what changed.
126
+ Invite the user to `/upg-show-status` or `/upg-check-gaps` to see what changed.
@@ -0,0 +1,320 @@
1
+ ---
2
+ name: upg-explore-detail
3
+ description: "Full property schemas and edge type reference for /upg-walk-region"
4
+ ---
5
+
6
+ # /upg-walk-region: Property Schemas & Edge Types (Detail)
7
+
8
+ This file is an **illustrative reference**, not the spec. It is loaded on demand by /upg-walk-region. The authoritative properties and valid children for any type come from **`get_entity_schema({ type: <type> })`** at runtime; the authoritative lifecycle phases (the top-level `status` enum) come from **`get_lifecycle({ entity_type: <type> })`** (not `get_entity_schema`); and the canonical edge for any pair comes from **`resolve_edge_for_pair({ source_type, target_type })`**. Where this file disagrees with those live calls, the live calls win. Use the blocks below to shape your questions, then confirm against the schema before writing.
9
+
10
+ ## Full Property Schemas
11
+
12
+ When creating an entity, actively prompt for the key properties. Do not just set title and description.
13
+
14
+ > **Two conventions these schemas follow (and you must too):**
15
+ > 1. **Lifecycle `status` is a TOP-LEVEL field on the node, not a property.** Where a block below shows `status (top-level ...)`, pass it as a top-level `status:` argument to `create_node`, alongside (not inside) `properties`. The shown enum is illustrative — confirm the live phase set with `get_lifecycle({ entity_type: <type> })`, which is the source of truth (`get_entity_schema` does not return it). Note: a `*_status` PROPERTY (e.g. `objective_status`, `kr_status`) is a SEPARATE enum field that lives inside `properties` and is distinct from the top-level lifecycle `status` — never copy one into the other.
16
+ > 2. **Assessments (`reach`, `frequency`, `pain`, `impact`, `confidence`, `effort`, `importance`, `current_satisfaction`) are `{ value, label }` objects on a 1-5 scale, NOT bare integers.** Where a block shows `1-5`, write `{ value: <1-5>, label: "<word>" }`.
17
+
18
+ ### outcome
19
+ ```json
20
+ {
21
+ "timeline": "When this should be achieved"
22
+ }
23
+ ```
24
+ Ask: "What's the timeline for this outcome?"
25
+
26
+ ### metric (KPI)
27
+ ```json
28
+ {
29
+ "designation": "kpi",
30
+ "current_value": 0,
31
+ "target_value": 100,
32
+ "unit": "%, users, seconds, etc.",
33
+ "range_min": 0,
34
+ "range_max": 100
35
+ }
36
+ ```
37
+ Ask: "What's the current value? What's the target? What unit?" (KPIs are `metric` nodes with `designation: "kpi"`; the `kpi` type was consolidated into `metric` in v0.1.0.)
38
+
39
+ ### objective
40
+ ```json
41
+ {
42
+ "timeframe": "Q1 2026, H2 2026, etc.",
43
+ "objective_status": "active | achieved | deferred",
44
+ "status (top-level lifecycle)": "draft | active | achieved | missed | deferred"
45
+ }
46
+ ```
47
+
48
+ ### key_result
49
+ ```json
50
+ {
51
+ "current_value": 0,
52
+ "target_value": 100,
53
+ "unit": "metric unit",
54
+ "kr_status": "on_track | at_risk | behind | achieved",
55
+ "status (top-level lifecycle)": "on_track | at_risk | behind | achieved"
56
+ }
57
+ ```
58
+
59
+ ### opportunity
60
+ ```json
61
+ {
62
+ "status (top-level)": "identified | validated | deferred",
63
+ "reach": "{ value: 1-5, label }",
64
+ "frequency": "{ value: 1-5, label }",
65
+ "pain": "{ value: 1-5, label }"
66
+ }
67
+ ```
68
+ Ask: "How many people does this affect (reach 1-5)? How often (frequency 1-5)? How painful (1-5)?"
69
+
70
+ ### solution
71
+ ```json
72
+ {
73
+ "status (top-level)": "proposed | in_progress | shipped | deferred",
74
+ "reach": "{ value: 1-5, label }",
75
+ "impact": "{ value: 1-5, label }",
76
+ "confidence": "{ value: 1-5, label }",
77
+ "effort": "{ value: 1-5, label }",
78
+ "rice_score": "(reach x impact x confidence) / effort"
79
+ }
80
+ ```
81
+ Ask: "Let's RICE-score this. Reach (1-5)? Impact (1-5)? Confidence (1-5)? Effort (1-5)?"
82
+
83
+ ### experiment
84
+ ```json
85
+ {
86
+ "method": "Description of the test method",
87
+ "status (top-level)": "planned | running | analysing | done",
88
+ "start_date": "ISO date",
89
+ "end_date": "ISO date"
90
+ }
91
+ ```
92
+ (For the hypothesis test chain, prefer `experiment_plan` -> `experiment_run`; `experiment` is the standalone test unit. There is no canonical `hypothesis -> experiment` edge.)
93
+
94
+ ### learning
95
+ ```json
96
+ {
97
+ "result": "What happened",
98
+ "metric": "What was measured",
99
+ "result_value": 0,
100
+ "confidence_impact": "strengthens | weakens | neutral"
101
+ }
102
+ ```
103
+
104
+ ### competitor
105
+ ```json
106
+ {
107
+ "positioning": "How they position themselves",
108
+ "pricing_model": "Their pricing approach",
109
+ "strengths": ["What they do well"],
110
+ "weaknesses": ["Where they fall short"],
111
+ "website": "URL"
112
+ }
113
+ ```
114
+
115
+ ### feature
116
+ ```json
117
+ {
118
+ "status (top-level)": "proposed | in_progress | shipped | archived"
119
+ }
120
+ ```
121
+
122
+ ### user_story
123
+ ```json
124
+ {
125
+ "as_a": "persona name",
126
+ "i_want_to": "action",
127
+ "so_that": "outcome",
128
+ "effort": 0
129
+ }
130
+ ```
131
+ (`user_story` is lifecycle-free; it has no `status` phases. Track delivery state on the parent epic or via task entities, not a story `status`.)
132
+
133
+ ### need
134
+ ```json
135
+ {
136
+ "valence": "pain | gap | constraint",
137
+ "frequency": "{ value: 1-5, label }",
138
+ "severity": "{ value: 1-5, label }"
139
+ }
140
+ ```
141
+ Ask: "How often does this happen (1-5)? How bad is it (1-5)? Is this a pain, gap, or constraint?" (The old `pain_point` type was consolidated into `need` with `valence: "pain"` in v0.1.0. `frequency` and `severity` are assessments; pass `{ value, label }`.)
142
+
143
+ ### research_study
144
+ ```json
145
+ {
146
+ "method": "interview | usability | survey | diary | analytics",
147
+ "status (top-level)": "planned | in_progress | analysing | complete",
148
+ "participant_count": 0
149
+ }
150
+ ```
151
+
152
+ ### insight (research insight)
153
+ ```json
154
+ {
155
+ "insight_level": "pattern | finding | actionable | strategic",
156
+ "confidence": "{ value: 1-5, label }",
157
+ "source_method": "method from the study",
158
+ "evidence_count": 0,
159
+ "status (top-level)": "proposed | validated | applied | retired"
160
+ }
161
+ ```
162
+ (The old `research_insight`, `finding`, and `ux_insight` types were all consolidated into `insight` in v0.1.0.)
163
+
164
+ ### business_model
165
+ ```json
166
+ {
167
+ "canvas_type": "lean | bmc | custom",
168
+ "customer_segments": ["Who you serve"],
169
+ "channels": ["How you reach them"],
170
+ "key_activities": ["What you do"],
171
+ "key_resources": ["What you need"],
172
+ "key_partners": ["Who helps you"],
173
+ "status (top-level)": "drafted | testing | validated | invalidated | pivoted"
174
+ }
175
+ ```
176
+ Ask: "What type of canvas is this; lean, BMC, or custom? Who are the customer segments? What are the key activities?"
177
+
178
+ ### value_proposition
179
+ ```json
180
+ {
181
+ "for_segment": "Which customer segment this serves",
182
+ "gains": ["What gains you create"],
183
+ "pain_relievers": ["What pains you relieve"],
184
+ "products_and_services": ["What you offer"],
185
+ "differentiator": "Why this is unique vs. alternatives",
186
+ "status (top-level)": "drafted | testing | validated | invalidated"
187
+ }
188
+ ```
189
+ Ask: "Which customer segment is this for? What gains does it create? What pains does it relieve? What makes it different from alternatives?"
190
+
191
+ ### gtm_strategy
192
+ ```json
193
+ {
194
+ "target_market": "Primary market",
195
+ "motion": "product_led | sales_led | community_led | hybrid",
196
+ "channels": ["Distribution channels"],
197
+ "timeline": "Launch timeline",
198
+ "success_metrics": ["How you'll measure success"],
199
+ "status (top-level)": "planning | active | paused | completed | sunset"
200
+ }
201
+ ```
202
+ Ask: "What's the target market? Is this product-led, sales-led, or community-led? What channels will you use?"
203
+
204
+ ### ideal_customer_profile
205
+ ```json
206
+ {
207
+ "company_size": "1-10 | 11-50 | 51-200 | 201-1000 | 1000+",
208
+ "industry": "Target industry",
209
+ "budget_range": "Typical budget",
210
+ "buying_triggers": ["What causes them to look for a solution"],
211
+ "disqualifiers": ["Red flags; who is NOT a fit"],
212
+ "decision_makers": ["Roles involved in the buying decision"]
213
+ }
214
+ ```
215
+ Ask: "What size company is the ideal fit? What industry? What triggers them to start looking for a solution like yours?"
216
+
217
+ ### positioning
218
+ ```json
219
+ {
220
+ "for_whom": "Target audience",
221
+ "who_need": "Their primary need",
222
+ "our_product_is": "Category or frame",
223
+ "that_provides": "Key benefit",
224
+ "unlike": "Primary alternative",
225
+ "we_differentiate_by": "Unique differentiator",
226
+ "framework": "april_dunford | moore | custom"
227
+ }
228
+ ```
229
+ Ask: "Let's use a positioning statement. For whom? Who need what? What category is your product? How do you differentiate?"
230
+
231
+ ### user_journey
232
+ ```json
233
+ {
234
+ "persona": "Which persona takes this journey",
235
+ "scenario": "The specific context or trigger",
236
+ "stages": ["awareness", "consideration", "decision", "onboarding", "retention"],
237
+ "emotional_arc": "How feelings change across stages",
238
+ "status (top-level)": "draft | review | published | archived"
239
+ }
240
+ ```
241
+ Ask: "Which persona takes this journey? What's the scenario? What stages does it cover?"
242
+
243
+ ### decision (architecture / design / product)
244
+ ```json
245
+ {
246
+ "layer": "engineering | design | product",
247
+ "context": "Why this decision was needed",
248
+ "decision": "What was decided",
249
+ "alternatives_considered": ["What else was evaluated"],
250
+ "consequences": ["Trade-offs and implications"],
251
+ "status (top-level)": "proposed | reviewing | approved | rejected | deprecated",
252
+ "decided_by": "Who made the decision",
253
+ "decided_on": "ISO date"
254
+ }
255
+ ```
256
+ Ask: "What's the context; why was this decision needed? What was decided? What alternatives were considered? Which layer does this belong to; engineering, design, or product?" (`architecture_decision`, `design_decision`, and `product_decision` were consolidated into the single `decision` type with a `layer` property in v0.2.0.)
257
+
258
+ ### growth_loop
259
+ ```json
260
+ {
261
+ "loop_type": "viral | content | paid | product",
262
+ "trigger": "What starts the loop",
263
+ "action": "What the user does",
264
+ "output": "What the action produces",
265
+ "reinvestment": "How the output feeds back into the trigger",
266
+ "time_to_complete": "How long one cycle takes"
267
+ }
268
+ ```
269
+ Ask: "What type of loop; viral, content, paid, or product? What triggers it? What action does the user take? How does the output feed back into the trigger?" (`growth_loop` is lifecycle-free; no `status` phases.)
270
+
271
+ ### pricing_strategy
272
+ ```json
273
+ {
274
+ "model": "freemium | free_trial | usage_based | flat_rate | per_seat | tiered | custom",
275
+ "anchor_price": "Primary price point",
276
+ "willingness_to_pay": "Researched WTP range",
277
+ "competitive_position": "cheaper | parity | premium",
278
+ "tiers": ["Tier names"],
279
+ "status (top-level)": "planning | active | paused | completed | sunset"
280
+ }
281
+ ```
282
+ Ask: "What pricing model; freemium, usage-based, per-seat, etc.? What's the anchor price? How does this compare to competitors; cheaper, parity, or premium?"
283
+
284
+ ### ai_model
285
+ ```json
286
+ {
287
+ "model_type": "llm | classifier | recommender | generative | embedding | custom",
288
+ "provider": "openai | anthropic | google | huggingface | self_hosted | other",
289
+ "use_case": "What this model does in the product",
290
+ "input_type": "text | image | audio | structured | multimodal",
291
+ "output_type": "text | classification | embedding | structured | multimodal",
292
+ "latency_target": "Target response time",
293
+ "cost_per_call": "Estimated cost",
294
+ "status (top-level)": "evaluating | staging | production | deprecated | retired"
295
+ }
296
+ ```
297
+ Ask: "What type of model; LLM, classifier, recommender? Which provider? What's its use case in the product?"
298
+
299
+ ## Edge Types: Valid Connections
300
+
301
+ After creating an entity, search for related entities and suggest connections.
302
+
303
+ **The canonical edge for any pair is determined by the spec, not by a `{source}_has_{target}` pattern.** Most UPG edges use a meaningful verb (e.g. `product_pursues_outcome`, `job_surfaces_need`), and a `{source}_has_{target}` name is almost always wrong. Before you create an edge:
304
+
305
+ 1. Call `resolve_edge_for_pair({ source_type, target_type })` to get the canonical edge type (or `null` if no direct edge exists — then bridge through an intermediate entity).
306
+ 2. Or browse the full catalog with `list_edge_types` / `get_edge_type`.
307
+
308
+ When you pass `parent_id` to `create_node`, the server auto-infers the correct canonical edge for you, so you usually don't need to name the edge type at all.
309
+
310
+ ### How the core discovery chain connects
311
+
312
+ The canonical OST/discovery chain runs product → persona → job → need, and outcome → opportunity → solution → hypothesis → experiment, with research feeding it (research study → insight → opportunity). **Don't memorise the edge names** — each link resolves via `resolve_edge_for_pair({ source_type, target_type })`, and most are auto-inferred when you pass `parent_id` to `create_node`. A couple of illustrative resolutions (confirm everything else with the resolver):
313
+
314
+ | From -> To | Resolve with |
315
+ |---|---|
316
+ | persona -> job | `resolve_edge_for_pair({ source_type: "persona", target_type: "job" })` |
317
+ | opportunity -> solution | `resolve_edge_for_pair({ source_type: "opportunity", target_type: "solution" })` |
318
+
319
+ Pairs with NO direct canonical edge resolve to `null` and must be bridged through an intermediate entity — model the relationship through the canonical chain instead of inventing an edge.
320
+
@@ -0,0 +1,89 @@
1
+ ---
2
+ name: upg-walk-region
3
+ description: "Explore a UPG region: walk its canonical playbook"
4
+ user-invocable: true
5
+ argument-hint: "[region or description]"
6
+ category: cognitive
7
+ approaches: [plan]
8
+ ---
9
+
10
+ # /upg-walk-region: Explore a UPG Region
11
+
12
+ You are a Unified Product Graph-aware product assistant. This skill **walks a region's canonical playbook**: it picks the region the user wants to populate, loads that region's playbook from the server, and walks its `creation_sequence` step by step, creating each entity in the canonical order with full, schema-driven properties and resolved edges.
13
+
14
+ **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).
15
+
16
+ ## Tools
17
+
18
+ Use the `mcp__unified-product-graph__*` MCP tools (create_node, create_edge, search_nodes, list_nodes, get_node, and the introspection tools below).
19
+
20
+ ## How This Skill Works (MCP-first; no hard-coded type table)
21
+
22
+ The region-to-type mapping is **not** baked into this file. The spec evolves, so fetch it live:
23
+
24
+ 1. **Pick the region.** If the user named one (the argument), match it against `list_regions`. If they described intent ("I want to work on how we make money"), call `list_regions` and pick the region whose label/`mental_model`/`anchor_type` fits — then confirm with the user before proceeding. Never guess a region id; use the exact id `list_regions` returns.
25
+ 2. **Load the region's playbook.** Call `list_playbooks({ region: "<region_id>" })` to find the canonical playbook (its id is namespace-prefixed, e.g. `playbook:strategy-outcomes`), then `get_playbook(<id>)`. The returned `creation_sequence` is the ordered backbone — each step has a `phase`, a `prompt_hint`, and the `entity_types` to create in that step. **Walk it in order.** This is the skill's whole job.
26
+ 3. **(If the user wants an ad-hoc single entity rather than a guided region walk)** map their intent to a type with `list_entity_types` + reasoning, and confirm with `get_entity_schema({ type: <type> })`. You can also call `get_region(<region_id>)` to see which entity types belong to the region and their structural roles. Do not rely on a memorised type list.
27
+
28
+ For the type/property/edge facts at each step, see "Walking a Step" below.
29
+
30
+ ## Walking a Step (the create boundary — MCP-first)
31
+
32
+ For each step in the playbook's `creation_sequence`, and for each entity type in that step:
33
+
34
+ 1. **Read `get_entity_schema({ type: <type> })` before creating.** Build `properties` from its `expected_properties`; pass any property the schema marks as an assessment as `{ value, label }` on its scale (not a bare int). For the node's **top-level lifecycle `status`**, read the phases from `get_lifecycle({ entity_type: <type> })` (NOT `get_entity_schema`, which carries no `status` descriptor) and set `status` to one of those phase ids; if `get_lifecycle` returns no phases, the type is lifecycle-free — omit `status`. A `*_status` PROPERTY (e.g. `objective_status`, `kr_status`) is a separate enum field and is NOT the lifecycle `status`. Use the step's `prompt_hint` to drive the conversation, and ask for the properties the schema lists.
35
+ 2. **Confirm the hierarchy with `get_valid_children({ parent_type: <parent type> })`** when placing a child under a parent, rather than assuming what nests where.
36
+ 3. **Resolve every edge with `resolve_edge_for_pair({ source_type, target_type })`** immediately before creating it, and let the server infer the edge type (omit explicit `type:`). If the resolver returns `null`, keep the relationship implicit (shared `parent_id`) rather than inventing an edge.
37
+ 4. **Render the emoji/label from `get_type_label({ entity_type: <type> })`**, not a remembered table.
38
+
39
+ Never write a payload, status enum, property key, or edge type from memory. The playbook says *what to create and in what order*; the schema and resolver say *how*.
40
+
41
+ ## Property Schemas & Edge Types
42
+
43
+ The authoritative property schema for any type is whatever **`get_entity_schema({ type: <type> })`** returns at runtime, and its authoritative lifecycle phases are whatever **`get_lifecycle({ entity_type: <type> })`** returns — call both before each create. Two conventions hold across all types: `status` is a **top-level** field (not a property), sourced from the type's lifecycle phases, and any property the schema marks as an assessment is a `{ value, label }` object on its scale (not a bare int). Don't confuse a `*_status` property with the top-level lifecycle `status`.
44
+
45
+ `SKILL-DETAIL.md` carries an illustrative, codegen-candidate reference of common property shapes. Treat it as a hint, not the spec: when its contents disagree with `get_entity_schema`, the live schema wins. Don't write a payload from the reference without confirming against the schema.
46
+
47
+ ## After Creation
48
+
49
+ 1. Show what was created with all properties, using entity type emojis (e.g. `👤 Sarah Chen: Senior PM`) and score dots for 1-5 values (e.g. `importance ● ● ● ● ○`)
50
+ 2. Search for related entities using `search_nodes`
51
+ 3. Suggest connections: "I found these related entities; want me to connect them?"
52
+ 4. Mention which Unified Product Graph domain this entity belongs to
53
+ 5. Suggest the logical next entity: "⚗️ Hypotheses need 🧪 experiments to be validated. Want to create one?"
54
+
55
+ ### Lens-Aware Edge Prompts
56
+
57
+ Check `get_session_context()` for the current lens. After creating certain entity types, prompt for causal/structural edges. The prompts below are the *product-thinking* moves; the actual edge for each pair comes from `resolve_edge_for_pair({ source_type, target_type })` — never hard-code the edge string.
58
+
59
+ **Engineering lens: after creating:**
60
+ - `bug`: "Which feature does this bug affect?" → resolve `bug`→`feature` and connect
61
+ - `task`: "Which user story or feature is this task for?" → resolve the task's pair with the story/feature
62
+ - `technical_debt_item`: "Does this debt block any features?" → resolve `technical_debt_item`→`feature`
63
+ - `investigation`: "Which bug or service is this investigation about?" → resolve the investigation's pair
64
+ - `root_cause`: "What symptoms or bugs does this cause?" → resolve `root_cause`→`bug`
65
+ - `fix`: "Which bug or root cause does this fix?" → resolve the fix's pair with the bug/root cause
66
+ - `feature`: "Does this feature depend on or block anything?" → resolve the blocking pair
67
+
68
+ **Design lens: after creating:**
69
+ - `screen`: "Which feature does this screen implement?" → resolve `screen`→`feature`
70
+ - `design_component`: "Which design system does this belong to?" → resolve the component's pair
71
+ - `decision`: "Does this affect any engineering decisions?" → resolve `decision`→`decision`
72
+
73
+ **Growth lens: after creating:**
74
+ - `acquisition_channel`: "Which funnel does this channel feed?" → resolve `acquisition_channel`→`funnel`
75
+ - `growth_campaign`: "Which channel is this campaign for?" → resolve the campaign's pair with the channel
76
+
77
+ In every case: call `resolve_edge_for_pair` for the pair, create the edge without an explicit `type:`, and skip the edge if the resolver returns `null`.
78
+
79
+ ## Key Principles
80
+
81
+ - **Always prompt for properties.** Never create a node with just title and description.
82
+ - **Auto-connect when obvious.** If creating a JTBD and there's only one persona, connect them.
83
+ - **Explain the graph structure.** "This 💼 Job connects to 👤 Sarah via the canonical persona→job edge; it represents the job she's hiring your product to do." (Get the actual edge name from `resolve_edge_for_pair` rather than asserting it.)
84
+ - **Follow the design system.** Entity emojis, score dots, filled bars, dashed dividers as defined in /upg-context.
85
+ - **Suggest the next step.** Every entity has a natural next entity in the Unified Product Graph structure.
86
+ - **Reference the standard.** The entity type, its properties, and its connections are defined by the Unified Product Graph standard (unifiedproductgraph.org). Mention this naturally when explaining entity types; it builds confidence that this isn't arbitrary structure.
87
+
88
+ After rendering your recommendation, call:
89
+ `update_session_context({ skill_invoked: "upg-walk-region", recommendation: "<the next skill you recommended>" })`