@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.
Files changed (55) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +21 -0
  3. package/README.md +247 -0
  4. package/dist/cli.cjs +141010 -0
  5. package/package.json +65 -0
  6. package/skills/README.md +10 -0
  7. package/skills/upg/SKILL.md +245 -0
  8. package/skills/upg-analytics/SKILL.md +135 -0
  9. package/skills/upg-capture/SKILL.md +274 -0
  10. package/skills/upg-connect/SKILL.md +167 -0
  11. package/skills/upg-context/SKILL.md +506 -0
  12. package/skills/upg-context-intelligence/SKILL.md +227 -0
  13. package/skills/upg-design-system/SKILL.md +265 -0
  14. package/skills/upg-diff/SKILL.md +150 -0
  15. package/skills/upg-discover/SKILL.md +290 -0
  16. package/skills/upg-explore/SKILL-DETAIL.md +481 -0
  17. package/skills/upg-explore/SKILL.md +297 -0
  18. package/skills/upg-export/SKILL.md +385 -0
  19. package/skills/upg-feedback/SKILL.md +141 -0
  20. package/skills/upg-gaps/SKILL.md +376 -0
  21. package/skills/upg-hypothesis/SKILL.md +190 -0
  22. package/skills/upg-impact/SKILL.md +229 -0
  23. package/skills/upg-import/SKILL.md +189 -0
  24. package/skills/upg-init/SKILL.md +410 -0
  25. package/skills/upg-inspect/SKILL.md +167 -0
  26. package/skills/upg-journey/SKILL.md +207 -0
  27. package/skills/upg-launch/SKILL-DETAIL.md +392 -0
  28. package/skills/upg-launch/SKILL.md +141 -0
  29. package/skills/upg-migrate/SKILL.md +146 -0
  30. package/skills/upg-okr/SKILL-DETAIL.md +351 -0
  31. package/skills/upg-okr/SKILL.md +88 -0
  32. package/skills/upg-persona/SKILL.md +230 -0
  33. package/skills/upg-prioritise/SKILL.md +195 -0
  34. package/skills/upg-pull/SKILL-DETAIL.md +398 -0
  35. package/skills/upg-pull/SKILL.md +57 -0
  36. package/skills/upg-push/SKILL-DETAIL.md +385 -0
  37. package/skills/upg-push/SKILL.md +113 -0
  38. package/skills/upg-reflect/SKILL.md +201 -0
  39. package/skills/upg-research/SKILL.md +336 -0
  40. package/skills/upg-rollback/SKILL.md +163 -0
  41. package/skills/upg-run/SKILL.md +126 -0
  42. package/skills/upg-schema-changelog/SKILL.md +231 -0
  43. package/skills/upg-schema-consolidate/SKILL.md +243 -0
  44. package/skills/upg-schema-edges/SKILL.md +287 -0
  45. package/skills/upg-schema-evolve/SKILL.md +313 -0
  46. package/skills/upg-schema-health/SKILL.md +279 -0
  47. package/skills/upg-schema-update/SKILL.md +206 -0
  48. package/skills/upg-snapshot/SKILL.md +108 -0
  49. package/skills/upg-status/SKILL.md +340 -0
  50. package/skills/upg-strategy/SKILL.md +334 -0
  51. package/skills/upg-template/SKILL.md +145 -0
  52. package/skills/upg-trace/SKILL.md +197 -0
  53. package/skills/upg-tree/SKILL.md +233 -0
  54. package/skills/upg-verify/SKILL.md +223 -0
  55. package/skills/upg-workspace/SKILL.md +103 -0
