@comfanion/workflow 4.38.4-dev.1 → 4.39.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 (40) hide show
  1. package/package.json +1 -1
  2. package/src/build-info.json +2 -2
  3. package/src/opencode/agents/architect.md +8 -3
  4. package/src/opencode/agents/pm.md +9 -3
  5. package/src/opencode/gitignore +1 -0
  6. package/src/opencode/skills/acceptance-criteria/SKILL.md +58 -176
  7. package/src/opencode/skills/architecture-design/SKILL.md +86 -576
  8. package/src/opencode/skills/archiving/SKILL.md +60 -140
  9. package/src/opencode/skills/coding-standards/SKILL.md +113 -434
  10. package/src/opencode/skills/coding-standards/what-to-document.md +512 -0
  11. package/src/opencode/skills/database-design/SKILL.md +94 -778
  12. package/src/opencode/skills/database-design/indexing.md +187 -0
  13. package/src/opencode/skills/database-design/migrations.md +239 -0
  14. package/src/opencode/skills/database-design/schema-design.md +319 -0
  15. package/src/opencode/skills/doc-todo/SKILL.md +35 -27
  16. package/src/opencode/skills/epic-writing/SKILL.md +156 -244
  17. package/src/opencode/skills/epic-writing/template.md +11 -1
  18. package/src/opencode/skills/methodologies/SKILL.md +91 -354
  19. package/src/opencode/skills/methodologies/define.md +336 -0
  20. package/src/opencode/skills/methodologies/diagnose.md +374 -0
  21. package/src/opencode/skills/methodologies/empathize.md +253 -0
  22. package/src/opencode/skills/methodologies/ideate.md +458 -0
  23. package/src/opencode/skills/prd-writing/SKILL.md +162 -366
  24. package/src/opencode/skills/prd-writing/template.md +178 -48
  25. package/src/opencode/skills/requirements-gathering/SKILL.md +102 -117
  26. package/src/opencode/skills/requirements-gathering/template.md +97 -17
  27. package/src/opencode/skills/sprint-planning/SKILL.md +76 -225
  28. package/src/opencode/skills/sprint-planning/template.yaml +8 -0
  29. package/src/opencode/skills/story-writing/SKILL.md +76 -210
  30. package/src/opencode/skills/story-writing/template.md +10 -1
  31. package/src/opencode/skills/test-design/SKILL.md +78 -84
  32. package/src/opencode/skills/test-design/test-strategy.md +279 -0
  33. package/src/opencode/skills/test-design/unit-tests-mocking.md +247 -0
  34. package/src/opencode/skills/test-design/unit-tests-patterns.md +181 -0
  35. package/src/opencode/skills/test-design/unit-tests.md +117 -0
  36. package/src/opencode/skills/unit-writing/SKILL.md +119 -377
  37. package/src/opencode/skills/module-documentation/SKILL.md +0 -224
  38. package/src/opencode/skills/module-documentation/template.md +0 -139
  39. /package/src/opencode/skills/test-design/{template-integration.md → templates/template-integration.md} +0 -0
  40. /package/src/opencode/skills/test-design/{template-module.md → templates/template-module.md} +0 -0
