@comfanion/workflow 3.0.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/README.md +185 -0
- package/bin/cli.js +406 -0
- package/package.json +50 -0
- package/src/build-info.json +16 -0
- package/src/opencode/ARCHITECTURE.md +255 -0
- package/src/opencode/FLOW.yaml +900 -0
- package/src/opencode/agents/analyst.md +141 -0
- package/src/opencode/agents/architect.md +177 -0
- package/src/opencode/agents/change-manager.md +263 -0
- package/src/opencode/agents/dev.md +171 -0
- package/src/opencode/agents/module-docs.md +628 -0
- package/src/opencode/agents/pm.md +157 -0
- package/src/opencode/agents/researcher.md +254 -0
- package/src/opencode/agents/sm.md +184 -0
- package/src/opencode/agents/workflow-orchestrator.md +249 -0
- package/src/opencode/checklists/architecture-checklist.md +166 -0
- package/src/opencode/checklists/code-review-checklist.md +151 -0
- package/src/opencode/checklists/prd-checklist.md +140 -0
- package/src/opencode/checklists/requirements-checklist.md +86 -0
- package/src/opencode/checklists/story-checklist.md +137 -0
- package/src/opencode/commands/architecture.md +68 -0
- package/src/opencode/commands/archive.md +146 -0
- package/src/opencode/commands/change.md +169 -0
- package/src/opencode/commands/clarify.md +132 -0
- package/src/opencode/commands/code-review.md +96 -0
- package/src/opencode/commands/coding-standards.md +102 -0
- package/src/opencode/commands/dev-story.md +80 -0
- package/src/opencode/commands/diagram.md +152 -0
- package/src/opencode/commands/epics.md +52 -0
- package/src/opencode/commands/help.md +139 -0
- package/src/opencode/commands/jira-sync.md +58 -0
- package/src/opencode/commands/module-docs.md +158 -0
- package/src/opencode/commands/prd.md +63 -0
- package/src/opencode/commands/quick.md +166 -0
- package/src/opencode/commands/requirements.md +49 -0
- package/src/opencode/commands/research.md +113 -0
- package/src/opencode/commands/sprint-plan.md +59 -0
- package/src/opencode/commands/stories.md +61 -0
- package/src/opencode/commands/validate.md +84 -0
- package/src/opencode/commands/workflow-status.md +150 -0
- package/src/opencode/config.yaml +223 -0
- package/src/opencode/opencode.json +36 -0
- package/src/opencode/skills/acceptance-criteria/SKILL.md +212 -0
- package/src/opencode/skills/adr-writing/SKILL.md +241 -0
- package/src/opencode/skills/architecture-design/SKILL.md +183 -0
- package/src/opencode/skills/architecture-validation/SKILL.md +199 -0
- package/src/opencode/skills/archiving/SKILL.md +191 -0
- package/src/opencode/skills/changelog/SKILL.md +280 -0
- package/src/opencode/skills/code-review/SKILL.md +193 -0
- package/src/opencode/skills/coding-standards/SKILL.md +430 -0
- package/src/opencode/skills/diagram-creation/SKILL.md +273 -0
- package/src/opencode/skills/doc-todo/SKILL.md +325 -0
- package/src/opencode/skills/epic-writing/SKILL.md +291 -0
- package/src/opencode/skills/jira-integration/SKILL.md +560 -0
- package/src/opencode/skills/methodologies/SKILL.md +376 -0
- package/src/opencode/skills/module-documentation/SKILL.md +214 -0
- package/src/opencode/skills/prd-validation/SKILL.md +164 -0
- package/src/opencode/skills/prd-writing/SKILL.md +104 -0
- package/src/opencode/skills/requirements-gathering/SKILL.md +132 -0
- package/src/opencode/skills/requirements-validation/SKILL.md +141 -0
- package/src/opencode/skills/research-methodology/SKILL.md +140 -0
- package/src/opencode/skills/sprint-planning/SKILL.md +217 -0
- package/src/opencode/skills/story-writing/SKILL.md +574 -0
- package/src/opencode/skills/test-design/SKILL.md +313 -0
- package/src/opencode/skills/translation/SKILL.md +411 -0
- package/src/opencode/templates/CHANGELOG.md +82 -0
- package/src/opencode/templates/adr-template.md +115 -0
- package/src/opencode/templates/architecture-template.md +362 -0
- package/src/opencode/templates/change-proposal-template.md +186 -0
- package/src/opencode/templates/epic-template.md +151 -0
- package/src/opencode/templates/git-workflow-template.md +384 -0
- package/src/opencode/templates/integration-tests-template.md +265 -0
- package/src/opencode/templates/jira-cache-template.yaml +103 -0
- package/src/opencode/templates/module-index-template.md +139 -0
- package/src/opencode/templates/module-test-cases-template.md +230 -0
- package/src/opencode/templates/prd-acceptance-criteria-template.md +124 -0
- package/src/opencode/templates/prd-template.md +479 -0
- package/src/opencode/templates/requirements-template.md +132 -0
- package/src/opencode/templates/sprint-status-template.yaml +84 -0
- package/src/opencode/templates/story-template.md +437 -0
- package/src/opencode/templates/testing-standards-template.md +359 -0
- package/src/opencode/workflows/dev-story/instructions.md +529 -0
- package/src/repo-structure/.gitattributes +64 -0
- package/src/repo-structure/CONTRIBUTING.md +182 -0
- package/src/repo-structure/README.md +77 -0
- package/src/repo-structure/docs/README.md +62 -0
- package/src/repo-structure/docs/api/README.md +43 -0
- package/src/repo-structure/docs/architecture/README.md +36 -0
- package/src/repo-structure/docs/architecture/adr/README.md +53 -0
- package/src/repo-structure/docs/architecture/diagrams/README.md +59 -0
- package/src/repo-structure/docs/coding-standards/README.md +52 -0
- package/src/repo-structure/docs/confluence/README.md +43 -0
- package/src/repo-structure/docs/requirements/README.md +28 -0
- package/src/repo-structure/docs/sprint-artifacts/README.md +76 -0
- package/src/repo-structure/docs/sprint-artifacts/backlog/README.md +24 -0
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# Test Design Skill
|
|
2
|
+
|
|
3
|
+
How to design and write effective tests for implementations.
|
|
4
|
+
|
|
5
|
+
## Test Pyramid
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/\
|
|
9
|
+
/ \ E2E Tests (few)
|
|
10
|
+
/----\
|
|
11
|
+
/ \ Integration Tests (some)
|
|
12
|
+
/--------\
|
|
13
|
+
/ \ Unit Tests (many)
|
|
14
|
+
/------------\
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Unit Tests
|
|
18
|
+
|
|
19
|
+
### When to Write
|
|
20
|
+
- Every public function
|
|
21
|
+
- Every method with business logic
|
|
22
|
+
- Edge cases and error paths
|
|
23
|
+
|
|
24
|
+
### Structure (Arrange-Act-Assert)
|
|
25
|
+
|
|
26
|
+
```go
|
|
27
|
+
func TestFunction_Scenario_ExpectedBehavior(t *testing.T) {
|
|
28
|
+
// Arrange - Setup test data
|
|
29
|
+
input := createTestInput()
|
|
30
|
+
expected := expectedOutput()
|
|
31
|
+
sut := NewSystemUnderTest()
|
|
32
|
+
|
|
33
|
+
// Act - Execute the function
|
|
34
|
+
result, err := sut.Function(input)
|
|
35
|
+
|
|
36
|
+
// Assert - Verify the outcome
|
|
37
|
+
if err != nil {
|
|
38
|
+
t.Fatalf("unexpected error: %v", err)
|
|
39
|
+
}
|
|
40
|
+
if result != expected {
|
|
41
|
+
t.Errorf("got %v, want %v", result, expected)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Naming Convention
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
Test{Type}_{Method}_{Scenario}
|
|
50
|
+
|
|
51
|
+
Examples:
|
|
52
|
+
- TestOffer_UpdatePrice_Success
|
|
53
|
+
- TestOffer_UpdatePrice_NegativePrice_ReturnsError
|
|
54
|
+
- TestOffer_Activate_FromPendingStatus_Success
|
|
55
|
+
- TestOffer_Activate_FromDeclinedStatus_Fails
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Table-Driven Tests
|
|
59
|
+
|
|
60
|
+
```go
|
|
61
|
+
func TestOffer_Validate(t *testing.T) {
|
|
62
|
+
tests := []struct {
|
|
63
|
+
name string
|
|
64
|
+
offer Offer
|
|
65
|
+
wantErr bool
|
|
66
|
+
}{
|
|
67
|
+
{
|
|
68
|
+
name: "valid offer",
|
|
69
|
+
offer: validOffer(),
|
|
70
|
+
wantErr: false,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "zero price",
|
|
74
|
+
offer: offerWithZeroPrice(),
|
|
75
|
+
wantErr: true,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: "negative quantity",
|
|
79
|
+
offer: offerWithNegativeQty(),
|
|
80
|
+
wantErr: true,
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
for _, tt := range tests {
|
|
85
|
+
t.Run(tt.name, func(t *testing.T) {
|
|
86
|
+
err := tt.offer.Validate()
|
|
87
|
+
if (err != nil) != tt.wantErr {
|
|
88
|
+
t.Errorf("Validate() error = %v, wantErr %v", err, tt.wantErr)
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Integration Tests
|
|
96
|
+
|
|
97
|
+
### When to Write
|
|
98
|
+
- Repository implementations
|
|
99
|
+
- API endpoints
|
|
100
|
+
- External service integrations
|
|
101
|
+
- Multi-component workflows
|
|
102
|
+
|
|
103
|
+
### Setup/Teardown
|
|
104
|
+
|
|
105
|
+
```go
|
|
106
|
+
func TestMain(m *testing.M) {
|
|
107
|
+
// Setup
|
|
108
|
+
testDB = setupTestDatabase()
|
|
109
|
+
|
|
110
|
+
// Run tests
|
|
111
|
+
code := m.Run()
|
|
112
|
+
|
|
113
|
+
// Teardown
|
|
114
|
+
teardownTestDatabase(testDB)
|
|
115
|
+
|
|
116
|
+
os.Exit(code)
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Test Isolation
|
|
121
|
+
|
|
122
|
+
```go
|
|
123
|
+
func TestRepository_Save(t *testing.T) {
|
|
124
|
+
// Use transaction that rolls back
|
|
125
|
+
tx := testDB.Begin()
|
|
126
|
+
defer tx.Rollback()
|
|
127
|
+
|
|
128
|
+
repo := NewRepository(tx)
|
|
129
|
+
|
|
130
|
+
// Test code here
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Test Coverage Requirements
|
|
135
|
+
|
|
136
|
+
| Type | Minimum Coverage |
|
|
137
|
+
|------|-----------------|
|
|
138
|
+
| Domain/Business Logic | 80%+ |
|
|
139
|
+
| Use Cases/Handlers | 70%+ |
|
|
140
|
+
| Repositories | 60%+ |
|
|
141
|
+
| HTTP Handlers | 50%+ |
|
|
142
|
+
|
|
143
|
+
## What to Test
|
|
144
|
+
|
|
145
|
+
### Domain Layer
|
|
146
|
+
- All aggregate methods
|
|
147
|
+
- All value object validation
|
|
148
|
+
- Domain service logic
|
|
149
|
+
- State transitions
|
|
150
|
+
|
|
151
|
+
### Application Layer
|
|
152
|
+
- Use case happy paths
|
|
153
|
+
- Error scenarios
|
|
154
|
+
- Validation failures
|
|
155
|
+
- Authorization checks
|
|
156
|
+
|
|
157
|
+
### Infrastructure Layer
|
|
158
|
+
- Repository CRUD operations
|
|
159
|
+
- External service adapters
|
|
160
|
+
- Event publishing/consuming
|
|
161
|
+
|
|
162
|
+
## What NOT to Test
|
|
163
|
+
|
|
164
|
+
- Private functions (test via public interface)
|
|
165
|
+
- Simple getters/setters
|
|
166
|
+
- Framework code
|
|
167
|
+
- Generated code (SQLC, etc.)
|
|
168
|
+
|
|
169
|
+
## Mocking
|
|
170
|
+
|
|
171
|
+
### When to Mock
|
|
172
|
+
- External services
|
|
173
|
+
- Databases (for unit tests)
|
|
174
|
+
- Time-dependent operations
|
|
175
|
+
- Random/non-deterministic operations
|
|
176
|
+
|
|
177
|
+
### Interface-Based Mocking
|
|
178
|
+
|
|
179
|
+
```go
|
|
180
|
+
// Define interface
|
|
181
|
+
type UserRepository interface {
|
|
182
|
+
FindByID(ctx context.Context, id string) (*User, error)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Create mock
|
|
186
|
+
type MockUserRepository struct {
|
|
187
|
+
FindByIDFunc func(ctx context.Context, id string) (*User, error)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
func (m *MockUserRepository) FindByID(ctx context.Context, id string) (*User, error) {
|
|
191
|
+
return m.FindByIDFunc(ctx, id)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Use in test
|
|
195
|
+
func TestUseCase(t *testing.T) {
|
|
196
|
+
mockRepo := &MockUserRepository{
|
|
197
|
+
FindByIDFunc: func(ctx context.Context, id string) (*User, error) {
|
|
198
|
+
return &User{ID: id, Name: "Test"}, nil
|
|
199
|
+
},
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
useCase := NewUseCase(mockRepo)
|
|
203
|
+
// ...
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Test Data
|
|
208
|
+
|
|
209
|
+
### Builders
|
|
210
|
+
|
|
211
|
+
```go
|
|
212
|
+
func NewTestOffer() *Offer {
|
|
213
|
+
return &Offer{
|
|
214
|
+
ID: NewOfferID(),
|
|
215
|
+
MerchantID: NewMerchantID(),
|
|
216
|
+
Price: decimal.NewFromInt(100),
|
|
217
|
+
Status: OfferStatusPending,
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
func (o *Offer) WithPrice(price decimal.Decimal) *Offer {
|
|
222
|
+
o.Price = price
|
|
223
|
+
return o
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
func (o *Offer) WithStatus(status OfferStatus) *Offer {
|
|
227
|
+
o.Status = status
|
|
228
|
+
return o
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Usage
|
|
232
|
+
offer := NewTestOffer().WithPrice(decimal.NewFromInt(200)).WithStatus(OfferStatusActive)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Red-Green-Refactor Cycle
|
|
236
|
+
|
|
237
|
+
### 1. RED - Write Failing Test
|
|
238
|
+
|
|
239
|
+
```go
|
|
240
|
+
func TestOffer_UpdatePrice_Success(t *testing.T) {
|
|
241
|
+
offer := NewTestOffer()
|
|
242
|
+
newPrice := decimal.NewFromInt(150)
|
|
243
|
+
|
|
244
|
+
err := offer.UpdatePrice(newPrice)
|
|
245
|
+
|
|
246
|
+
if err != nil {
|
|
247
|
+
t.Fatalf("unexpected error: %v", err)
|
|
248
|
+
}
|
|
249
|
+
if !offer.Price.Equal(newPrice) {
|
|
250
|
+
t.Errorf("price not updated")
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Run test - it should FAIL.
|
|
256
|
+
|
|
257
|
+
### 2. GREEN - Minimal Implementation
|
|
258
|
+
|
|
259
|
+
```go
|
|
260
|
+
func (o *Offer) UpdatePrice(price decimal.Decimal) error {
|
|
261
|
+
o.Price = price
|
|
262
|
+
return nil
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Run test - it should PASS.
|
|
267
|
+
|
|
268
|
+
### 3. REFACTOR - Improve Code
|
|
269
|
+
|
|
270
|
+
```go
|
|
271
|
+
func (o *Offer) UpdatePrice(price decimal.Decimal) error {
|
|
272
|
+
if price.LessThanOrEqual(decimal.Zero) {
|
|
273
|
+
return ErrInvalidPrice
|
|
274
|
+
}
|
|
275
|
+
o.Price = price
|
|
276
|
+
return nil
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Run test - it should still PASS.
|
|
281
|
+
|
|
282
|
+
Add test for new validation:
|
|
283
|
+
|
|
284
|
+
```go
|
|
285
|
+
func TestOffer_UpdatePrice_ZeroPrice_ReturnsError(t *testing.T) {
|
|
286
|
+
offer := NewTestOffer()
|
|
287
|
+
|
|
288
|
+
err := offer.UpdatePrice(decimal.Zero)
|
|
289
|
+
|
|
290
|
+
if !errors.Is(err, ErrInvalidPrice) {
|
|
291
|
+
t.Errorf("expected ErrInvalidPrice, got %v", err)
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Test Commands
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
# Run all tests
|
|
300
|
+
go test ./...
|
|
301
|
+
|
|
302
|
+
# Run with coverage
|
|
303
|
+
go test -cover ./...
|
|
304
|
+
|
|
305
|
+
# Run specific test
|
|
306
|
+
go test -run TestOffer_UpdatePrice ./...
|
|
307
|
+
|
|
308
|
+
# Run with race detection
|
|
309
|
+
go test -race ./...
|
|
310
|
+
|
|
311
|
+
# Verbose output
|
|
312
|
+
go test -v ./...
|
|
313
|
+
```
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# Translation & Export Skill
|
|
2
|
+
|
|
3
|
+
> **Purpose**: Translate technical docs to user language, export to Confluence format
|
|
4
|
+
> **Used by**: Any agent on request
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Principle
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
12
|
+
│ DOCUMENTATION FLOW │
|
|
13
|
+
├─────────────────────────────────────────────────────────────────┤
|
|
14
|
+
│ │
|
|
15
|
+
│ docs/ (English) docs/confluence/ (User Language) │
|
|
16
|
+
│ ──────────────── ──────────────────────────────── │
|
|
17
|
+
│ • prd.md → • prd-uk.md (Ukrainian) │
|
|
18
|
+
│ • architecture.md → • architecture-uk.confluence │
|
|
19
|
+
│ • epic-01.md → • epic-01-uk.md (Ukrainian) │
|
|
20
|
+
│ │
|
|
21
|
+
│ ALWAYS English Translated + Reformatted │
|
|
22
|
+
│ (agents work here) (stakeholders read here) │
|
|
23
|
+
│ │
|
|
24
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Rule:** Technical docs in `docs/` are ALWAYS in English. Translations go to `docs/confluence/`.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Configuration
|
|
32
|
+
|
|
33
|
+
```yaml
|
|
34
|
+
# config.yaml
|
|
35
|
+
documentation:
|
|
36
|
+
technical:
|
|
37
|
+
language: "English"
|
|
38
|
+
enforced: true
|
|
39
|
+
|
|
40
|
+
user_facing:
|
|
41
|
+
enabled: true
|
|
42
|
+
output_folder: "docs/confluence/"
|
|
43
|
+
default_language: "Ukrainian"
|
|
44
|
+
formats: [confluence, markdown, html]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Output Formats
|
|
50
|
+
|
|
51
|
+
### 1. Confluence Wiki Format
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
docs/confluence/
|
|
55
|
+
├── prd-uk.confluence # Confluence markup
|
|
56
|
+
├── architecture-uk.confluence
|
|
57
|
+
└── assets/
|
|
58
|
+
└── diagrams/
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Confluence Markup:**
|
|
62
|
+
```
|
|
63
|
+
h1. Назва продукту - PRD
|
|
64
|
+
|
|
65
|
+
h2. Огляд
|
|
66
|
+
|
|
67
|
+
Цей документ описує вимоги до системи...
|
|
68
|
+
|
|
69
|
+
h3. Функціональні вимоги
|
|
70
|
+
|
|
71
|
+
|| ID || Вимога || Пріоритет ||
|
|
72
|
+
| FR-001 | Реєстрація користувача | P0 |
|
|
73
|
+
| FR-002 | Авторизація | P0 |
|
|
74
|
+
|
|
75
|
+
{info}
|
|
76
|
+
Важлива примітка для команди
|
|
77
|
+
{info}
|
|
78
|
+
|
|
79
|
+
{code}
|
|
80
|
+
// Code example
|
|
81
|
+
{code}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 2. Translated Markdown
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
docs/confluence/
|
|
88
|
+
├── prd-uk.md # Ukrainian markdown
|
|
89
|
+
├── architecture-uk.md
|
|
90
|
+
└── epic-01-uk.md
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 3. Standalone HTML
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
docs/confluence/
|
|
97
|
+
├── html/
|
|
98
|
+
│ ├── prd-uk.html
|
|
99
|
+
│ └── style.css
|
|
100
|
+
```
|
|
101
|
+
confluence/
|
|
102
|
+
├── html/
|
|
103
|
+
│ ├── prd-uk.html
|
|
104
|
+
│ ├── style.css
|
|
105
|
+
│ └── assets/
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Translation Rules
|
|
111
|
+
|
|
112
|
+
### What to Translate
|
|
113
|
+
|
|
114
|
+
| Content | Translate? | Notes |
|
|
115
|
+
|---------|------------|-------|
|
|
116
|
+
| Headers | ✅ Yes | |
|
|
117
|
+
| Descriptions | ✅ Yes | |
|
|
118
|
+
| User stories | ✅ Yes | "As a... I want... So that..." |
|
|
119
|
+
| Acceptance criteria | ✅ Yes | Given/When/Then |
|
|
120
|
+
| Technical terms | ⚠️ Keep English | API, endpoint, cache, etc. |
|
|
121
|
+
| Code blocks | ❌ No | Keep original |
|
|
122
|
+
| File paths | ❌ No | Keep original |
|
|
123
|
+
| Variable names | ❌ No | Keep original |
|
|
124
|
+
| Jira IDs | ❌ No | PROJ-123 stays PROJ-123 |
|
|
125
|
+
|
|
126
|
+
### Technical Terms (Keep in English)
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
API, REST, GraphQL, endpoint, request, response,
|
|
130
|
+
cache, database, schema, migration, query,
|
|
131
|
+
repository, service, handler, middleware,
|
|
132
|
+
authentication, authorization, token, JWT,
|
|
133
|
+
deploy, CI/CD, pipeline, container, Docker,
|
|
134
|
+
Kafka, Redis, PostgreSQL, MongoDB
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Translation Examples
|
|
138
|
+
|
|
139
|
+
**English (source):**
|
|
140
|
+
```markdown
|
|
141
|
+
## FR-001: User Registration
|
|
142
|
+
|
|
143
|
+
**As a** new user,
|
|
144
|
+
**I want** to register with email and password,
|
|
145
|
+
**So that** I can access the platform.
|
|
146
|
+
|
|
147
|
+
### Acceptance Criteria
|
|
148
|
+
|
|
149
|
+
**Given** a valid email and password
|
|
150
|
+
**When** user submits registration form
|
|
151
|
+
**Then** account is created and confirmation email sent
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Ukrainian (translated):**
|
|
155
|
+
```markdown
|
|
156
|
+
## FR-001: Реєстрація користувача
|
|
157
|
+
|
|
158
|
+
**Як** новий користувач,
|
|
159
|
+
**Я хочу** зареєструватися за допомогою email та пароля,
|
|
160
|
+
**Щоб** отримати доступ до платформи.
|
|
161
|
+
|
|
162
|
+
### Критерії приймання
|
|
163
|
+
|
|
164
|
+
**Дано** валідний email та пароль
|
|
165
|
+
**Коли** користувач відправляє форму реєстрації
|
|
166
|
+
**Тоді** створюється обліковий запис і надсилається лист підтвердження
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Workflow
|
|
172
|
+
|
|
173
|
+
### Command: `/translate [doc] [language]`
|
|
174
|
+
|
|
175
|
+
```xml
|
|
176
|
+
<workflow name="translate-document">
|
|
177
|
+
<step n="1" goal="Identify source document">
|
|
178
|
+
<check if="doc path provided">
|
|
179
|
+
<action>Use provided path</action>
|
|
180
|
+
</check>
|
|
181
|
+
<check else>
|
|
182
|
+
<output>
|
|
183
|
+
Available documents for translation:
|
|
184
|
+
1. docs/prd.md
|
|
185
|
+
2. docs/architecture.md
|
|
186
|
+
3. docs/sprint-artifacts/sprint-1/epic-01.md
|
|
187
|
+
</output>
|
|
188
|
+
<ask>Which document to translate?</ask>
|
|
189
|
+
</check>
|
|
190
|
+
</step>
|
|
191
|
+
|
|
192
|
+
<step n="2" goal="Select target language">
|
|
193
|
+
<check if="language provided">
|
|
194
|
+
<action>Use provided language</action>
|
|
195
|
+
</check>
|
|
196
|
+
<check else>
|
|
197
|
+
<action>Use default from config: {{default_language}}</action>
|
|
198
|
+
<ask>Translate to {{default_language}}? (y/n or specify language)</ask>
|
|
199
|
+
</check>
|
|
200
|
+
</step>
|
|
201
|
+
|
|
202
|
+
<step n="3" goal="Select output format">
|
|
203
|
+
<output>
|
|
204
|
+
Output formats:
|
|
205
|
+
1. Confluence wiki markup (.confluence)
|
|
206
|
+
2. Markdown (.md)
|
|
207
|
+
3. HTML (.html)
|
|
208
|
+
4. All formats
|
|
209
|
+
</output>
|
|
210
|
+
<ask>Select format:</ask>
|
|
211
|
+
</step>
|
|
212
|
+
|
|
213
|
+
<step n="4" goal="Translate">
|
|
214
|
+
<action>Read source document</action>
|
|
215
|
+
<action>Translate content (preserve technical terms)</action>
|
|
216
|
+
<action>Convert to target format</action>
|
|
217
|
+
<action>Save to docs/confluence/ folder</action>
|
|
218
|
+
|
|
219
|
+
<output>
|
|
220
|
+
✅ Translation complete:
|
|
221
|
+
|
|
222
|
+
Source: docs/prd.md (English)
|
|
223
|
+
Output: docs/confluence/prd-uk.confluence (Ukrainian)
|
|
224
|
+
|
|
225
|
+
Sections translated: 15
|
|
226
|
+
Technical terms preserved: 23
|
|
227
|
+
</output>
|
|
228
|
+
</step>
|
|
229
|
+
</workflow>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Command: `/export-confluence`
|
|
233
|
+
|
|
234
|
+
Batch export all configured documents:
|
|
235
|
+
|
|
236
|
+
```xml
|
|
237
|
+
<workflow name="export-confluence">
|
|
238
|
+
<step n="1" goal="Read config">
|
|
239
|
+
<action>Get documents marked for translation</action>
|
|
240
|
+
<action>Get target language</action>
|
|
241
|
+
</step>
|
|
242
|
+
|
|
243
|
+
<step n="2" goal="Translate all">
|
|
244
|
+
<for-each doc in="translate_list">
|
|
245
|
+
<action>Translate to target language</action>
|
|
246
|
+
<action>Generate Confluence format</action>
|
|
247
|
+
<action>Save to docs/confluence/</action>
|
|
248
|
+
</for-each>
|
|
249
|
+
</step>
|
|
250
|
+
|
|
251
|
+
<step n="3" goal="Generate index">
|
|
252
|
+
<action>Create docs/confluence/README.md with links to all translated docs</action>
|
|
253
|
+
</step>
|
|
254
|
+
|
|
255
|
+
<output>
|
|
256
|
+
✅ Export complete:
|
|
257
|
+
|
|
258
|
+
Documents translated: 5
|
|
259
|
+
Target language: Ukrainian
|
|
260
|
+
Output folder: docs/confluence/
|
|
261
|
+
|
|
262
|
+
Files created:
|
|
263
|
+
- docs/confluence/prd-uk.confluence
|
|
264
|
+
- docs/confluence/architecture-uk.confluence
|
|
265
|
+
- docs/confluence/epic-01-uk.confluence
|
|
266
|
+
- docs/confluence/epic-02-uk.confluence
|
|
267
|
+
- docs/confluence/README.md
|
|
268
|
+
</output>
|
|
269
|
+
</workflow>
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Confluence Format Reference
|
|
275
|
+
|
|
276
|
+
### Headers
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
h1. Header 1
|
|
280
|
+
h2. Header 2
|
|
281
|
+
h3. Header 3
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Tables
|
|
285
|
+
|
|
286
|
+
```
|
|
287
|
+
|| Header 1 || Header 2 || Header 3 ||
|
|
288
|
+
| Cell 1 | Cell 2 | Cell 3 |
|
|
289
|
+
| Cell 4 | Cell 5 | Cell 6 |
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Lists
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
* Bullet item
|
|
296
|
+
** Nested bullet
|
|
297
|
+
|
|
298
|
+
# Numbered item
|
|
299
|
+
## Nested numbered
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Code Blocks
|
|
303
|
+
|
|
304
|
+
```
|
|
305
|
+
{code:language=go|title=Example}
|
|
306
|
+
func main() {
|
|
307
|
+
fmt.Println("Hello")
|
|
308
|
+
}
|
|
309
|
+
{code}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Panels
|
|
313
|
+
|
|
314
|
+
```
|
|
315
|
+
{info}
|
|
316
|
+
Information panel
|
|
317
|
+
{info}
|
|
318
|
+
|
|
319
|
+
{warning}
|
|
320
|
+
Warning panel
|
|
321
|
+
{warning}
|
|
322
|
+
|
|
323
|
+
{note}
|
|
324
|
+
Note panel
|
|
325
|
+
{note}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Links
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
[Link text|https://example.com]
|
|
332
|
+
[Link to page|PAGE:Page Title]
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Status Macros
|
|
336
|
+
|
|
337
|
+
```
|
|
338
|
+
{status:colour=Green|title=Done}
|
|
339
|
+
{status:colour=Yellow|title=In Progress}
|
|
340
|
+
{status:colour=Red|title=Blocked}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## File Naming Convention
|
|
346
|
+
|
|
347
|
+
```
|
|
348
|
+
docs/confluence/
|
|
349
|
+
├── {doc-name}-{lang}.{format}
|
|
350
|
+
│
|
|
351
|
+
├── prd-uk.confluence # Ukrainian Confluence
|
|
352
|
+
├── prd-uk.md # Ukrainian Markdown
|
|
353
|
+
├── architecture-uk.confluence
|
|
354
|
+
├── epic-01-uk.confluence
|
|
355
|
+
│
|
|
356
|
+
├── html/ # HTML exports
|
|
357
|
+
│ ├── prd-uk.html
|
|
358
|
+
│ └── style.css
|
|
359
|
+
│
|
|
360
|
+
└── README.md # Index of all translations
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
**Language codes:**
|
|
364
|
+
- `uk` - Ukrainian
|
|
365
|
+
- `en` - English
|
|
366
|
+
- `pl` - Polish
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## Confluence Index Template
|
|
371
|
+
|
|
372
|
+
```markdown
|
|
373
|
+
# Документація проекту / Project Documentation
|
|
374
|
+
|
|
375
|
+
**Мова / Language:** Українська
|
|
376
|
+
**Оновлено / Updated:** {{date}}
|
|
377
|
+
**Джерело / Source:** docs/ (English)
|
|
378
|
+
|
|
379
|
+
## Документи / Documents
|
|
380
|
+
|
|
381
|
+
| Документ | Confluence | Markdown | Оригінал |
|
|
382
|
+
|----------|------------|----------|----------|
|
|
383
|
+
| PRD | [prd-uk.confluence](./prd-uk.confluence) | [prd-uk.md](./prd-uk.md) | [docs/prd.md](../docs/prd.md) |
|
|
384
|
+
| Архітектура | [architecture-uk.confluence](./architecture-uk.confluence) | [architecture-uk.md](./architecture-uk.md) | [docs/architecture.md](../docs/architecture.md) |
|
|
385
|
+
|
|
386
|
+
## Примітки / Notes
|
|
387
|
+
|
|
388
|
+
- Технічні терміни залишені англійською (API, endpoint, cache, etc.)
|
|
389
|
+
- Блоки коду не перекладаються
|
|
390
|
+
- Оригінальна документація завжди актуальніша
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## Changelog
|
|
395
|
+
|
|
396
|
+
| Version | Date | Changes |
|
|
397
|
+
|---------|------|---------|
|
|
398
|
+
| 1.0 | {{date}} | Initial translation |
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## Validation
|
|
404
|
+
|
|
405
|
+
- [ ] Source document exists in docs/
|
|
406
|
+
- [ ] Target language supported
|
|
407
|
+
- [ ] Output folder writable
|
|
408
|
+
- [ ] Technical terms preserved
|
|
409
|
+
- [ ] Code blocks unchanged
|
|
410
|
+
- [ ] Links updated for new paths
|
|
411
|
+
- [ ] Index updated
|