@@ -0,0 +1,279 @@
1
+ ---
2
+ name: upg-schema-health
3
+ description: "Schema usage audit — dead types, empty properties, orphan patterns, real vs theoretical"
4
+ user-invocable: false
5
+ audience: advanced
6
+ argument-hint: "[path to .upg file] or [domain]"
7
+ category: schema
8
+ ---
9
+
10
+ > ⚠️ **Advanced skill** — intended for UPG contributors and power users who understand the spec internals. Not for general use. Running mutation skills (schema-update, schema-consolidate, schema-evolve) without understanding the cascade can corrupt your graph.
11
+
12
+ # /upg-schema-health — Schema Usage Audit
13
+
14
+ You are a schema health auditor. Your job is to compare what the UPG schema defines against what real graphs actually contain — surfacing dead types, empty properties, unused edges, and patterns the schema didn't anticipate.
15
+
16
+ **This is the feedback loop for schema governance.** Without it, we add types speculatively and never learn if they were right.
17
+
18
+ ## When to Use
19
+
20
+ - After adding new entity types — are they being used?
21
+ - Before a major schema evolution — what's dead weight?
22
+ - When a user reports confusion — is the schema matching their mental model?
23
+ - Periodically (quarterly) — schema hygiene check
24
+ - When onboarding a new domain (e.g., Felix bringing engineering) — what does their graph actually contain?
25
+
26
+ ## Input Modes
27
+
28
+ **Mode 1: Audit a specific graph**
29
+ ```
30
+ /upg-schema-health .upg/entopo.upg
31
+ ```
32
+
33
+ **Mode 2: Audit all graphs in workspace**
34
+ ```
35
+ /upg-schema-health
36
+ ```
37
+
38
+ **Mode 3: Audit a specific domain against real data**
39
+ ```
40
+ /upg-schema-health engineering
41
+ ```
42
+
43
+ ## Phase 1: Gather Data
44
+
45
+ ### 1a. Load the Graph(s)
46
+
47
+ Use MCP tools to read the graph:
48
+ ```
49
+ get_product_context(include_summary: true)
50
+ get_graph_digest()
51
+ list_nodes({ limit: 200 })
52
+ ```
53
+
54
+ If auditing multiple graphs, repeat for each `.upg` file via `list_local_products()` and `switch_product()`.
55
+
56
+ ### 1b. Load the Schema
57
+
58
+ Read the schema definition:
59
+ ```
60
+ Read packages/upg-spec/src/domains.ts → all domains and their types
61
+ Read packages/upg-spec/src/entity-meta.ts → all registered types with maturity
62
+ Read packages/upg-spec/src/index.ts → all edge types
63
+ ```
64
+
65
+ ## Phase 2: Type Usage Analysis
66
+
67
+ ### 2a. Used vs Defined
68
+
69
+ Compare types present in the graph against types defined in the schema:
70
+
71
+ ```
72
+ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
73
+ TYPE USAGE ANALYSIS
74
+
75
+ Schema defines: 310 entity types (across 36 atomic domains, 10 canonical regions)
76
+ Graph uses: 47 entity types
77
+ Coverage: 21%
78
+
79
+ BY DOMAIN:
80
+ | Domain | Defined | Used | Coverage | Status |
81
+ |--------|---------|------|----------|--------|
82
+ | Strategic | 14 | 8 | 57% | 🟢 Active |
83
+ | User | 6 | 4 | 67% | 🟢 Active |
84
+ | Engineering | 26 | 3 | 12% | 🟡 Sparse |
85
+ | Design | 22 | 0 | 0% | 🔴 Unused |
86
+ | Growth | 9 | 0 | 0% | 🔴 Unused |
87
+ ```
88
+
89
+ ### 2b. Dead Types
90
+
91
+ Types defined in the schema but with zero instances across all audited graphs:
92
+
93
+ ```
94
+ DEAD TYPES (0 instances in any graph)
95
+
96
+ Engineering (23 of 26 unused):
97
+ ⚪ aggregate, domain_entity, value_object, command, read_model,
98
+ queue_topic, build_artifact, integration_pattern, ...
99
+
100
+ Design (22 of 22 unused):
101
+ ⚪ user_journey, journey_step, design_question, design_concept, ...
102
+ ```
103
+
104
+ **Classify each dead type:**
105
+ - **Too new** — added recently, hasn't had time to be used (check `since` in entity-meta)
106
+ - **Too specialised** — only relevant at scale-up/enterprise tier (check tier classification)
107
+ - **Wrong abstraction** — the concept exists in the user's world but the type doesn't match their mental model
108
+ - **Genuinely unnecessary** — deprecation candidate
109
+
110
+ ### 2c. Surprise Types
111
+
112
+ Types present in the graph that aren't in the schema (via `source_type` or custom type strings):
113
+
114
+ ```
115
+ SURPRISE TYPES (in graph but not in schema)
116
+
117
+ | Type String | Count | Source | Interpretation |
118
+ |-------------|-------|--------|----------------|
119
+ | "user_segment" | 3 | manual | → Should map to 'market_segment' or 'behavioral_segment' |
120
+ | "tech_spike" | 2 | upg-capture | → Candidate for new type? Or map to 'investigation'? |
121
+ ```
122
+
123
+ These are gold — they tell you what users actually need that the schema doesn't provide.
124
+
125
+ ## Phase 3: Property Usage Analysis
126
+
127
+ ### 3a. Property Fill Rates
128
+
129
+ For each type that has instances, check how many of its defined properties are actually populated:
130
+
131
+ ```
132
+ PROPERTY FILL RATES
133
+
134
+ | Type | Instances | Avg Properties Filled | Empty Properties |
135
+ |------|-----------|----------------------|------------------|
136
+ | persona | 5 | 8/12 (67%) | segment, recruit_source, consent_status, switching_costs |
137
+ | hypothesis | 8 | 3/7 (43%) | expected_outcome, timeframe, success_criteria, null_hypothesis |
138
+ | service | 3 | 2/8 (25%) | tech_stack, repo_url, ci_status, health_check, team_owner, status |
139
+ ```
140
+
141
+ **Flag types with <30% fill rate** — the properties might be:
142
+ - Too granular for the user's stage
143
+ - Named confusingly (user doesn't recognise the field)
144
+ - Better suited as optional future enrichment than required at creation
145
+
146
+ ### 3b. Properties Used But Not Defined
147
+
148
+ Check for properties in graph nodes that aren't in the schema's property interface:
149
+
150
+ ```
151
+ UNSCHEMATISED PROPERTIES
152
+
153
+ | Type | Property | Count | Values Seen |
154
+ |------|----------|-------|-------------|
155
+ | feature | "priority" | 12 | "high", "medium", "low" |
156
+ | bug | "browser" | 4 | "chrome", "firefox", "safari" |
157
+ | persona | "company_size" | 3 | "startup", "enterprise" |
158
+ ```
159
+
160
+ These are candidates for adding to the property interfaces — the user is already using them.
161
+
162
+ ## Phase 4: Edge Usage Analysis
163
+
164
+ ### 4a. Used vs Defined Edges
165
+
166
+ ```
167
+ EDGE USAGE
168
+
169
+ Schema defines: 800+ edge types
170
+ Graph uses: 23 edge types
171
+ Coverage: 3%
172
+
173
+ MOST USED EDGES:
174
+ | Edge Type | Count | Between |
175
+ |-----------|-------|---------|
176
+ | persona_pursues_job | 15 | persona → job |
177
+ | job_has_need | 12 | job → need |
178
+ | feature_has_epic | 8 | feature → epic |
179
+
180
+ NEVER-USED EDGES (in defined domains that ARE used):
181
+ | Edge Type | Source Domain | Target Domain | Status |
182
+ |-----------|-------------|---------------|--------|
183
+ | evidence_supports_hypothesis | validation | validation | ⚪ Available but unused |
184
+ | insight_informs_opportunity | ux_research | discovery | ⚪ Available but unused |
185
+ ```
186
+
187
+ ### 4b. Implicit Relationships
188
+
189
+ Look for nodes that are semantically related but not connected by edges. These suggest missing edges or edges the user doesn't know about:
190
+
191
+ ```
192
+ IMPLICIT RELATIONSHIPS (nodes likely related but unconnected)
193
+
194
+ | Node A | Node B | Why related | Missing edge? |
195
+ |--------|--------|-------------|--------------|
196
+ | "Auth redesign" (feature) | "OAuth migration" (tech_debt) | Same domain keywords | debt_blocks_feature? |
197
+ | "Mobile persona" (persona) | "App Store channel" (acquisition_channel) | channel_targets_persona? |
198
+ ```
199
+
200
+ ## Phase 5: Structural Health
201
+
202
+ ### 5a. Orphan Rate by Type
203
+
204
+ ```
205
+ ORPHAN ANALYSIS
206
+
207
+ | Type | Total | Orphaned | Orphan Rate | Concern |
208
+ |------|-------|----------|-------------|---------|
209
+ | feature | 12 | 2 | 17% | 🟡 2 features with no parent or children |
210
+ | hypothesis | 8 | 5 | 63% | 🔴 Most hypotheses disconnected |
211
+ | task | 6 | 6 | 100% | 🔴 All tasks are orphans — wrong parent? |
212
+ ```
213
+
214
+ **High orphan rates suggest:**
215
+ - Parent-child hierarchy doesn't match user's mental model
216
+ - The creation flow (skill) doesn't prompt for connections
217
+ - The type is being used as a standalone note, not a graph entity
218
+
219
+ ### 5b. Chain Completeness
220
+
221
+ Check the key chains that make the graph useful:
222
+
223
+ ```
224
+ CHAIN HEALTH
225
+
226
+ persona → job → need → opportunity → solution → hypothesis → experiment → learning
227
+ 5/5 4/5 3/5 2/5 1/5 1/5 0/5 0/5
228
+
229
+ Chain breaks at: opportunity → solution (only 1 of 2 opportunities has solutions)
230
+ Chain dies at: experiment (no experiments exist)
231
+
232
+ → Discovery is strong, validation is absent
233
+ ```
234
+
235
+ ## Phase 6: Recommendations
236
+
237
+ Synthesise findings into actionable recommendations:
238
+
239
+ ```
240
+ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
241
+ SCHEMA HEALTH SUMMARY
242
+
243
+ Graph: [name] · [N] nodes · [M] edges · [T] types used
244
+
245
+ 🟢 HEALTHY
246
+ - [list what's working well]
247
+
248
+ 🟡 ATTENTION
249
+ - [list things that need review]
250
+
251
+ 🔴 ACTION NEEDED
252
+ - [list things that need fixing]
253
+
254
+ RECOMMENDATIONS:
255
+ 1. [Most impactful action] — /upg-schema-evolve [domain]
256
+ 2. [Second action] — /upg-schema-consolidate [types]
257
+ 3. [Third action] — consider deprecating [types]
258
+
259
+ DEAD TYPE CANDIDATES FOR DEPRECATION:
260
+ - [types with 0 usage across all audited graphs AND >6 months old]
261
+
262
+ PROPERTY ENRICHMENT CANDIDATES:
263
+ - [unschematised properties that appear in >3 instances]
264
+
265
+ SURPRISE TYPES TO INVESTIGATE:
266
+ - [custom types that might warrant schema addition]
267
+ ```
268
+
269
+ ## Key Principles
270
+
271
+ - **Real data over theory.** A type with 0 instances isn't wrong — it might be too new, too specialised, or genuinely unnecessary. The data tells you which.
272
+ - **Surprise types are the most valuable signal.** When users create types the schema doesn't have, that's direct feedback on what's missing.
273
+ - **Property fill rates reveal UX problems.** A 25% fill rate doesn't mean the properties are wrong — it might mean the creation skill doesn't ask for them.
274
+ - **Orphan rate reveals hierarchy problems.** 100% orphan rate on a type means the parent-child model is wrong for how users think about that concept.
275
+ - **Run this before and after schema changes.** The "before" establishes a baseline; the "after" tells you if the change helped.
276
+ - **Cross-graph analysis is more valuable than single-graph.** One graph's habits aren't representative. Compare multiple graphs to separate user preference from schema design issues.
277
+
278
+ ---
279
+ Internal development skill for UPG schema governance.
@@ -0,0 +1,206 @@
1
+ ---
2
+ name: upg-schema-update
3
+ description: "Add or update UPG entity types, edge types, or properties — cascades through the full codebase"
4
+ user-invocable: false
5
+ audience: advanced
6
+ argument-hint: "[entity type name or description of change]"
7
+ category: schema
8
+ ---
9
+
10
+ > ⚠️ **Advanced skill** — intended for UPG contributors and power users who understand the spec internals. Not for general use. Running mutation skills (schema-update, schema-consolidate, schema-evolve) without understanding the cascade can corrupt your graph.
11
+
12
+ # /upg-schema-update — UPG Schema Update Cascade
13
+
14
+ You are a schema update operator. When new entity types, edge types, or properties need to be added to the UPG specification, you cascade the change through every registration point in the codebase — from spec to MCP server to Graph UI to cloud server.
15
+
16
+ **This is an internal development skill, not a user-facing UPG skill.**
17
+
18
+ ## When to Use
19
+
20
+ - Adding new entity types (e.g., `investigation`, `root_cause`)
21
+ - Adding new edge types (e.g., `causes`, `revealed_by`)
22
+ - Adding property interfaces to existing types
23
+ - Updating domain groupings
24
+ - Deprecating or renaming entity types
25
+
26
+ ## The Cascade
27
+
28
+ Every schema change must flow through these 5 layers in order. **Do not skip layers.** Check each one even if you think it doesn't apply.
29
+
30
+ ### Layer 1: `@unified-product-graph/core` (packages/upg-spec/src/)
31
+
32
+ The source of truth. All changes start here.
33
+
34
+ | File | What to update | How to find the insertion point |
35
+ |------|---------------|-------------------------------|
36
+ | `catalog/entity-catalog.ts` | Add to `UPGEntityType` union | Find the domain comment (e.g., `// Engineering`) and add after the last type in that section |
37
+ | `registry/entity-meta.ts` | Register with immutable ID | Find the highest `ent_XXX` ID (`grep -o 'ent_[0-9]*' packages/upg-spec/src/registry/entity-meta.ts \| sort -t_ -k2 -n \| tail -1`), increment by 1. Set `maturity: 'stable'`, `since: '0.2.0'` |
38
+ | `registry/domains.ts` | Add to domain's `types` array | Find the domain by `id` in `UPG_DOMAINS`, add to its `types` array |
39
+ | `properties/domains/<domain>.ts` | Add property interface | Create `export interface XxxProperties { ... }` with typed fields. Use existing interfaces as templates. |
40
+ | `catalog/edge-catalog.ts` | Add edge types to `UPG_EDGE_CATALOG` | Format: `edge_name: { source_type, target_type, description, cardinality }`. The `UPG_EDGE_PAIR_MAP` is derived automatically. |
41
+ | `shapes/edges.ts` / `shapes/base-node.ts` | If modifying UPGEdge / UPGBaseNode | Rarely needed — most additions go in catalog and property interfaces |
42
+
43
+ **Verify:** `cd packages/upg-spec && npm run build` — must compile clean.
44
+
45
+ ### Layer 2: `upg-mcp-server` (packages/upg-mcp-server/)
46
+
47
+ The MCP server that reads/writes `.upg` files.
48
+
49
+ | What to check | When it matters |
50
+ |---------------|----------------|
51
+ | `src/server.ts` — tool handlers | If new types need special handling in `get_product_context`, `get_graph_digest`, or lens-aware sections |
52
+ | `src/lib/tools.ts` — digest computation | If new types should appear in health metrics |
53
+ | `skills/` — skill markdown files | If any skill references entity types that changed |
54
+ | `src/lib/edge-inference.ts` | If new edge types need inference rules |
55
+ | `src/classification.ts` | If tier classification changes |
56
+
57
+ **Verify:** `cd packages/upg-mcp-server && npm run build` — JS must build (DTS error in preflight.ts is pre-existing, ignore it).
58
+
59
+ ### Layer 3: `apps/graph` (apps/graph/src/)
60
+
61
+ The Graph UI. This is the most tedious layer — one monolithic file with ~10 registries that ALL need every type.
62
+
63
+ **Main file:** `apps/graph/src/lib/entity-metadata.ts` (~6300 lines)
64
+
65
+ **EVERY new NodeType requires entries in ALL of these registries:**
66
+
67
+ | Registry | Type | Line range | Format |
68
+ |----------|------|------------|--------|
69
+ | `NodeType` (in `types/graph.ts`) | Union type | ~138–550 | `\| 'type_name' // phase: X` |
70
+ | `NODE_LABELS` | `Record<NodeType, string>` | ~70–435 | `type_name: 'Display Name',` |
71
+ | `NODE_LABELS_PLURAL` | `Record<NodeType, string>` | ~436–800 | `type_name: 'Display Names',` |
72
+ | `NODE_ICONS` | `Record<NodeType, string>` | ~801–935 | `type_name: '🔍',` |
73
+ | `NODE_DESCRIPTIONS` | `Record<NodeType, string>` | ~1166–1530 | `type_name: 'One-line description',` |
74
+ | `NODE_LAYER` | `Record<NodeType, string>` | ~1531–1895 | `type_name: 'Engineering',` |
75
+ | `NODE_TYPE_TO_SLUG` | `Record<NodeType, string>` | ~2351–2715 | `type_name: 'type-name',` |
76
+ | `ENTITY_LAYERS` | Domain grouping | ~3547–3582 | Add to the right domain array |
77
+ | `DEFAULT_LAYOUT` | Layout mode | ~3600–3973 | `type_name: 'default',` |
78
+ | `PARENT_TYPE_MAP` | `Partial<Record<NodeType, NodeType>>` | ~6135–6330 | `type_name: 'parent_type',` |
79
+
80
+ **Optional registries (add if applicable):**
81
+
82
+ | Registry | When |
83
+ |----------|------|
84
+ | `TOP_LEVEL_TYPES` (~6065) | If the type can be a root node (no required parent) |
85
+ | `BOARD_GROUP_OPTIONS` (~3974) | If the type should have board view grouping |
86
+ | `VALID_CHILDREN` (if exists) | For explicit child-type allowlists |
87
+
88
+ **How to add to entity-metadata.ts efficiently:**
89
+
90
+ 1. Search for an existing type in the same domain to use as a template
91
+ 2. For each registry, search for that template type and add the new type nearby
92
+ 3. Follow alphabetical or domain ordering within each registry
93
+
94
+ **Verify:** `cd apps/graph && npx tsc --noEmit` — the `Record<NodeType, ...>` pattern will catch any missing entries at compile time.
95
+
96
+ ### Layer 4: `upg-cloud-server` (packages/upg-cloud-server/)
97
+
98
+ The cloud API server with PostgreSQL storage.
99
+
100
+ | What to check | When it matters |
101
+ |---------------|----------------|
102
+ | `src/store/pg-store.ts` — `rowToEdge()` | If new fields were added to UPGEdge (e.g., `confidence`, `note`) — need column or JSONB field |
103
+ | `src/store/pg-store.ts` — `rowToNode()` | If new fields were added to UPGBaseNode |
104
+ | Database migrations | If new columns needed for new edge/node properties |
105
+
106
+ **Usually no changes needed** for additive entity types — the cloud server stores types as strings and properties as JSONB. But check edge/node serialisation if interface shapes changed.
107
+
108
+ ### Layer 5: `apps/upg-site` (apps/upg-site/)
109
+
110
+ The documentation site.
111
+
112
+ | What to check | When it matters |
113
+ |---------------|----------------|
114
+ | Entity type documentation pages | If new types need user-facing docs |
115
+ | Sanity CMS content | If framework docs reference entity types |
116
+ | Domain/layer overview pages | If domain composition changed |
117
+
118
+ **Usually deferred** — docs update is a separate task.
119
+
120
+ ## Workflow
121
+
122
+ ### Step 1: Gather Requirements
123
+
124
+ Ask for or determine:
125
+ - **Entity type name(s)** — snake_case, singular (e.g., `root_cause`)
126
+ - **Domain** — which domain does it belong to? (e.g., `engineering`)
127
+ - **Properties** — what typed fields does it have?
128
+ - **Parent type** — what's its canonical parent in the hierarchy?
129
+ - **Edge types** — what relationships does it have with other types?
130
+ - **Display metadata** — label, plural, icon, description, layer name
131
+
132
+ ### Step 2: Execute the Cascade
133
+
134
+ Work through Layers 1–5 in order. For each layer:
135
+ 1. Read the relevant files
136
+ 2. Find the insertion points
137
+ 3. Make the changes
138
+ 4. Verify the build
139
+
140
+ ### Step 3: Verify
141
+
142
+ Run these checks after all changes:
143
+ ```bash
144
+ # Layer 1
145
+ cd packages/upg-spec && npm run build
146
+
147
+ # Layer 2
148
+ cd packages/upg-mcp-server && npm run build
149
+
150
+ # Layer 3 (most likely to catch missing entries)
151
+ cd apps/graph && npx tsc --noEmit
152
+
153
+ # Layer 4 (if changed)
154
+ cd packages/upg-cloud-server && npm run build
155
+ ```
156
+
157
+ **The `Record<NodeType, ...>` pattern in Layer 3 is your best friend** — TypeScript will error on every registry that's missing the new type. Let the compiler find what you missed.
158
+
159
+ ### Step 4: Commit
160
+
161
+ Use a commit message like:
162
+ ```
163
+ feat(upg-spec): add <type_name> entity type to <domain> domain
164
+
165
+ Cascade: spec → mcp-server → graph → cloud-server
166
+ ```
167
+
168
+ ## ID Assignment Rules
169
+
170
+ - Entity type IDs are immutable and sequential: `ent_001`, `ent_002`, ...
171
+ - Always find the current highest: `grep -o 'ent_[0-9]*' packages/upg-spec/src/registry/entity-meta.ts | sort -t_ -k2 -n | tail -1`
172
+ - Increment by 1 for each new type
173
+ - **Never reuse an ID**, even if the previous type was deprecated
174
+
175
+ ## Edge Type Rules
176
+
177
+ - Edges live in `UPG_EDGE_CATALOG` in `catalog/edge-catalog.ts`
178
+ - Format: `edge_name: { source_type, target_type, description, cardinality }`
179
+ - `UPG_EDGE_PAIR_MAP` (`source_type:target_type` → edge key) is derived automatically — don't edit it
180
+ - Check for duplicates before adding: search for the pair in the catalog
181
+ - Edge names should be verb-based: `causes`, `blocks`, `enables`, `implements`, `specifies`
182
+
183
+ ## Common Patterns
184
+
185
+ **Adding a debugging/troubleshooting entity (like investigation, root_cause):**
186
+ - Domain: `engineering`
187
+ - Parent: usually `service` or `bounded_context`
188
+ - Edges: `causes`, `affects`, `revealed_by`
189
+ - Properties: `status`, `severity`, `category`
190
+
191
+ **Adding a design governance entity:**
192
+ - For design decisions specifically, use the consolidated `decision` type with `layer: "design"` (see v0.2.0 migration) rather than creating a new type.
193
+ - Domain: `design`
194
+ - Parent: usually `product` or `design_system`
195
+ - Edges: `decision_informs_decision`, `decision_affects_component`, `decision_affects_screen`
196
+ - Properties (DecisionProperties): `layer`, `status` (proposed/accepted/deprecated/superseded), `context`, `decision`, `consequences`
197
+
198
+ **Adding a growth/marketing entity:**
199
+ - Domain: `growth` or `go_to_market`
200
+ - Parent: varies
201
+ - Edges: `targets`, `feeds`, `measures`
202
+ - Properties: domain-specific metrics
203
+
204
+ ## Key Principle
205
+
206
+ **The compiler is the checklist.** After adding to Layer 1 (spec) and Layer 3 (graph), run `tsc --noEmit` on `apps/graph`. Every `Record<NodeType, ...>` will error if you missed a registration. Fix each error = complete cascade.
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: upg-snapshot
3
+ description: "Save a named checkpoint of your product graph — version your thinking"
4
+ user-invocable: true
5
+ argument-hint: "[message]"
6
+ category: tooling
7
+ ---
8
+
9
+ # /upg-snapshot — Version Your Thinking
10
+
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
+
13
+ **Before producing any output, read the design system:** /upg-context for emoji mappings, formatting rules, and shared interaction patterns.
14
+
15
+ ## Tools
16
+
17
+ Use `mcp__unified-product-graph__get_graph_digest` to read current graph state.
18
+ Use Bash for git operations and .upg file version patching.
19
+
20
+ ## Flow
21
+
22
+ ### Step 1: Read Graph State
23
+
24
+ Silently fetch the graph summary:
25
+
26
+ ```
27
+ get_graph_digest()
28
+ ```
29
+
30
+ Extract: product title, node count, edge count.
31
+
32
+ ### Step 2: Get Snapshot Message
33
+
34
+ If the user provided a message as an argument, use it directly.
35
+
36
+ If no message was provided, ask once:
37
+
38
+ ```
39
+ What changed? (e.g. "Added pricing strategy", "Refined personas")
40
+ ```
41
+
42
+ Do NOT ask anything else. One question max.
43
+
44
+ ### Step 3: Increment Version
45
+
46
+ Read the .upg file with Bash, extract the current `graph_version` (default to 0 if missing), increment by 1, and write it back:
47
+
48
+ ```bash
49
+ # Read current version from .upg JSON
50
+ current=$(python3 -c "import json; d=json.load(open('$(ls *.upg | head -1)')); print(d.get('graph_version', 0))")
51
+ next=$((current + 1))
52
+
53
+ # Patch graph_version into the .upg JSON
54
+ python3 -c "
55
+ import json, glob
56
+ f = glob.glob('*.upg')[0]
57
+ d = json.load(open(f))
58
+ d['graph_version'] = $next
59
+ json.dump(d, open(f, 'w'), indent=2)
60
+ print(f' patched {f} → version {next}')
61
+ "
62
+ ```
63
+
64
+ ### Step 4: Git Commit
65
+
66
+ Stage and commit the .upg file:
67
+
68
+ ```bash
69
+ git add *.upg
70
+ git commit -m "upg: <message>"
71
+ ```
72
+
73
+ If git fails (not a repo, nothing to commit), report the error briefly and still confirm the version was incremented in the file.
74
+
75
+ ### Step 5: Confirm
76
+
77
+ Show confirmation using this exact format:
78
+
79
+ ```
80
+ <checkmark> Snapshot saved — version <N>: "<message>"
81
+ <node_count> entities · <edge_count> edges
82
+
83
+ Rollback: git checkout HEAD~1 -- <filename>.upg
84
+ ```
85
+
86
+ Use the checkmark symbol, entity/edge counts from Step 1, and the actual .upg filename.
87
+
88
+ ## Example Output
89
+
90
+ ```
91
+ ✓ Snapshot saved — version 5: "Added pricing strategy"
92
+ 47 entities · 38 edges
93
+
94
+ Rollback: git checkout HEAD~1 -- product.upg
95
+ ```
96
+
97
+ ## Key Principles
98
+
99
+ - **Fast.** No preamble, no dashboard, no health check. ~10 seconds.
100
+ - **One question max.** Only ask for the message if not provided.
101
+ - **Git-native.** The .upg file is diffable — git is the version history.
102
+ - **Silent on success.** Don't explain what versioning is. Just confirm.
103
+ - **Graceful on failure.** If git isn't available, still patch the version and say so.
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