@su-record/vibe 2.6.14 → 2.6.16

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 (233) hide show
  1. package/CLAUDE.md +1 -394
  2. package/LICENSE +21 -21
  3. package/README.md +203 -497
  4. package/agents/architect-low.md +41 -41
  5. package/agents/architect-medium.md +59 -59
  6. package/agents/architect.md +80 -80
  7. package/agents/build-error-resolver.md +115 -115
  8. package/agents/compounder.md +261 -261
  9. package/agents/diagrammer.md +178 -178
  10. package/agents/e2e-tester.md +266 -266
  11. package/agents/explorer-low.md +42 -42
  12. package/agents/explorer-medium.md +59 -59
  13. package/agents/explorer.md +48 -48
  14. package/agents/implementer-low.md +43 -43
  15. package/agents/implementer-medium.md +52 -52
  16. package/agents/implementer.md +54 -54
  17. package/agents/refactor-cleaner.md +143 -143
  18. package/agents/research/best-practices-agent.md +199 -199
  19. package/agents/research/codebase-patterns-agent.md +157 -157
  20. package/agents/research/framework-docs-agent.md +188 -188
  21. package/agents/research/security-advisory-agent.md +213 -213
  22. package/agents/review/architecture-reviewer.md +107 -107
  23. package/agents/review/complexity-reviewer.md +116 -116
  24. package/agents/review/data-integrity-reviewer.md +88 -88
  25. package/agents/review/git-history-reviewer.md +103 -103
  26. package/agents/review/performance-reviewer.md +86 -86
  27. package/agents/review/python-reviewer.md +150 -150
  28. package/agents/review/rails-reviewer.md +139 -139
  29. package/agents/review/react-reviewer.md +144 -144
  30. package/agents/review/security-reviewer.md +80 -80
  31. package/agents/review/simplicity-reviewer.md +140 -140
  32. package/agents/review/test-coverage-reviewer.md +116 -116
  33. package/agents/review/typescript-reviewer.md +127 -127
  34. package/agents/searcher.md +54 -54
  35. package/agents/simplifier.md +120 -120
  36. package/agents/tester.md +49 -49
  37. package/agents/ui-previewer.md +268 -268
  38. package/commands/vibe.analyze.md +356 -356
  39. package/commands/vibe.reason.md +329 -329
  40. package/commands/vibe.review.md +412 -412
  41. package/commands/vibe.run.md +1266 -1266
  42. package/commands/vibe.spec.md +1054 -1054
  43. package/commands/vibe.spec.review.md +319 -319
  44. package/commands/vibe.trace.md +161 -161
  45. package/commands/vibe.utils.md +376 -376
  46. package/commands/vibe.verify.md +375 -375
  47. package/dist/cli/collaborator.js +52 -52
  48. package/dist/cli/detect.js +32 -32
  49. package/dist/cli/hud.js +20 -20
  50. package/dist/cli/index.js +118 -118
  51. package/dist/cli/index.js.map +1 -1
  52. package/dist/cli/llm.js +144 -144
  53. package/dist/cli/mcp.d.ts +49 -0
  54. package/dist/cli/mcp.d.ts.map +1 -0
  55. package/dist/cli/mcp.js +169 -0
  56. package/dist/cli/mcp.js.map +1 -0
  57. package/dist/cli/postinstall.js +858 -858
  58. package/dist/cli/setup/ProjectSetup.d.ts +3 -3
  59. package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
  60. package/dist/cli/setup/ProjectSetup.js +76 -30
  61. package/dist/cli/setup/ProjectSetup.js.map +1 -1
  62. package/dist/lib/DeepInit.js +24 -24
  63. package/dist/lib/IterationTracker.js +11 -11
  64. package/dist/lib/PythonParser.js +108 -108
  65. package/dist/lib/ReviewRace.js +96 -96
  66. package/dist/lib/SkillFrontmatter.js +28 -28
  67. package/dist/lib/SkillQualityGate.js +9 -9
  68. package/dist/lib/SkillRepository.js +159 -159
  69. package/dist/lib/UltraQA.js +77 -77
  70. package/dist/lib/gemini-api.js +5 -5
  71. package/dist/lib/gemini-mcp.d.ts +10 -0
  72. package/dist/lib/gemini-mcp.d.ts.map +1 -0
  73. package/dist/lib/gemini-mcp.js +353 -0
  74. package/dist/lib/gemini-mcp.js.map +1 -0
  75. package/dist/lib/gpt-api.js +4 -4
  76. package/dist/lib/gpt-mcp.d.ts +10 -0
  77. package/dist/lib/gpt-mcp.d.ts.map +1 -0
  78. package/dist/lib/gpt-mcp.js +352 -0
  79. package/dist/lib/gpt-mcp.js.map +1 -0
  80. package/dist/lib/memory/KnowledgeGraph.js +4 -4
  81. package/dist/lib/memory/MemorySearch.js +20 -20
  82. package/dist/lib/memory/MemoryStorage.js +64 -64
  83. package/dist/orchestrator/AgentManager.js +12 -12
  84. package/dist/orchestrator/MultiLlmResearch.js +8 -8
  85. package/dist/orchestrator/SmartRouter.js +11 -11
  86. package/dist/orchestrator/parallelResearch.js +24 -24
  87. package/dist/tools/analytics/getUsageAnalytics.d.ts +10 -0
  88. package/dist/tools/analytics/getUsageAnalytics.d.ts.map +1 -0
  89. package/dist/tools/analytics/getUsageAnalytics.js +246 -0
  90. package/dist/tools/analytics/getUsageAnalytics.js.map +1 -0
  91. package/dist/tools/analytics/index.d.ts +5 -0
  92. package/dist/tools/analytics/index.d.ts.map +1 -0
  93. package/dist/tools/analytics/index.js +5 -0
  94. package/dist/tools/analytics/index.js.map +1 -0
  95. package/dist/tools/convention/analyzeComplexity.test.js +115 -115
  96. package/dist/tools/convention/getCodingGuide.d.ts +7 -0
  97. package/dist/tools/convention/getCodingGuide.d.ts.map +1 -0
  98. package/dist/tools/convention/getCodingGuide.js +69 -0
  99. package/dist/tools/convention/getCodingGuide.js.map +1 -0
  100. package/dist/tools/convention/validateCodeQuality.test.js +104 -104
  101. package/dist/tools/planning/analyzeRequirements.d.ts +9 -0
  102. package/dist/tools/planning/analyzeRequirements.d.ts.map +1 -0
  103. package/dist/tools/planning/analyzeRequirements.js +171 -0
  104. package/dist/tools/planning/analyzeRequirements.js.map +1 -0
  105. package/dist/tools/planning/createUserStories.d.ts +9 -0
  106. package/dist/tools/planning/createUserStories.d.ts.map +1 -0
  107. package/dist/tools/planning/createUserStories.js +124 -0
  108. package/dist/tools/planning/createUserStories.js.map +1 -0
  109. package/dist/tools/planning/featureRoadmap.d.ts +10 -0
  110. package/dist/tools/planning/featureRoadmap.d.ts.map +1 -0
  111. package/dist/tools/planning/featureRoadmap.js +207 -0
  112. package/dist/tools/planning/featureRoadmap.js.map +1 -0
  113. package/dist/tools/planning/generatePrd.d.ts +11 -0
  114. package/dist/tools/planning/generatePrd.d.ts.map +1 -0
  115. package/dist/tools/planning/generatePrd.js +161 -0
  116. package/dist/tools/planning/generatePrd.js.map +1 -0
  117. package/dist/tools/planning/index.d.ts +8 -0
  118. package/dist/tools/planning/index.d.ts.map +1 -0
  119. package/dist/tools/planning/index.js +8 -0
  120. package/dist/tools/planning/index.js.map +1 -0
  121. package/dist/tools/prompt/analyzePrompt.d.ts +7 -0
  122. package/dist/tools/prompt/analyzePrompt.d.ts.map +1 -0
  123. package/dist/tools/prompt/analyzePrompt.js +150 -0
  124. package/dist/tools/prompt/analyzePrompt.js.map +1 -0
  125. package/dist/tools/prompt/enhancePrompt.d.ts +8 -0
  126. package/dist/tools/prompt/enhancePrompt.d.ts.map +1 -0
  127. package/dist/tools/prompt/enhancePrompt.js +110 -0
  128. package/dist/tools/prompt/enhancePrompt.js.map +1 -0
  129. package/dist/tools/prompt/enhancePromptGemini.d.ts +8 -0
  130. package/dist/tools/prompt/enhancePromptGemini.d.ts.map +1 -0
  131. package/dist/tools/prompt/enhancePromptGemini.js +332 -0
  132. package/dist/tools/prompt/enhancePromptGemini.js.map +1 -0
  133. package/dist/tools/prompt/index.d.ts +7 -0
  134. package/dist/tools/prompt/index.d.ts.map +1 -0
  135. package/dist/tools/prompt/index.js +7 -0
  136. package/dist/tools/prompt/index.js.map +1 -0
  137. package/dist/tools/reasoning/applyReasoningFramework.d.ts +8 -0
  138. package/dist/tools/reasoning/applyReasoningFramework.d.ts.map +1 -0
  139. package/dist/tools/reasoning/applyReasoningFramework.js +266 -0
  140. package/dist/tools/reasoning/applyReasoningFramework.js.map +1 -0
  141. package/dist/tools/reasoning/index.d.ts +5 -0
  142. package/dist/tools/reasoning/index.d.ts.map +1 -0
  143. package/dist/tools/reasoning/index.js +5 -0
  144. package/dist/tools/reasoning/index.js.map +1 -0
  145. package/dist/tools/spec/prdParser.test.js +171 -171
  146. package/dist/tools/spec/specGenerator.js +169 -169
  147. package/dist/tools/spec/traceabilityMatrix.js +64 -64
  148. package/dist/tools/spec/traceabilityMatrix.test.js +28 -28
  149. package/dist/tools/thinking/analyzeProblem.d.ts +7 -0
  150. package/dist/tools/thinking/analyzeProblem.d.ts.map +1 -0
  151. package/dist/tools/thinking/analyzeProblem.js +55 -0
  152. package/dist/tools/thinking/analyzeProblem.js.map +1 -0
  153. package/dist/tools/thinking/breakDownProblem.d.ts +8 -0
  154. package/dist/tools/thinking/breakDownProblem.d.ts.map +1 -0
  155. package/dist/tools/thinking/breakDownProblem.js +145 -0
  156. package/dist/tools/thinking/breakDownProblem.js.map +1 -0
  157. package/dist/tools/thinking/createThinkingChain.d.ts +7 -0
  158. package/dist/tools/thinking/createThinkingChain.d.ts.map +1 -0
  159. package/dist/tools/thinking/createThinkingChain.js +44 -0
  160. package/dist/tools/thinking/createThinkingChain.js.map +1 -0
  161. package/dist/tools/thinking/formatAsPlan.d.ts +9 -0
  162. package/dist/tools/thinking/formatAsPlan.d.ts.map +1 -0
  163. package/dist/tools/thinking/formatAsPlan.js +78 -0
  164. package/dist/tools/thinking/formatAsPlan.js.map +1 -0
  165. package/dist/tools/thinking/index.d.ts +10 -0
  166. package/dist/tools/thinking/index.d.ts.map +1 -0
  167. package/dist/tools/thinking/index.js +10 -0
  168. package/dist/tools/thinking/index.js.map +1 -0
  169. package/dist/tools/thinking/stepByStepAnalysis.d.ts +8 -0
  170. package/dist/tools/thinking/stepByStepAnalysis.d.ts.map +1 -0
  171. package/dist/tools/thinking/stepByStepAnalysis.js +63 -0
  172. package/dist/tools/thinking/stepByStepAnalysis.js.map +1 -0
  173. package/dist/tools/thinking/thinkAloudProcess.d.ts +8 -0
  174. package/dist/tools/thinking/thinkAloudProcess.d.ts.map +1 -0
  175. package/dist/tools/thinking/thinkAloudProcess.js +80 -0
  176. package/dist/tools/thinking/thinkAloudProcess.js.map +1 -0
  177. package/hooks/hooks.json +222 -222
  178. package/hooks/scripts/code-check.js +22 -22
  179. package/hooks/scripts/code-review.js +22 -22
  180. package/hooks/scripts/complexity.js +22 -22
  181. package/hooks/scripts/compound.js +23 -23
  182. package/hooks/scripts/context-save.js +33 -33
  183. package/hooks/scripts/gemini-ui-gen.js +281 -281
  184. package/hooks/scripts/generate-brand-assets.js +474 -474
  185. package/hooks/scripts/hud-multiline.js +262 -262
  186. package/hooks/scripts/hud-status.js +291 -291
  187. package/hooks/scripts/keyword-detector.js +214 -214
  188. package/hooks/scripts/llm-orchestrate.js +171 -171
  189. package/hooks/scripts/post-edit.js +97 -97
  190. package/hooks/scripts/post-tool-verify.js +210 -210
  191. package/hooks/scripts/pre-tool-guard.js +125 -125
  192. package/hooks/scripts/recall.js +22 -22
  193. package/hooks/scripts/session-start.js +30 -30
  194. package/hooks/scripts/skill-injector.js +191 -191
  195. package/hooks/scripts/utils.js +97 -97
  196. package/languages/csharp-unity.md +515 -515
  197. package/languages/gdscript-godot.md +470 -470
  198. package/languages/ruby-rails.md +489 -489
  199. package/languages/typescript-angular.md +433 -433
  200. package/languages/typescript-astro.md +416 -416
  201. package/languages/typescript-electron.md +406 -406
  202. package/languages/typescript-nestjs.md +524 -524
  203. package/languages/typescript-svelte.md +407 -407
  204. package/languages/typescript-tauri.md +365 -365
  205. package/package.json +84 -84
  206. package/skills/brand-assets.md +141 -141
  207. package/skills/commerce-patterns.md +361 -361
  208. package/skills/context7-usage.md +102 -102
  209. package/skills/e2e-commerce.md +304 -304
  210. package/skills/frontend-design.md +92 -92
  211. package/skills/git-worktree.md +181 -181
  212. package/skills/parallel-research.md +77 -77
  213. package/skills/priority-todos.md +239 -239
  214. package/skills/seo-checklist.md +244 -244
  215. package/skills/tool-fallback.md +190 -190
  216. package/skills/vibe-capabilities.md +161 -161
  217. package/vibe/constitution.md +227 -227
  218. package/vibe/rules/core/communication-guide.md +98 -98
  219. package/vibe/rules/core/development-philosophy.md +52 -52
  220. package/vibe/rules/core/quick-start.md +102 -102
  221. package/vibe/rules/quality/bdd-contract-testing.md +393 -393
  222. package/vibe/rules/quality/checklist.md +276 -276
  223. package/vibe/rules/quality/testing-strategy.md +440 -440
  224. package/vibe/rules/standards/anti-patterns.md +541 -541
  225. package/vibe/rules/standards/code-structure.md +291 -291
  226. package/vibe/rules/standards/complexity-metrics.md +313 -313
  227. package/vibe/rules/standards/naming-conventions.md +198 -198
  228. package/vibe/setup.sh +31 -31
  229. package/vibe/templates/constitution-template.md +252 -252
  230. package/vibe/templates/contract-backend-template.md +526 -526
  231. package/vibe/templates/contract-frontend-template.md +599 -599
  232. package/vibe/templates/feature-template.md +96 -96
  233. package/vibe/templates/spec-template.md +221 -221
