@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.
- package/CHANGELOG.md +22 -0
- package/README.md +1 -1
- package/TOOLS.md +79 -16
- package/dist/index.js +1440 -290
- package/dist/index.js.map +1 -1
- package/dist/tools-manifest.json +197 -82
- 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 +10 -10
- 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
|
@@ -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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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>" })`
|