@comfanion/workflow 4.38.4-dev.1 → 4.39.0-dev.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.
- package/package.json +1 -1
- package/src/build-info.json +2 -2
- package/src/opencode/skills/acceptance-criteria/SKILL.md +58 -176
- package/src/opencode/skills/architecture-design/SKILL.md +86 -576
- package/src/opencode/skills/archiving/SKILL.md +60 -140
- package/src/opencode/skills/coding-standards/SKILL.md +113 -434
- package/src/opencode/skills/coding-standards/what-to-document.md +512 -0
- package/src/opencode/skills/database-design/SKILL.md +94 -778
- package/src/opencode/skills/database-design/indexing.md +187 -0
- package/src/opencode/skills/database-design/migrations.md +239 -0
- package/src/opencode/skills/database-design/schema-design.md +319 -0
- package/src/opencode/skills/doc-todo/SKILL.md +35 -27
- package/src/opencode/skills/epic-writing/SKILL.md +156 -244
- package/src/opencode/skills/epic-writing/template.md +11 -1
- package/src/opencode/skills/methodologies/SKILL.md +91 -354
- package/src/opencode/skills/methodologies/define.md +336 -0
- package/src/opencode/skills/methodologies/diagnose.md +374 -0
- package/src/opencode/skills/methodologies/empathize.md +253 -0
- package/src/opencode/skills/methodologies/ideate.md +458 -0
- package/src/opencode/skills/prd-writing/SKILL.md +162 -366
- package/src/opencode/skills/prd-writing/template.md +178 -48
- package/src/opencode/skills/requirements-gathering/SKILL.md +102 -117
- package/src/opencode/skills/requirements-gathering/template.md +97 -17
- package/src/opencode/skills/sprint-planning/SKILL.md +76 -225
- package/src/opencode/skills/sprint-planning/template.yaml +8 -0
- package/src/opencode/skills/story-writing/SKILL.md +76 -210
- package/src/opencode/skills/story-writing/template.md +10 -1
- package/src/opencode/skills/test-design/SKILL.md +78 -84
- package/src/opencode/skills/test-design/test-strategy.md +279 -0
- package/src/opencode/skills/test-design/unit-tests-mocking.md +247 -0
- package/src/opencode/skills/test-design/unit-tests-patterns.md +181 -0
- package/src/opencode/skills/test-design/unit-tests.md +117 -0
- package/src/opencode/skills/unit-writing/SKILL.md +119 -377
- package/src/opencode/skills/module-documentation/SKILL.md +0 -224
- package/src/opencode/skills/module-documentation/template.md +0 -139
- /package/src/opencode/skills/test-design/{template-integration.md → templates/template-integration.md} +0 -0
- /package/src/opencode/skills/test-design/{template-module.md → templates/template-module.md} +0 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# Schema Design
|
|
2
|
+
|
|
3
|
+
How to design database schema: entities, relationships, normalization.
|
|
4
|
+
|
|
5
|
+
## Entities
|
|
6
|
+
|
|
7
|
+
**Types:**
|
|
8
|
+
- **Core entities:** Main business objects (users, orders, products)
|
|
9
|
+
- **Supporting entities:** Metadata, configuration (categories, tags)
|
|
10
|
+
- **Junction entities:** Many-to-many relationships (user_roles, product_categories)
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Relationships
|
|
15
|
+
|
|
16
|
+
### One-to-One (1:1)
|
|
17
|
+
**Implementation:** FK in either table OR same table
|
|
18
|
+
|
|
19
|
+
```sql
|
|
20
|
+
-- Option 1: FK in either table
|
|
21
|
+
CREATE TABLE users (id UUID PRIMARY KEY);
|
|
22
|
+
CREATE TABLE user_profiles (
|
|
23
|
+
id UUID PRIMARY KEY,
|
|
24
|
+
user_id UUID UNIQUE REFERENCES users(id)
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
-- Option 2: Same table
|
|
28
|
+
CREATE TABLE users (
|
|
29
|
+
id UUID PRIMARY KEY,
|
|
30
|
+
profile_data JSONB
|
|
31
|
+
);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### One-to-Many (1:N)
|
|
35
|
+
**Implementation:** FK in "many" side
|
|
36
|
+
|
|
37
|
+
```sql
|
|
38
|
+
CREATE TABLE users (id UUID PRIMARY KEY);
|
|
39
|
+
CREATE TABLE orders (
|
|
40
|
+
id UUID PRIMARY KEY,
|
|
41
|
+
user_id UUID NOT NULL REFERENCES users(id)
|
|
42
|
+
);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Many-to-Many (M:N)
|
|
46
|
+
**Implementation:** Junction table
|
|
47
|
+
|
|
48
|
+
```sql
|
|
49
|
+
CREATE TABLE users (id UUID PRIMARY KEY);
|
|
50
|
+
CREATE TABLE roles (id UUID PRIMARY KEY);
|
|
51
|
+
CREATE TABLE user_roles (
|
|
52
|
+
user_id UUID REFERENCES users(id),
|
|
53
|
+
role_id UUID REFERENCES roles(id),
|
|
54
|
+
PRIMARY KEY (user_id, role_id)
|
|
55
|
+
);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Hierarchy (Self-Referencing)
|
|
59
|
+
**Implementation:** Self-referencing FK OR nested set
|
|
60
|
+
|
|
61
|
+
```sql
|
|
62
|
+
-- Option 1: Self-referencing FK
|
|
63
|
+
CREATE TABLE categories (
|
|
64
|
+
id UUID PRIMARY KEY,
|
|
65
|
+
parent_id UUID REFERENCES categories(id),
|
|
66
|
+
name VARCHAR(255)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
-- Option 2: Nested set (for read-heavy)
|
|
70
|
+
CREATE TABLE categories (
|
|
71
|
+
id UUID PRIMARY KEY,
|
|
72
|
+
lft INT NOT NULL,
|
|
73
|
+
rgt INT NOT NULL,
|
|
74
|
+
name VARCHAR(255)
|
|
75
|
+
);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Polymorphic
|
|
79
|
+
**Implementation:** Type column + nullable FKs OR separate tables
|
|
80
|
+
|
|
81
|
+
```sql
|
|
82
|
+
-- Option 1: Type column (simple)
|
|
83
|
+
CREATE TABLE comments (
|
|
84
|
+
id UUID PRIMARY KEY,
|
|
85
|
+
commentable_type VARCHAR(50), -- 'post' or 'product'
|
|
86
|
+
commentable_id UUID,
|
|
87
|
+
content TEXT
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
-- Option 2: Separate tables (type-safe)
|
|
91
|
+
CREATE TABLE post_comments (
|
|
92
|
+
id UUID PRIMARY KEY,
|
|
93
|
+
post_id UUID REFERENCES posts(id),
|
|
94
|
+
content TEXT
|
|
95
|
+
);
|
|
96
|
+
CREATE TABLE product_comments (
|
|
97
|
+
id UUID PRIMARY KEY,
|
|
98
|
+
product_id UUID REFERENCES products(id),
|
|
99
|
+
content TEXT
|
|
100
|
+
);
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Normalization
|
|
106
|
+
|
|
107
|
+
### First Normal Form (1NF)
|
|
108
|
+
**Rule:** Atomic values, no arrays in columns
|
|
109
|
+
|
|
110
|
+
```sql
|
|
111
|
+
-- ❌ Bad (not 1NF)
|
|
112
|
+
CREATE TABLE users (
|
|
113
|
+
id UUID,
|
|
114
|
+
tags VARCHAR[] -- array!
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
-- ✅ Good (1NF)
|
|
118
|
+
CREATE TABLE users (id UUID);
|
|
119
|
+
CREATE TABLE user_tags (
|
|
120
|
+
user_id UUID REFERENCES users(id),
|
|
121
|
+
tag VARCHAR(50)
|
|
122
|
+
);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Second Normal Form (2NF)
|
|
126
|
+
**Rule:** No partial dependencies (all non-key depend on FULL PK)
|
|
127
|
+
|
|
128
|
+
```sql
|
|
129
|
+
-- ❌ Bad (not 2NF) - product_name depends only on product_id
|
|
130
|
+
CREATE TABLE order_items (
|
|
131
|
+
order_id UUID,
|
|
132
|
+
product_id UUID,
|
|
133
|
+
product_name VARCHAR(255), -- depends only on product_id!
|
|
134
|
+
quantity INT,
|
|
135
|
+
PRIMARY KEY (order_id, product_id)
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
-- ✅ Good (2NF)
|
|
139
|
+
CREATE TABLE order_items (
|
|
140
|
+
order_id UUID,
|
|
141
|
+
product_id UUID REFERENCES products(id),
|
|
142
|
+
quantity INT,
|
|
143
|
+
PRIMARY KEY (order_id, product_id)
|
|
144
|
+
);
|
|
145
|
+
CREATE TABLE products (
|
|
146
|
+
id UUID PRIMARY KEY,
|
|
147
|
+
name VARCHAR(255)
|
|
148
|
+
);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Third Normal Form (3NF)
|
|
152
|
+
**Rule:** No transitive dependencies (non-key don't depend on other non-key)
|
|
153
|
+
|
|
154
|
+
```sql
|
|
155
|
+
-- ❌ Bad (not 3NF) - city depends on zip_code
|
|
156
|
+
CREATE TABLE users (
|
|
157
|
+
id UUID PRIMARY KEY,
|
|
158
|
+
zip_code VARCHAR(10),
|
|
159
|
+
city VARCHAR(100) -- depends on zip_code!
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
-- ✅ Good (3NF)
|
|
163
|
+
CREATE TABLE users (
|
|
164
|
+
id UUID PRIMARY KEY,
|
|
165
|
+
zip_code VARCHAR(10) REFERENCES zip_codes(code)
|
|
166
|
+
);
|
|
167
|
+
CREATE TABLE zip_codes (
|
|
168
|
+
code VARCHAR(10) PRIMARY KEY,
|
|
169
|
+
city VARCHAR(100)
|
|
170
|
+
);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### When to Denormalize
|
|
174
|
+
|
|
175
|
+
**Reasons:**
|
|
176
|
+
- Read-heavy, rarely changes
|
|
177
|
+
- Reporting/analytics
|
|
178
|
+
- Cross-module data
|
|
179
|
+
- Computed values
|
|
180
|
+
|
|
181
|
+
**Rule:** Normalize first, denormalize with measured reason.
|
|
182
|
+
|
|
183
|
+
```sql
|
|
184
|
+
-- Denormalized for performance
|
|
185
|
+
CREATE TABLE orders (
|
|
186
|
+
id UUID PRIMARY KEY,
|
|
187
|
+
user_id UUID REFERENCES users(id),
|
|
188
|
+
user_email VARCHAR(255), -- denormalized from users
|
|
189
|
+
total DECIMAL(10,2) -- computed from order_items
|
|
190
|
+
);
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Naming Conventions
|
|
196
|
+
|
|
197
|
+
| Type | Convention | Example |
|
|
198
|
+
|------|------------|---------|
|
|
199
|
+
| Tables | plural, snake_case | users, order_items |
|
|
200
|
+
| Columns | snake_case | created_at, user_id |
|
|
201
|
+
| Primary Key | id | id UUID PRIMARY KEY |
|
|
202
|
+
| Foreign Key | {table}_id | user_id, order_id |
|
|
203
|
+
| Timestamps | *_at | created_at, updated_at |
|
|
204
|
+
| Boolean | is_*, has_* | is_active, has_permission |
|
|
205
|
+
| Junction | table1_table2 | user_roles, product_categories |
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Standard Columns
|
|
210
|
+
|
|
211
|
+
**Every table:**
|
|
212
|
+
```sql
|
|
213
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
214
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
215
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**Soft delete (optional):**
|
|
219
|
+
```sql
|
|
220
|
+
deleted_at TIMESTAMPTZ
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Multi-tenant (if needed):**
|
|
224
|
+
```sql
|
|
225
|
+
tenant_id UUID NOT NULL REFERENCES tenants(id)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Constraints
|
|
231
|
+
|
|
232
|
+
### NOT NULL
|
|
233
|
+
**Rule:** NOT NULL by default, NULL explicitly documented
|
|
234
|
+
|
|
235
|
+
```sql
|
|
236
|
+
CREATE TABLE users (
|
|
237
|
+
id UUID PRIMARY KEY,
|
|
238
|
+
email VARCHAR(255) NOT NULL, -- required
|
|
239
|
+
phone VARCHAR(50) -- optional (explicitly NULL)
|
|
240
|
+
);
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### CHECK
|
|
244
|
+
**Rule:** Validate data at database level
|
|
245
|
+
|
|
246
|
+
```sql
|
|
247
|
+
CREATE TABLE orders (
|
|
248
|
+
status VARCHAR(50) CHECK (status IN ('pending', 'paid', 'shipped')),
|
|
249
|
+
total DECIMAL(10,2) CHECK (total >= 0),
|
|
250
|
+
start_date DATE,
|
|
251
|
+
end_date DATE,
|
|
252
|
+
CHECK (start_date < end_date)
|
|
253
|
+
);
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### UNIQUE
|
|
257
|
+
**Rule:** Use for scoped uniqueness
|
|
258
|
+
|
|
259
|
+
```sql
|
|
260
|
+
-- Global uniqueness
|
|
261
|
+
CREATE TABLE users (
|
|
262
|
+
email VARCHAR(255) UNIQUE
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
-- Scoped uniqueness (per tenant)
|
|
266
|
+
CREATE TABLE users (
|
|
267
|
+
tenant_id UUID,
|
|
268
|
+
email VARCHAR(255),
|
|
269
|
+
UNIQUE (tenant_id, email)
|
|
270
|
+
);
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Example: Complete Table
|
|
276
|
+
|
|
277
|
+
```sql
|
|
278
|
+
CREATE TABLE orders (
|
|
279
|
+
-- Standard columns
|
|
280
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
281
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
282
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
283
|
+
|
|
284
|
+
-- Multi-tenancy
|
|
285
|
+
tenant_id UUID NOT NULL REFERENCES tenants(id),
|
|
286
|
+
|
|
287
|
+
-- Business columns
|
|
288
|
+
user_id UUID NOT NULL REFERENCES users(id),
|
|
289
|
+
status VARCHAR(50) NOT NULL
|
|
290
|
+
CHECK (status IN ('pending', 'paid', 'shipped', 'cancelled'))
|
|
291
|
+
DEFAULT 'pending',
|
|
292
|
+
total DECIMAL(10,2) NOT NULL CHECK (total >= 0),
|
|
293
|
+
|
|
294
|
+
-- Soft delete
|
|
295
|
+
deleted_at TIMESTAMPTZ,
|
|
296
|
+
|
|
297
|
+
-- Constraints
|
|
298
|
+
UNIQUE (tenant_id, id)
|
|
299
|
+
);
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Tips
|
|
305
|
+
|
|
306
|
+
**Start simple:**
|
|
307
|
+
- Normalize first
|
|
308
|
+
- Add constraints
|
|
309
|
+
- Test with real data
|
|
310
|
+
|
|
311
|
+
**Iterate:**
|
|
312
|
+
- Denormalize if needed
|
|
313
|
+
- Add indexes (see indexing.md)
|
|
314
|
+
- Optimize queries (see optimization.md)
|
|
315
|
+
|
|
316
|
+
**Document:**
|
|
317
|
+
- Why denormalized
|
|
318
|
+
- Why nullable
|
|
319
|
+
- Business rules
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: doc-todo
|
|
3
|
-
description: Use when adding TODO
|
|
3
|
+
description: Add structured TODO comments in code (TASK, STORY, EPIC, TECH_DEBT, FIXME, HACK) and documentation (DRAFT, EXPAND, RESEARCH, REVIEW, DECISION). Use when marking incomplete work, adding placeholders, tracking future tasks, or when user mentions "TODO", "placeholder", "future work", "incomplete", or "mark for later".
|
|
4
4
|
license: MIT
|
|
5
5
|
compatibility: opencode
|
|
6
6
|
metadata:
|
|
@@ -8,37 +8,45 @@ metadata:
|
|
|
8
8
|
agents: [all]
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
# TODO Placeholders
|
|
11
|
+
# TODO Placeholders Skill
|
|
12
|
+
|
|
13
|
+
```xml
|
|
14
|
+
<doc_todo>
|
|
15
|
+
<definition>Mark incomplete work with structured TODOs</definition>
|
|
16
|
+
|
|
17
|
+
<code>
|
|
18
|
+
<format>// TODO({type}:{id}): {description}</format>
|
|
19
|
+
<types>TASK, STORY, EPIC, BACKLOG, TECH_DEBT, FIXME, HACK</types>
|
|
20
|
+
<require_id>true (except BACKLOG, HACK)</require_id>
|
|
21
|
+
</code>
|
|
22
|
+
|
|
23
|
+
<docs>
|
|
24
|
+
<format><!-- TODO({type}): {description} --></format>
|
|
25
|
+
<types>DRAFT, EXPAND, RESEARCH, REVIEW, DECISION, EXAMPLE, DIAGRAM</types>
|
|
26
|
+
</docs>
|
|
27
|
+
|
|
28
|
+
<rules>
|
|
29
|
+
<specific>Be specific: "add validation" not "fix"</specific>
|
|
30
|
+
<track>Don't leave TODOs forever - resolve or convert to tasks</track>
|
|
31
|
+
</rules>
|
|
32
|
+
</doc_todo>
|
|
33
|
+
```
|
|
12
34
|
|
|
13
|
-
|
|
35
|
+
---
|
|
14
36
|
|
|
15
|
-
##
|
|
37
|
+
## Examples
|
|
16
38
|
|
|
39
|
+
```go
|
|
40
|
+
// TODO(TASK:T01-03): Implement email validation
|
|
41
|
+
// TODO(BACKLOG): Consider caching layer
|
|
42
|
+
// FIXME(TASK:T02-01): Fix race condition
|
|
43
|
+
// HACK: Temporary workaround until API v2
|
|
17
44
|
```
|
|
18
|
-
// TODO: description
|
|
19
|
-
// TODO(STORY-123): description with ticket
|
|
20
|
-
// FIXME: known bug
|
|
21
|
-
// HACK: temporary workaround
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## In Documentation
|
|
25
45
|
|
|
26
46
|
```markdown
|
|
27
|
-
<!-- TODO:
|
|
28
|
-
<!-- TODO(DECISION):
|
|
47
|
+
<!-- TODO(DRAFT): Section needs review -->
|
|
48
|
+
<!-- TODO(DECISION): Choose PostgreSQL or MongoDB -->
|
|
49
|
+
<!-- TODO(DIAGRAM): Add sequence diagram -->
|
|
29
50
|
```
|
|
30
51
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
| Type | Use for |
|
|
34
|
-
|------|---------|
|
|
35
|
-
| `TODO` | General incomplete work |
|
|
36
|
-
| `FIXME` | Known bug to fix |
|
|
37
|
-
| `HACK` | Temporary workaround |
|
|
38
|
-
| `NOTE` | Important context |
|
|
39
|
-
|
|
40
|
-
## Best Practices
|
|
41
|
-
|
|
42
|
-
- Be specific: `TODO: add validation` not `TODO: fix`
|
|
43
|
-
- Add ticket if exists: `TODO(PROJ-123): ...`
|
|
44
|
-
- Don't leave TODOs forever - track and resolve
|
|
52
|
+
See `config.yaml` for full configuration.
|