@@ -1,361 +1,361 @@
1
- ---
2
- name: commerce-patterns
3
- description: "E-commerce domain patterns - cart, payment, inventory with transaction safety"
4
- triggers: [commerce, ecommerce, cart, payment, checkout, inventory, stock, order, pg, toss, stripe]
5
- priority: 70
6
- ---
7
- # Commerce Patterns Skill
8
-
9
- E-commerce domain patterns for reliable transactions.
10
-
11
- ## When to Use
12
-
13
- - Shopping cart implementation
14
- - Payment integration (PG, Stripe, Toss)
15
- - Inventory/stock management
16
- - Order processing systems
17
-
18
- ## Core Patterns
19
-
20
- ### 1. Cart (Shopping Cart)
21
-
22
- #### State Model
23
- ```typescript
24
- interface CartItem {
25
- productId: string;
26
- variantId?: string;
27
- quantity: number;
28
- price: number; // Snapshot at add time
29
- originalPrice: number; // For comparison
30
- addedAt: Date;
31
- }
32
-
33
- interface Cart {
34
- id: string;
35
- userId?: string; // null for guest
36
- sessionId: string; // For guest merge
37
- items: CartItem[];
38
- couponCode?: string;
39
- updatedAt: Date;
40
- expiresAt: Date; // Cart expiration
41
- }
42
- ```
43
-
44
- #### Key Patterns
45
-
46
- | Pattern | Description |
47
- |---------|-------------|
48
- | **Guest → User Merge** | Merge localStorage cart on login |
49
- | **Price Snapshot** | Store price at add time, revalidate at checkout |
50
- | **Expiration** | Clear abandoned carts after N days |
51
- | **Validation** | Check stock/price at checkout entry |
52
-
53
- #### Implementation
54
- ```typescript
55
- class CartService {
56
- async addItem(cartId: string, item: AddItemRequest): Promise<Cart> {
57
- // 1. Validate product exists and in stock
58
- const product = await this.productService.get(item.productId);
59
- if (!product || product.stock < item.quantity) {
60
- throw new OutOfStockError();
61
- }
62
-
63
- // 2. Snapshot current price
64
- const cartItem: CartItem = {
65
- ...item,
66
- price: product.currentPrice,
67
- originalPrice: product.originalPrice,
68
- addedAt: new Date(),
69
- };
70
-
71
- // 3. Add or update quantity
72
- return this.cartRepository.upsertItem(cartId, cartItem);
73
- }
74
-
75
- async mergeGuestCart(userId: string, sessionId: string): Promise<Cart> {
76
- const guestCart = await this.cartRepository.findBySession(sessionId);
77
- const userCart = await this.cartRepository.findByUser(userId);
78
-
79
- if (!guestCart) return userCart;
80
-
81
- // Merge: user cart takes priority for duplicates
82
- const merged = this.mergeItems(userCart.items, guestCart.items);
83
- await this.cartRepository.delete(guestCart.id);
84
-
85
- return this.cartRepository.update(userCart.id, { items: merged });
86
- }
87
- }
88
- ```
89
-
90
- ### 2. Payment
91
-
92
- #### State Machine
93
- ```
94
- PENDING → PROCESSING → AUTHORIZED → CAPTURED → COMPLETED
95
- ↘ FAILED
96
- ↘ CANCELED
97
- COMPLETED → REFUND_REQUESTED → REFUNDED (partial/full)
98
- ```
99
-
100
- #### Idempotency Pattern (Critical)
101
- ```typescript
102
- interface PaymentRequest {
103
- orderId: string;
104
- amount: number;
105
- currency: string;
106
- idempotencyKey: string; // REQUIRED: `order_${orderId}_${timestamp}`
107
- paymentMethod: PaymentMethod;
108
- }
109
-
110
- class PaymentService {
111
- async processPayment(request: PaymentRequest): Promise<PaymentResult> {
112
- // 1. Check idempotency - prevent duplicate charges
113
- const existing = await this.paymentRepository.findByIdempotencyKey(
114
- request.idempotencyKey
115
- );
116
- if (existing) {
117
- return existing.result; // Return cached result
118
- }
119
-
120
- // 2. Create payment record (PENDING)
121
- const payment = await this.paymentRepository.create({
122
- ...request,
123
- status: 'PENDING',
124
- });
125
-
126
- try {
127
- // 3. Call PG adapter
128
- const pgResult = await this.pgAdapter.authorize(request);
129
-
130
- // 4. Update status
131
- return this.paymentRepository.update(payment.id, {
132
- status: pgResult.success ? 'AUTHORIZED' : 'FAILED',
133
- pgTransactionId: pgResult.transactionId,
134
- result: pgResult,
135
- });
136
- } catch (error) {
137
- await this.paymentRepository.update(payment.id, {
138
- status: 'FAILED',
139
- error: error.message,
140
- });
141
- throw error;
142
- }
143
- }
144
- }
145
- ```
146
-
147
- #### PG Adapter Pattern
148
- ```typescript
149
- interface PGAdapter {
150
- authorize(request: PaymentRequest): Promise<PGResult>;
151
- capture(transactionId: string): Promise<PGResult>;
152
- cancel(transactionId: string): Promise<PGResult>;
153
- refund(transactionId: string, amount?: number): Promise<PGResult>;
154
- }
155
-
156
- // Implementations
157
- class TossPaymentsAdapter implements PGAdapter { /* ... */ }
158
- class StripeAdapter implements PGAdapter { /* ... */ }
159
- class PortOneAdapter implements PGAdapter { /* ... */ }
160
- ```
161
-
162
- #### Webhook Handling
163
- ```typescript
164
- class PaymentWebhookHandler {
165
- async handle(event: WebhookEvent): Promise<void> {
166
- // 1. Verify signature
167
- if (!this.verifySignature(event)) {
168
- throw new UnauthorizedError();
169
- }
170
-
171
- // 2. Idempotency check - process each event only once
172
- const processed = await this.eventStore.find(event.id);
173
- if (processed) {
174
- return; // Already processed
175
- }
176
-
177
- // 3. Process event
178
- await this.processEvent(event);
179
-
180
- // 4. Mark as processed
181
- await this.eventStore.save({
182
- eventId: event.id,
183
- processedAt: new Date(),
184
- });
185
- }
186
- }
187
- ```
188
-
189
- ### 3. Inventory (Stock Management)
190
-
191
- #### Reservation Pattern (Two-Phase)
192
- ```typescript
193
- interface StockReservation {
194
- id: string;
195
- productId: string;
196
- quantity: number;
197
- orderId: string;
198
- status: 'RESERVED' | 'COMMITTED' | 'RELEASED';
199
- expiresAt: Date; // Auto-release if not committed
200
- createdAt: Date;
201
- }
202
-
203
- class InventoryService {
204
- // Phase 1: Reserve stock (at checkout start)
205
- async reserve(orderId: string, items: OrderItem[]): Promise<void> {
206
- for (const item of items) {
207
- // Atomic decrement with check
208
- const result = await this.db.query(`
209
- UPDATE products
210
- SET reserved_stock = reserved_stock + $1
211
- WHERE id = $2
212
- AND (available_stock - reserved_stock) >= $1
213
- RETURNING *
214
- `, [item.quantity, item.productId]);
215
-
216
- if (result.rowCount === 0) {
217
- // Rollback previous reservations
218
- await this.releaseAll(orderId);
219
- throw new InsufficientStockError(item.productId);
220
- }
221
-
222
- await this.reservationRepository.create({
223
- orderId,
224
- productId: item.productId,
225
- quantity: item.quantity,
226
- status: 'RESERVED',
227
- expiresAt: addMinutes(new Date(), 15), // 15min hold
228
- });
229
- }
230
- }
231
-
232
- // Phase 2: Commit stock (after payment success)
233
- async commit(orderId: string): Promise<void> {
234
- const reservations = await this.reservationRepository.findByOrder(orderId);
235
-
236
- for (const reservation of reservations) {
237
- await this.db.query(`
238
- UPDATE products
239
- SET
240
- available_stock = available_stock - $1,
241
- reserved_stock = reserved_stock - $1
242
- WHERE id = $2
243
- `, [reservation.quantity, reservation.productId]);
244
-
245
- await this.reservationRepository.update(reservation.id, {
246
- status: 'COMMITTED',
247
- });
248
- }
249
- }
250
-
251
- // Rollback: Release stock (payment failed or timeout)
252
- async release(orderId: string): Promise<void> {
253
- const reservations = await this.reservationRepository.findByOrder(orderId);
254
-
255
- for (const reservation of reservations) {
256
- if (reservation.status === 'RESERVED') {
257
- await this.db.query(`
258
- UPDATE products
259
- SET reserved_stock = reserved_stock - $1
260
- WHERE id = $2
261
- `, [reservation.quantity, reservation.productId]);
262
-
263
- await this.reservationRepository.update(reservation.id, {
264
- status: 'RELEASED',
265
- });
266
- }
267
- }
268
- }
269
- }
270
- ```
271
-
272
- #### Concurrency Control
273
- ```typescript
274
- // Option 1: Optimistic Locking
275
- await db.query(`
276
- UPDATE products
277
- SET stock = stock - $1, version = version + 1
278
- WHERE id = $2 AND version = $3 AND stock >= $1
279
- `, [quantity, productId, expectedVersion]);
280
-
281
- // Option 2: Pessimistic Locking (for high contention)
282
- await db.query(`
283
- SELECT * FROM products WHERE id = $1 FOR UPDATE
284
- `, [productId]);
285
-
286
- // Option 3: Redis Distributed Lock
287
- const lock = await redlock.lock(`stock:${productId}`, 5000);
288
- try {
289
- // Update stock
290
- } finally {
291
- await lock.unlock();
292
- }
293
- ```
294
-
295
- ## Order Flow (Complete)
296
-
297
- ```
298
- ┌─────────────────────────────────────────────────────────────┐
299
- │ CHECKOUT FLOW │
300
- ├─────────────────────────────────────────────────────────────┤
301
- │ │
302
- │ 1. Cart Validation │
303
- │ └─ Revalidate prices, check stock availability │
304
- │ │
305
- │ 2. Order Creation (PENDING) │
306
- │ └─ Generate orderId, snapshot cart │
307
- │ │
308
- │ 3. Stock Reservation │
309
- │ └─ Reserve inventory (15min hold) │
310
- │ │
311
- │ 4. Payment Processing │
312
- │ ├─ Success → Order PAID, Stock COMMIT │
313
- │ └─ Failure → Order FAILED, Stock RELEASE │
314
- │ │
315
- │ 5. Order Confirmation │
316
- │ └─ Send notification, trigger fulfillment │
317
- │ │
318
- └─────────────────────────────────────────────────────────────┘
319
- ```
320
-
321
- ## Common Bugs & Prevention
322
-
323
- | Bug | Cause | Prevention |
324
- |-----|-------|------------|
325
- | **Duplicate payment** | User double-click, webhook retry | Idempotency key |
326
- | **Negative stock** | Race condition | Atomic update with check |
327
- | **Price mismatch** | Price changed during checkout | Snapshot + revalidation |
328
- | **Orphan reservation** | Payment timeout without release | TTL + scheduled cleanup |
329
- | **Lost webhook** | Network failure | Retry + idempotent handler |
330
- | **Order state corruption** | Concurrent updates | State machine + versioning |
331
-
332
- ## Integration with /vibe.run
333
-
334
- During commerce feature implementation:
335
-
336
- 1. **Phase 1**: Define domain models (Cart, Order, Payment, Inventory)
337
- 2. **Phase 2**: Implement core services with patterns above
338
- 3. **Phase 3**: Add PG adapter and webhook handlers
339
- 4. **Phase 4**: Implement compensating transactions (Saga)
340
- 5. **Phase 5**: E2E test critical flows
341
-
342
- ## Checklist
343
-
344
- ### Cart
345
- - [ ] Guest/user cart merge on login
346
- - [ ] Price snapshot at add time
347
- - [ ] Stock validation at checkout
348
- - [ ] Cart expiration cleanup
349
-
350
- ### Payment
351
- - [ ] Idempotency key on all requests
352
- - [ ] Webhook signature verification
353
- - [ ] Duplicate event handling
354
- - [ ] Timeout/retry strategy
355
- - [ ] Refund flow tested
356
-
357
- ### Inventory
358
- - [ ] Two-phase reservation (reserve → commit/release)
359
- - [ ] Atomic stock updates
360
- - [ ] Reservation TTL and cleanup job
361
- - [ ] Concurrency control tested
1
+ ---
2
+ name: commerce-patterns
3
+ description: "E-commerce domain patterns - cart, payment, inventory with transaction safety"
4
+ triggers: [commerce, ecommerce, cart, payment, checkout, inventory, stock, order, pg, toss, stripe]
5
+ priority: 70
6
+ ---
7
+ # Commerce Patterns Skill
8
+
9
+ E-commerce domain patterns for reliable transactions.
10
+
11
+ ## When to Use
12
+
13
+ - Shopping cart implementation
14
+ - Payment integration (PG, Stripe, Toss)
15
+ - Inventory/stock management
16
+ - Order processing systems
17
+
18
+ ## Core Patterns
19
+
20
+ ### 1. Cart (Shopping Cart)
21
+
22
+ #### State Model
23
+ ```typescript
24
+ interface CartItem {
25
+ productId: string;
26
+ variantId?: string;
27
+ quantity: number;
28
+ price: number; // Snapshot at add time
29
+ originalPrice: number; // For comparison
30
+ addedAt: Date;
31
+ }
32
+
33
+ interface Cart {
34
+ id: string;
35
+ userId?: string; // null for guest
36
+ sessionId: string; // For guest merge
37
+ items: CartItem[];
38
+ couponCode?: string;
39
+ updatedAt: Date;
40
+ expiresAt: Date; // Cart expiration
41
+ }
42
+ ```
43
+
44
+ #### Key Patterns
45
+
46
+ | Pattern | Description |
47
+ |---------|-------------|
48
+ | **Guest → User Merge** | Merge localStorage cart on login |
49
+ | **Price Snapshot** | Store price at add time, revalidate at checkout |
50
+ | **Expiration** | Clear abandoned carts after N days |
51
+ | **Validation** | Check stock/price at checkout entry |
52
+
53
+ #### Implementation
54
+ ```typescript
55
+ class CartService {
56
+ async addItem(cartId: string, item: AddItemRequest): Promise<Cart> {
57
+ // 1. Validate product exists and in stock
58
+ const product = await this.productService.get(item.productId);
59
+ if (!product || product.stock < item.quantity) {
60
+ throw new OutOfStockError();
61
+ }
62
+
63
+ // 2. Snapshot current price
64
+ const cartItem: CartItem = {
65
+ ...item,
66
+ price: product.currentPrice,
67
+ originalPrice: product.originalPrice,
68
+ addedAt: new Date(),
69
+ };
70
+
71
+ // 3. Add or update quantity
72
+ return this.cartRepository.upsertItem(cartId, cartItem);
73
+ }
74
+
75
+ async mergeGuestCart(userId: string, sessionId: string): Promise<Cart> {
76
+ const guestCart = await this.cartRepository.findBySession(sessionId);
77
+ const userCart = await this.cartRepository.findByUser(userId);
78
+
79
+ if (!guestCart) return userCart;
80
+
81
+ // Merge: user cart takes priority for duplicates
82
+ const merged = this.mergeItems(userCart.items, guestCart.items);
83
+ await this.cartRepository.delete(guestCart.id);
84
+
85
+ return this.cartRepository.update(userCart.id, { items: merged });
86
+ }
87
+ }
88
+ ```
89
+
90
+ ### 2. Payment
91
+
92
+ #### State Machine
93
+ ```
94
+ PENDING → PROCESSING → AUTHORIZED → CAPTURED → COMPLETED
95
+ ↘ FAILED
96
+ ↘ CANCELED
97
+ COMPLETED → REFUND_REQUESTED → REFUNDED (partial/full)
98
+ ```
99
+
100
+ #### Idempotency Pattern (Critical)
101
+ ```typescript
102
+ interface PaymentRequest {
103
+ orderId: string;
104
+ amount: number;
105
+ currency: string;
106
+ idempotencyKey: string; // REQUIRED: `order_${orderId}_${timestamp}`
107
+ paymentMethod: PaymentMethod;
108
+ }
109
+
110
+ class PaymentService {
111
+ async processPayment(request: PaymentRequest): Promise<PaymentResult> {
112
+ // 1. Check idempotency - prevent duplicate charges
113
+ const existing = await this.paymentRepository.findByIdempotencyKey(
114
+ request.idempotencyKey
115
+ );
116
+ if (existing) {
117
+ return existing.result; // Return cached result
118
+ }
119
+
120
+ // 2. Create payment record (PENDING)
121
+ const payment = await this.paymentRepository.create({
122
+ ...request,
123
+ status: 'PENDING',
124
+ });
125
+
126
+ try {
127
+ // 3. Call PG adapter
128
+ const pgResult = await this.pgAdapter.authorize(request);
129
+
130
+ // 4. Update status
131
+ return this.paymentRepository.update(payment.id, {
132
+ status: pgResult.success ? 'AUTHORIZED' : 'FAILED',
133
+ pgTransactionId: pgResult.transactionId,
134
+ result: pgResult,
135
+ });
136
+ } catch (error) {
137
+ await this.paymentRepository.update(payment.id, {
138
+ status: 'FAILED',
139
+ error: error.message,
140
+ });
141
+ throw error;
142
+ }
143
+ }
144
+ }
145
+ ```
146
+
147
+ #### PG Adapter Pattern
148
+ ```typescript
149
+ interface PGAdapter {
150
+ authorize(request: PaymentRequest): Promise<PGResult>;
151
+ capture(transactionId: string): Promise<PGResult>;
152
+ cancel(transactionId: string): Promise<PGResult>;
153
+ refund(transactionId: string, amount?: number): Promise<PGResult>;
154
+ }
155
+
156
+ // Implementations
157
+ class TossPaymentsAdapter implements PGAdapter { /* ... */ }
158
+ class StripeAdapter implements PGAdapter { /* ... */ }
159
+ class PortOneAdapter implements PGAdapter { /* ... */ }
160
+ ```
161
+
162
+ #### Webhook Handling
163
+ ```typescript
164
+ class PaymentWebhookHandler {
165
+ async handle(event: WebhookEvent): Promise<void> {
166
+ // 1. Verify signature
167
+ if (!this.verifySignature(event)) {
168
+ throw new UnauthorizedError();
169
+ }
170
+
171
+ // 2. Idempotency check - process each event only once
172
+ const processed = await this.eventStore.find(event.id);
173
+ if (processed) {
174
+ return; // Already processed
175
+ }
176
+
177
+ // 3. Process event
178
+ await this.processEvent(event);
179
+
180
+ // 4. Mark as processed
181
+ await this.eventStore.save({
182
+ eventId: event.id,
183
+ processedAt: new Date(),
184
+ });
185
+ }
186
+ }
187
+ ```
188
+
189
+ ### 3. Inventory (Stock Management)
190
+
191
+ #### Reservation Pattern (Two-Phase)
192
+ ```typescript
193
+ interface StockReservation {
194
+ id: string;
195
+ productId: string;
196
+ quantity: number;
197
+ orderId: string;
198
+ status: 'RESERVED' | 'COMMITTED' | 'RELEASED';
199
+ expiresAt: Date; // Auto-release if not committed
200
+ createdAt: Date;
201
+ }
202
+
203
+ class InventoryService {
204
+ // Phase 1: Reserve stock (at checkout start)
205
+ async reserve(orderId: string, items: OrderItem[]): Promise<void> {
206
+ for (const item of items) {
207
+ // Atomic decrement with check
208
+ const result = await this.db.query(`
209
+ UPDATE products
210
+ SET reserved_stock = reserved_stock + $1
211
+ WHERE id = $2
212
+ AND (available_stock - reserved_stock) >= $1
213
+ RETURNING *
214
+ `, [item.quantity, item.productId]);
215
+
216
+ if (result.rowCount === 0) {
217
+ // Rollback previous reservations
218
+ await this.releaseAll(orderId);
219
+ throw new InsufficientStockError(item.productId);
220
+ }
221
+
222
+ await this.reservationRepository.create({
223
+ orderId,
224
+ productId: item.productId,
225
+ quantity: item.quantity,
226
+ status: 'RESERVED',
227
+ expiresAt: addMinutes(new Date(), 15), // 15min hold
228
+ });
229
+ }
230
+ }
231
+
232
+ // Phase 2: Commit stock (after payment success)
233
+ async commit(orderId: string): Promise<void> {
234
+ const reservations = await this.reservationRepository.findByOrder(orderId);
235
+
236
+ for (const reservation of reservations) {
237
+ await this.db.query(`
238
+ UPDATE products
239
+ SET
240
+ available_stock = available_stock - $1,
241
+ reserved_stock = reserved_stock - $1
242
+ WHERE id = $2
243
+ `, [reservation.quantity, reservation.productId]);
244
+
245
+ await this.reservationRepository.update(reservation.id, {
246
+ status: 'COMMITTED',
247
+ });
248
+ }
249
+ }
250
+
251
+ // Rollback: Release stock (payment failed or timeout)
252
+ async release(orderId: string): Promise<void> {
253
+ const reservations = await this.reservationRepository.findByOrder(orderId);
254
+
255
+ for (const reservation of reservations) {
256
+ if (reservation.status === 'RESERVED') {
257
+ await this.db.query(`
258
+ UPDATE products
259
+ SET reserved_stock = reserved_stock - $1
260
+ WHERE id = $2
261
+ `, [reservation.quantity, reservation.productId]);
262
+
263
+ await this.reservationRepository.update(reservation.id, {
264
+ status: 'RELEASED',
265
+ });
266
+ }
267
+ }
268
+ }
269
+ }
270
+ ```
271
+
272
+ #### Concurrency Control
273
+ ```typescript
274
+ // Option 1: Optimistic Locking
275
+ await db.query(`
276
+ UPDATE products
277
+ SET stock = stock - $1, version = version + 1
278
+ WHERE id = $2 AND version = $3 AND stock >= $1
279
+ `, [quantity, productId, expectedVersion]);
280
+
281
+ // Option 2: Pessimistic Locking (for high contention)
282
+ await db.query(`
283
+ SELECT * FROM products WHERE id = $1 FOR UPDATE
284
+ `, [productId]);
285
+
286
+ // Option 3: Redis Distributed Lock
287
+ const lock = await redlock.lock(`stock:${productId}`, 5000);
288
+ try {
289
+ // Update stock
290
+ } finally {
291
+ await lock.unlock();
292
+ }
293
+ ```
294
+
295
+ ## Order Flow (Complete)
296
+
297
+ ```
298
+ ┌─────────────────────────────────────────────────────────────┐
299
+ │ CHECKOUT FLOW │
300
+ ├─────────────────────────────────────────────────────────────┤
301
+ │ │
302
+ │ 1. Cart Validation │
303
+ │ └─ Revalidate prices, check stock availability │
304
+ │ │
305
+ │ 2. Order Creation (PENDING) │
306
+ │ └─ Generate orderId, snapshot cart │
307
+ │ │
308
+ │ 3. Stock Reservation │
309
+ │ └─ Reserve inventory (15min hold) │
310
+ │ │
311
+ │ 4. Payment Processing │
312
+ │ ├─ Success → Order PAID, Stock COMMIT │
313
+ │ └─ Failure → Order FAILED, Stock RELEASE │
314
+ │ │
315
+ │ 5. Order Confirmation │
316
+ │ └─ Send notification, trigger fulfillment │
317
+ │ │
318
+ └─────────────────────────────────────────────────────────────┘
319
+ ```
320
+
321
+ ## Common Bugs & Prevention
322
+
323
+ | Bug | Cause | Prevention |
324
+ |-----|-------|------------|
325
+ | **Duplicate payment** | User double-click, webhook retry | Idempotency key |
326
+ | **Negative stock** | Race condition | Atomic update with check |
327
+ | **Price mismatch** | Price changed during checkout | Snapshot + revalidation |
328
+ | **Orphan reservation** | Payment timeout without release | TTL + scheduled cleanup |
329
+ | **Lost webhook** | Network failure | Retry + idempotent handler |
330
+ | **Order state corruption** | Concurrent updates | State machine + versioning |
331
+
332
+ ## Integration with /vibe.run
333
+
334
+ During commerce feature implementation:
335
+
336
+ 1. **Phase 1**: Define domain models (Cart, Order, Payment, Inventory)
337
+ 2. **Phase 2**: Implement core services with patterns above
338
+ 3. **Phase 3**: Add PG adapter and webhook handlers
339
+ 4. **Phase 4**: Implement compensating transactions (Saga)
340
+ 5. **Phase 5**: E2E test critical flows
341
+
342
+ ## Checklist
343
+
344
+ ### Cart
345
+ - [ ] Guest/user cart merge on login
346
+ - [ ] Price snapshot at add time
347
+ - [ ] Stock validation at checkout
348
+ - [ ] Cart expiration cleanup
349
+
350
+ ### Payment
351
+ - [ ] Idempotency key on all requests
352
+ - [ ] Webhook signature verification
353
+ - [ ] Duplicate event handling
354
+ - [ ] Timeout/retry strategy
355
+ - [ ] Refund flow tested
356
+
357
+ ### Inventory
358
+ - [ ] Two-phase reservation (reserve → commit/release)
359
+ - [ ] Atomic stock updates
360
+ - [ ] Reservation TTL and cleanup job
361
+ - [ ] Concurrency control tested