@@ -0,0 +1,181 @@
1
+ # Unit Testing Patterns
2
+
3
+ Common patterns for writing effective unit tests.
4
+
5
+ ## Table-Driven Tests
6
+
7
+ Test multiple scenarios with same logic.
8
+
9
+ **Go Example:**
10
+ ```go
11
+ func TestValidateEmail(t *testing.T) {
12
+ tests := []struct {
13
+ name string
14
+ email string
15
+ wantErr bool
16
+ }{
17
+ {"valid", "test@example.com", false},
18
+ {"missing @", "testexample.com", true},
19
+ {"empty", "", true},
20
+ }
21
+
22
+ for _, tt := range tests {
23
+ t.Run(tt.name, func(t *testing.T) {
24
+ err := ValidateEmail(tt.email)
25
+ if (err != nil) != tt.wantErr {
26
+ t.Errorf("got error = %v, want %v", err, tt.wantErr)
27
+ }
28
+ })
29
+ }
30
+ }
31
+ ```
32
+
33
+ **TypeScript Example:**
34
+ ```typescript
35
+ describe('validateEmail', () => {
36
+ test.each([
37
+ { email: 'test@example.com', valid: true },
38
+ { email: 'testexample.com', valid: false },
39
+ { email: '', valid: false },
40
+ ])('validates $email', ({ email, valid }) => {
41
+ expect(validateEmail(email).isValid).toBe(valid);
42
+ });
43
+ });
44
+ ```
45
+
46
+ ---
47
+
48
+ ## State Transitions
49
+
50
+ Test state machine behavior.
51
+
52
+ ```typescript
53
+ describe('Order state transitions', () => {
54
+ it('transitions DRAFT → PENDING on submit', () => {
55
+ const order = new Order(); // DRAFT
56
+
57
+ order.submit();
58
+
59
+ expect(order.status).toBe('PENDING');
60
+ });
61
+
62
+ it('throws error on invalid transition', () => {
63
+ const order = new Order();
64
+ order.submit(); // DRAFT → PENDING
65
+
66
+ expect(() => order.submit()).toThrow('Invalid state');
67
+ });
68
+ });
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Validation Testing
74
+
75
+ Test input validation rules.
76
+
77
+ ```typescript
78
+ describe('Order validation', () => {
79
+ it('rejects empty items', () => {
80
+ const order = new Order();
81
+
82
+ const result = order.validate();
83
+
84
+ expect(result.isValid).toBe(false);
85
+ expect(result.errors).toContain('Order must have items');
86
+ });
87
+
88
+ it('rejects negative quantities', () => {
89
+ const order = new Order();
90
+ order.addItem({ price: 100, quantity: -1 });
91
+
92
+ const result = order.validate();
93
+
94
+ expect(result.errors).toContain('Quantity must be positive');
95
+ });
96
+ });
97
+ ```
98
+
99
+ ---
100
+
101
+ ## Error Handling
102
+
103
+ Test error scenarios and recovery.
104
+
105
+ ```typescript
106
+ describe('OrderService error handling', () => {
107
+ it('handles database errors', async () => {
108
+ const mockDb = {
109
+ save: jest.fn().mockRejectedValue(new Error('DB error'))
110
+ };
111
+ const service = new OrderService(mockDb);
112
+
113
+ await expect(service.createOrder(order))
114
+ .rejects.toThrow('Failed to create order');
115
+ });
116
+
117
+ it('retries on transient errors', async () => {
118
+ const mockDb = {
119
+ save: jest.fn()
120
+ .mockRejectedValueOnce(new Error('Timeout'))
121
+ .mockResolvedValueOnce({ id: '123' })
122
+ };
123
+
124
+ const result = await service.createOrder(order);
125
+
126
+ expect(result.id).toBe('123');
127
+ expect(mockDb.save).toHaveBeenCalledTimes(2);
128
+ });
129
+ });
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Boundary Testing
135
+
136
+ Test edge cases and limits.
137
+
138
+ ```typescript
139
+ describe('boundary conditions', () => {
140
+ it('handles empty input', () => {
141
+ expect(calculateTotal([])).toBe(0);
142
+ });
143
+
144
+ it('handles single item', () => {
145
+ expect(calculateTotal([{ price: 100 }])).toBe(100);
146
+ });
147
+
148
+ it('handles maximum items', () => {
149
+ const items = Array(1000).fill({ price: 1 });
150
+ expect(calculateTotal(items)).toBe(1000);
151
+ });
152
+
153
+ it('handles zero price', () => {
154
+ expect(calculateTotal([{ price: 0 }])).toBe(0);
155
+ });
156
+ });
157
+ ```
158
+
159
+ ---
160
+
161
+ ## Tips
162
+
163
+ **Table-driven tests:**
164
+ - Use for multiple input/output combinations
165
+ - Name each case clearly
166
+ - Include edge cases
167
+
168
+ **State transitions:**
169
+ - Test all valid transitions
170
+ - Test invalid transitions (should error)
171
+ - Verify state after transition
172
+
173
+ **Validation:**
174
+ - Test each validation rule separately
175
+ - Test combinations of errors
176
+ - Verify error messages
177
+
178
+ **Error handling:**
179
+ - Test error paths
180
+ - Test recovery/retry logic
181
+ - Verify error messages
@@ -0,0 +1,117 @@
1
+ # Unit Testing Guide
2
+
3
+ Unit tests verify individual components in isolation.
4
+
5
+ ## What to Test
6
+
7
+ ### ✅ Always Test
8
+ - **Public API** - Public methods, exported interfaces
9
+ - **Business Logic** - Domain rules, calculations, validations
10
+ - **Error Handling** - Invalid input, exceptions
11
+ - **Edge Cases** - Empty/null/zero, min/max, boundaries
12
+
13
+ ### ❌ Don't Test
14
+ - **Private methods** - Test through public API
15
+ - **Trivial code** - Getters/setters, pass-through
16
+ - **Framework internals** - Third-party libraries
17
+
18
+ ---
19
+
20
+ ## AAA Pattern
21
+
22
+ **Structure:** Arrange → Act → Assert
23
+
24
+ ```typescript
25
+ it('calculates order total', () => {
26
+ // Arrange - setup
27
+ const order = new Order();
28
+ order.addItem({ price: 100, quantity: 2 });
29
+
30
+ // Act - execute
31
+ const total = order.calculateTotal();
32
+
33
+ // Assert - verify
34
+ expect(total).toBe(200);
35
+ });
36
+ ```
37
+
38
+ ---
39
+
40
+ ## Test Naming
41
+
42
+ **Format:** `Test{Component}_{Method}_{Scenario}_{Expected}`
43
+
44
+ **Examples:**
45
+ ```
46
+ TestOrder_CalculateTotal_WithItems_ReturnsSum
47
+ TestOrder_CalculateTotal_EmptyOrder_ReturnsZero
48
+ TestOrder_AddItem_DuplicateSKU_MergesQuantity
49
+ ```
50
+
51
+ **TypeScript/Jest:**
52
+ ```typescript
53
+ describe('Order', () => {
54
+ describe('calculateTotal', () => {
55
+ it('returns sum when order has items', () => {});
56
+ it('returns zero when order is empty', () => {});
57
+ });
58
+ });
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Coverage Targets
64
+
65
+ | Layer | Target | Focus |
66
+ |-------|--------|-------|
67
+ | **Domain** | 80%+ | Business logic, rules |
68
+ | **Application** | 70%+ | Use cases |
69
+ | **Infrastructure** | 50%+ | Adapters |
70
+
71
+ **Don't chase 100%** - Focus on critical paths.
72
+
73
+ ---
74
+
75
+ ## Advanced Topics
76
+
77
+ **For more details, see:**
78
+ - [unit-tests-patterns.md](unit-tests-patterns.md) - Table-driven tests, state transitions, validation
79
+ - [unit-tests-mocking.md](unit-tests-mocking.md) - Mocking, dependency injection, test isolation
80
+
81
+ ---
82
+
83
+ ## Quick Example
84
+
85
+ ```typescript
86
+ describe('validateEmail', () => {
87
+ it('accepts valid email', () => {
88
+ expect(validateEmail('test@example.com').isValid).toBe(true);
89
+ });
90
+
91
+ it('rejects invalid email', () => {
92
+ expect(validateEmail('invalid').isValid).toBe(false);
93
+ });
94
+
95
+ it('rejects empty email', () => {
96
+ expect(validateEmail('').isValid).toBe(false);
97
+ });
98
+ });
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Tips
104
+
105
+ **Keep tests simple:**
106
+ - One assertion per test
107
+ - Clear test names
108
+ - Minimal setup
109
+
110
+ **Test behavior, not implementation:**
111
+ - Test what it does, not how
112
+ - Refactor shouldn't break tests
113
+
114
+ **Make tests fast:**
115
+ - No real I/O (mock it)
116
+ - No sleep/delays
117
+ - Parallel execution