oden-forge 2.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/.claude/CLAUDE.md +75 -0
- package/.claude/commands/oden/architect.md +204 -0
- package/.claude/commands/oden/checklist.md +199 -0
- package/.claude/commands/oden/daily.md +223 -0
- package/.claude/commands/oden/debug.md +203 -0
- package/.claude/commands/oden/epic.md +224 -0
- package/.claude/commands/oden/git.md +259 -0
- package/.claude/commands/oden/help.md +304 -0
- package/.claude/commands/oden/init-agents.md +268 -0
- package/.claude/commands/oden/init-mcp.md +460 -0
- package/.claude/commands/oden/init.md +495 -0
- package/.claude/commands/oden/mcp.md +585 -0
- package/.claude/commands/oden/prd.md +134 -0
- package/.claude/commands/oden/research.md +207 -0
- package/.claude/commands/oden/review.md +146 -0
- package/.claude/commands/oden/spec.md +539 -0
- package/.claude/commands/oden/sync.md +286 -0
- package/.claude/commands/oden/tasks.md +156 -0
- package/.claude/commands/oden/test.md +200 -0
- package/.claude/commands/oden/work.md +791 -0
- package/.claude/epics/.gitkeep +0 -0
- package/.claude/hooks/README.md +130 -0
- package/.claude/hooks/bash-worktree-fix.sh +189 -0
- package/.claude/prds/.gitkeep +0 -0
- package/.claude/rules/agent-coordination.md +224 -0
- package/.claude/rules/branch-operations.md +147 -0
- package/.claude/rules/datetime.md +118 -0
- package/.claude/rules/frontmatter-operations.md +58 -0
- package/.claude/rules/github-operations.md +89 -0
- package/.claude/rules/oden-methodology.md +111 -0
- package/.claude/rules/path-standards.md +155 -0
- package/.claude/rules/standard-patterns.md +174 -0
- package/.claude/rules/strip-frontmatter.md +82 -0
- package/.claude/rules/worktree-operations.md +136 -0
- package/.claude/scripts/oden/blocked.sh +72 -0
- package/.claude/scripts/oden/epic-list.sh +101 -0
- package/.claude/scripts/oden/epic-show.sh +91 -0
- package/.claude/scripts/oden/epic-status.sh +90 -0
- package/.claude/scripts/oden/help.sh +71 -0
- package/.claude/scripts/oden/in-progress.sh +74 -0
- package/.claude/scripts/oden/init.sh +192 -0
- package/.claude/scripts/oden/next.sh +65 -0
- package/.claude/scripts/oden/prd-list.sh +89 -0
- package/.claude/scripts/oden/prd-status.sh +63 -0
- package/.claude/scripts/oden/search.sh +71 -0
- package/.claude/scripts/oden/standup.sh +89 -0
- package/.claude/scripts/oden/status.sh +42 -0
- package/.claude/scripts/oden/validate.sh +101 -0
- package/.claude/settings.json +27 -0
- package/MIGRATION.md +217 -0
- package/README.md +368 -0
- package/bin/install.js +155 -0
- package/bin/migrate.js +191 -0
- package/bin/oden-forge.js +114 -0
- package/bin/post-install.js +47 -0
- package/bin/pre-uninstall.js +108 -0
- package/install.sh +231 -0
- package/package.json +76 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
---
|
|
2
|
+
allowed-tools: Bash, Read, Write, LS, Task
|
|
3
|
+
description: Sincronizar epic y tasks con GitHub Issues (nativo, sin CCPM)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Sync - GitHub Issues Synchronization
|
|
7
|
+
|
|
8
|
+
Sincroniza epics y tasks locales con GitHub Issues. Comando nativo sin dependencia de CCPM.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
```
|
|
12
|
+
/oden:sync <feature_name> [subcommand]
|
|
13
|
+
/oden:sync status
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Subcommands
|
|
17
|
+
|
|
18
|
+
- `/oden:sync <name>` - Full sync: push epic + tasks to GitHub, create branch
|
|
19
|
+
- `/oden:sync <name> push` - Same as above (explicit)
|
|
20
|
+
- `/oden:sync <name> update` - Update existing GitHub issues from local changes
|
|
21
|
+
- `/oden:sync status` - Show sync status of all epics
|
|
22
|
+
|
|
23
|
+
## Preflight
|
|
24
|
+
|
|
25
|
+
### Repository Protection
|
|
26
|
+
```bash
|
|
27
|
+
remote_url=$(git remote get-url origin 2>/dev/null || echo "")
|
|
28
|
+
if [[ "$remote_url" == *"automazeio/ccpm"* ]] || [[ "$remote_url" == *"automazeio/ccpm.git"* ]]; then
|
|
29
|
+
echo "Cannot sync to CCPM template repository!"
|
|
30
|
+
echo "Update remote: git remote set-url origin https://github.com/YOUR_USERNAME/YOUR_REPO.git"
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Validation
|
|
36
|
+
1. **Epic exists**: Check `.claude/epics/$ARGUMENTS/epic.md`
|
|
37
|
+
- If not found: "Epic not found. Create it: /oden:prd $ARGUMENTS && /oden:epic $ARGUMENTS && /oden:tasks $ARGUMENTS"
|
|
38
|
+
|
|
39
|
+
2. **Tasks exist**: Check for numbered task files in `.claude/epics/$ARGUMENTS/`
|
|
40
|
+
- If none found: "No tasks found. Create them: /oden:tasks $ARGUMENTS"
|
|
41
|
+
|
|
42
|
+
3. **Git remote**: Verify origin is configured
|
|
43
|
+
- If not: "No remote. Run: git remote add origin <url>"
|
|
44
|
+
|
|
45
|
+
## Instructions
|
|
46
|
+
|
|
47
|
+
### Detect Repository
|
|
48
|
+
```bash
|
|
49
|
+
remote_url=$(git remote get-url origin 2>/dev/null || echo "")
|
|
50
|
+
REPO=$(echo "$remote_url" | sed 's|.*github.com[:/]||' | sed 's|\.git$||')
|
|
51
|
+
[ -z "$REPO" ] && REPO="user/repo"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Setup Labels
|
|
55
|
+
Create labels if they don't exist (silently):
|
|
56
|
+
```bash
|
|
57
|
+
gh label create "epic" --color "0E8A16" --description "Epic issue" 2>/dev/null || true
|
|
58
|
+
gh label create "task" --color "1D76DB" --description "Task issue" 2>/dev/null || true
|
|
59
|
+
gh label create "feature" --color "A2EEEF" --description "New feature" 2>/dev/null || true
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Full Sync Flow (`/oden:sync <name>`)
|
|
65
|
+
|
|
66
|
+
### Step 1: Create Epic Issue
|
|
67
|
+
|
|
68
|
+
Strip frontmatter and prepare body:
|
|
69
|
+
```bash
|
|
70
|
+
# Extract content without frontmatter
|
|
71
|
+
sed '1,/^---$/d; 1,/^---$/d' .claude/epics/$ARGUMENTS/epic.md > /tmp/epic-body-raw.md
|
|
72
|
+
|
|
73
|
+
# Remove "## Tasks Created" section (will be auto-generated from sub-issues)
|
|
74
|
+
awk '
|
|
75
|
+
/^## Tasks Created/ { skip=1; next }
|
|
76
|
+
/^## / && skip { skip=0 }
|
|
77
|
+
!skip { print }
|
|
78
|
+
' /tmp/epic-body-raw.md > /tmp/epic-body.md
|
|
79
|
+
|
|
80
|
+
# Create epic issue
|
|
81
|
+
epic_number=$(gh issue create \
|
|
82
|
+
--repo "$REPO" \
|
|
83
|
+
--title "Epic: $ARGUMENTS" \
|
|
84
|
+
--body-file /tmp/epic-body.md \
|
|
85
|
+
--label "epic,epic:$ARGUMENTS,feature" \
|
|
86
|
+
--json number -q .number)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Step 2: Create Task Sub-Issues
|
|
90
|
+
|
|
91
|
+
Check for gh-sub-issue extension:
|
|
92
|
+
```bash
|
|
93
|
+
if gh extension list | grep -q "yahsan2/gh-sub-issue"; then
|
|
94
|
+
use_subissues=true
|
|
95
|
+
else
|
|
96
|
+
use_subissues=false
|
|
97
|
+
fi
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
For each task file:
|
|
101
|
+
```bash
|
|
102
|
+
for task_file in .claude/epics/$ARGUMENTS/[0-9][0-9][0-9].md; do
|
|
103
|
+
[ -f "$task_file" ] || continue
|
|
104
|
+
|
|
105
|
+
task_name=$(grep '^name:' "$task_file" | sed 's/^name: *//')
|
|
106
|
+
sed '1,/^---$/d; 1,/^---$/d' "$task_file" > /tmp/task-body.md
|
|
107
|
+
|
|
108
|
+
if [ "$use_subissues" = true ]; then
|
|
109
|
+
task_number=$(gh sub-issue create \
|
|
110
|
+
--parent "$epic_number" \
|
|
111
|
+
--title "$task_name" \
|
|
112
|
+
--body-file /tmp/task-body.md \
|
|
113
|
+
--label "task,epic:$ARGUMENTS" \
|
|
114
|
+
--json number -q .number)
|
|
115
|
+
else
|
|
116
|
+
task_number=$(gh issue create \
|
|
117
|
+
--repo "$REPO" \
|
|
118
|
+
--title "$task_name" \
|
|
119
|
+
--body-file /tmp/task-body.md \
|
|
120
|
+
--label "task,epic:$ARGUMENTS" \
|
|
121
|
+
--json number -q .number)
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
echo "$task_file:$task_number" >> /tmp/task-mapping.txt
|
|
125
|
+
done
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**For 5+ tasks**: Use Task tool for parallel creation in batches of 3-4.
|
|
129
|
+
|
|
130
|
+
### Step 3: Rename Files and Update References
|
|
131
|
+
|
|
132
|
+
Build old-to-new mapping:
|
|
133
|
+
```bash
|
|
134
|
+
> /tmp/id-mapping.txt
|
|
135
|
+
while IFS=: read -r task_file task_number; do
|
|
136
|
+
old_num=$(basename "$task_file" .md)
|
|
137
|
+
echo "$old_num:$task_number" >> /tmp/id-mapping.txt
|
|
138
|
+
done < /tmp/task-mapping.txt
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Rename and update references:
|
|
142
|
+
```bash
|
|
143
|
+
repo_name=$(gh repo view --json nameWithOwner -q .nameWithOwner)
|
|
144
|
+
current_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
145
|
+
|
|
146
|
+
while IFS=: read -r task_file task_number; do
|
|
147
|
+
new_name="$(dirname "$task_file")/${task_number}.md"
|
|
148
|
+
content=$(cat "$task_file")
|
|
149
|
+
|
|
150
|
+
# Update depends_on and conflicts_with references
|
|
151
|
+
while IFS=: read -r old_num new_num; do
|
|
152
|
+
content=$(echo "$content" | sed "s/\b$old_num\b/$new_num/g")
|
|
153
|
+
done < /tmp/id-mapping.txt
|
|
154
|
+
|
|
155
|
+
echo "$content" > "$new_name"
|
|
156
|
+
[ "$task_file" != "$new_name" ] && rm "$task_file"
|
|
157
|
+
|
|
158
|
+
# Update frontmatter
|
|
159
|
+
github_url="https://github.com/$repo_name/issues/$task_number"
|
|
160
|
+
sed -i.bak "/^github:/c\github: $github_url" "$new_name"
|
|
161
|
+
sed -i.bak "/^updated:/c\updated: $current_date" "$new_name"
|
|
162
|
+
rm "${new_name}.bak"
|
|
163
|
+
done < /tmp/task-mapping.txt
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Step 4: Update Epic with Task List (fallback without sub-issues)
|
|
167
|
+
|
|
168
|
+
If NOT using gh-sub-issue, add task list to epic issue body:
|
|
169
|
+
```bash
|
|
170
|
+
if [ "$use_subissues" = false ]; then
|
|
171
|
+
gh issue view ${epic_number} --json body -q .body > /tmp/epic-body.md
|
|
172
|
+
# Append task checklist
|
|
173
|
+
echo "" >> /tmp/epic-body.md
|
|
174
|
+
echo "## Tasks" >> /tmp/epic-body.md
|
|
175
|
+
while IFS=: read -r task_file task_number; do
|
|
176
|
+
task_name=$(grep '^name:' "$(dirname "$task_file")/${task_number}.md" | sed 's/^name: *//')
|
|
177
|
+
echo "- [ ] #${task_number} ${task_name}" >> /tmp/epic-body.md
|
|
178
|
+
done < /tmp/task-mapping.txt
|
|
179
|
+
gh issue edit ${epic_number} --body-file /tmp/epic-body.md
|
|
180
|
+
fi
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Step 5: Update Local Epic File
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
epic_url="https://github.com/$repo_name/issues/$epic_number"
|
|
187
|
+
current_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
188
|
+
|
|
189
|
+
# Update frontmatter
|
|
190
|
+
sed -i.bak "/^github:/c\github: $epic_url" .claude/epics/$ARGUMENTS/epic.md
|
|
191
|
+
sed -i.bak "/^updated:/c\updated: $current_date" .claude/epics/$ARGUMENTS/epic.md
|
|
192
|
+
rm .claude/epics/$ARGUMENTS/epic.md.bak
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Update "## Tasks Created" section with real issue numbers.
|
|
196
|
+
|
|
197
|
+
### Step 6: Create Mapping File
|
|
198
|
+
|
|
199
|
+
Create `.claude/epics/$ARGUMENTS/github-mapping.md`:
|
|
200
|
+
```markdown
|
|
201
|
+
# GitHub Issue Mapping
|
|
202
|
+
|
|
203
|
+
Epic: #{epic_number} - https://github.com/{repo}/issues/{epic_number}
|
|
204
|
+
|
|
205
|
+
Tasks:
|
|
206
|
+
- #{task_number}: {task_name} - https://github.com/{repo}/issues/{task_number}
|
|
207
|
+
- ...
|
|
208
|
+
|
|
209
|
+
Synced: {current_datetime}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Step 7: Create Branch
|
|
213
|
+
|
|
214
|
+
Follow `/rules/branch-operations.md`:
|
|
215
|
+
```bash
|
|
216
|
+
git checkout main && git pull origin main
|
|
217
|
+
git checkout -b epic/$ARGUMENTS
|
|
218
|
+
git push -u origin epic/$ARGUMENTS
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Output
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
Synced to GitHub
|
|
225
|
+
Epic: #{epic_number}
|
|
226
|
+
Tasks: {count} issues created
|
|
227
|
+
Labels: epic, task, epic:{name}
|
|
228
|
+
Files renamed: 001.md -> {issue_id}.md
|
|
229
|
+
Branch: epic/$ARGUMENTS
|
|
230
|
+
|
|
231
|
+
Next: /oden:epic-start $ARGUMENTS
|
|
232
|
+
View: https://github.com/{repo}/issues/{epic_number}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Update Flow (`/oden:sync <name> update`)
|
|
238
|
+
|
|
239
|
+
For syncing local changes to existing GitHub issues:
|
|
240
|
+
|
|
241
|
+
1. Read github-mapping.md for issue numbers
|
|
242
|
+
2. For each task with local changes since last sync:
|
|
243
|
+
- Update GitHub issue body if task description changed
|
|
244
|
+
- Add progress comment if updates exist
|
|
245
|
+
3. Update epic progress on GitHub
|
|
246
|
+
4. Update local sync timestamps
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Status Flow (`/oden:sync status`)
|
|
251
|
+
|
|
252
|
+
Scan all epics and show sync state:
|
|
253
|
+
|
|
254
|
+
```
|
|
255
|
+
SYNC STATUS
|
|
256
|
+
|
|
257
|
+
Epics:
|
|
258
|
+
{name} (#{number}) - {closed}/{total} tasks | {progress}%
|
|
259
|
+
{name} (#{number}) - {closed}/{total} tasks | {progress}%
|
|
260
|
+
|
|
261
|
+
Issues in progress:
|
|
262
|
+
#{number}: {title}
|
|
263
|
+
#{number}: {title}
|
|
264
|
+
|
|
265
|
+
Local only (not synced):
|
|
266
|
+
{name} - Run: /oden:sync {name}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Error Handling
|
|
272
|
+
|
|
273
|
+
Follow `/rules/github-operations.md` for GitHub CLI errors.
|
|
274
|
+
|
|
275
|
+
If any issue creation fails:
|
|
276
|
+
- Report what succeeded and what failed
|
|
277
|
+
- Don't attempt rollback (partial sync is fine)
|
|
278
|
+
- Suggest: "Retry failed items with: /oden:sync $ARGUMENTS update"
|
|
279
|
+
|
|
280
|
+
## Important Notes
|
|
281
|
+
|
|
282
|
+
- **No CCPM dependency** - this is fully native
|
|
283
|
+
- Always check remote origin before GitHub writes
|
|
284
|
+
- Get REAL datetime: `date -u +"%Y-%m-%dT%H:%M:%SZ"`
|
|
285
|
+
- Update frontmatter only after successful creation
|
|
286
|
+
- Clean up temp files after operations
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
allowed-tools: Bash, Read, Write, LS, Task
|
|
3
|
+
description: Descomponer Epic en tasks/issues individuales (nativo, sin CCPM)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Tasks - Decompose Epic into Issues
|
|
7
|
+
|
|
8
|
+
Descompone un Epic en tasks individuales, accionables y con dependencias claras.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
```
|
|
12
|
+
/oden:tasks <feature_name>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Preflight
|
|
16
|
+
|
|
17
|
+
Silently validate:
|
|
18
|
+
|
|
19
|
+
1. **Epic exists**: Check `.claude/epics/$ARGUMENTS/epic.md`
|
|
20
|
+
- If not found: "Epic not found. Create it first: /oden:epic $ARGUMENTS"
|
|
21
|
+
|
|
22
|
+
2. **Epic frontmatter**: Verify name, status, created, prd fields
|
|
23
|
+
- If invalid: "Invalid epic. Check: .claude/epics/$ARGUMENTS/epic.md"
|
|
24
|
+
|
|
25
|
+
3. **Existing tasks**: Check for numbered files (001.md, 002.md, etc.) in `.claude/epics/$ARGUMENTS/`
|
|
26
|
+
- If found, list them and ask: "Found {count} existing tasks. Delete and recreate? (yes/no)"
|
|
27
|
+
- Only proceed with confirmation
|
|
28
|
+
|
|
29
|
+
4. **Epic status**: If status is "completed", warn before proceeding
|
|
30
|
+
|
|
31
|
+
## Instructions
|
|
32
|
+
|
|
33
|
+
You are decomposing an epic into actionable tasks for: **$ARGUMENTS**
|
|
34
|
+
|
|
35
|
+
### 1. Read the Epic
|
|
36
|
+
|
|
37
|
+
Load `.claude/epics/$ARGUMENTS/epic.md`:
|
|
38
|
+
- Understand technical approach
|
|
39
|
+
- Review task breakdown preview
|
|
40
|
+
- Note dependencies and constraints
|
|
41
|
+
|
|
42
|
+
### 2. Create Tasks
|
|
43
|
+
|
|
44
|
+
For each task, create a numbered file in `.claude/epics/$ARGUMENTS/`:
|
|
45
|
+
|
|
46
|
+
#### Task File Format: `.claude/epics/$ARGUMENTS/{number}.md`
|
|
47
|
+
|
|
48
|
+
```markdown
|
|
49
|
+
---
|
|
50
|
+
name: [Task Title]
|
|
51
|
+
status: open
|
|
52
|
+
created: [Real datetime]
|
|
53
|
+
updated: [Real datetime]
|
|
54
|
+
github:
|
|
55
|
+
depends_on: []
|
|
56
|
+
parallel: true
|
|
57
|
+
conflicts_with: []
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
# Task: [Task Title]
|
|
61
|
+
|
|
62
|
+
## Description
|
|
63
|
+
[Clear, concise description]
|
|
64
|
+
|
|
65
|
+
## Acceptance Criteria
|
|
66
|
+
- [ ] Criterion 1
|
|
67
|
+
- [ ] Criterion 2
|
|
68
|
+
- [ ] Criterion 3
|
|
69
|
+
|
|
70
|
+
## Technical Details
|
|
71
|
+
[Implementation approach, files affected, key considerations]
|
|
72
|
+
|
|
73
|
+
## Dependencies
|
|
74
|
+
- [ ] Task/external dependencies
|
|
75
|
+
|
|
76
|
+
## Effort Estimate
|
|
77
|
+
- Size: XS/S/M/L/XL
|
|
78
|
+
- Parallel: true/false
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 3. Task Guidelines
|
|
82
|
+
|
|
83
|
+
- **Numbering**: Sequential 001.md, 002.md, etc.
|
|
84
|
+
- **Size**: Each task completable in 1-3 days
|
|
85
|
+
- **Max tasks**: Aim for 10 or fewer
|
|
86
|
+
- **Parallel field**: Set true if no blocking dependencies
|
|
87
|
+
- **depends_on**: Reference task numbers that must complete first (e.g., [001, 002])
|
|
88
|
+
- **conflicts_with**: Tasks that modify same files
|
|
89
|
+
|
|
90
|
+
### 4. Execution Strategy
|
|
91
|
+
|
|
92
|
+
Choose based on task count:
|
|
93
|
+
|
|
94
|
+
**< 5 tasks**: Create sequentially (simpler)
|
|
95
|
+
|
|
96
|
+
**5-10 tasks**: Can batch with Task tool:
|
|
97
|
+
```yaml
|
|
98
|
+
Task:
|
|
99
|
+
description: "Create tasks batch {X} for epic $ARGUMENTS"
|
|
100
|
+
subagent_type: "general-purpose"
|
|
101
|
+
prompt: |
|
|
102
|
+
Create task files for epic: $ARGUMENTS
|
|
103
|
+
Tasks to create: [list]
|
|
104
|
+
Directory: .claude/epics/$ARGUMENTS/
|
|
105
|
+
Use exact frontmatter format.
|
|
106
|
+
Get real datetime: date -u +"%Y-%m-%dT%H:%M:%SZ"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 5. Update Epic
|
|
110
|
+
|
|
111
|
+
After creating all tasks, update `.claude/epics/$ARGUMENTS/epic.md`:
|
|
112
|
+
|
|
113
|
+
Add/replace "## Tasks Created" section:
|
|
114
|
+
```markdown
|
|
115
|
+
## Tasks Created
|
|
116
|
+
- [ ] 001 - {Task Title} (parallel: true/false)
|
|
117
|
+
- [ ] 002 - {Task Title} (parallel: true/false)
|
|
118
|
+
- etc.
|
|
119
|
+
|
|
120
|
+
Total tasks: {count}
|
|
121
|
+
Parallel tasks: {parallel_count}
|
|
122
|
+
Sequential tasks: {sequential_count}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Update frontmatter `updated` field with current datetime.
|
|
126
|
+
|
|
127
|
+
### 6. Validation
|
|
128
|
+
|
|
129
|
+
Before finalizing:
|
|
130
|
+
- All tasks have clear acceptance criteria
|
|
131
|
+
- Task sizes are reasonable (1-3 days)
|
|
132
|
+
- Dependencies are logical (no circular)
|
|
133
|
+
- Parallel tasks don't conflict
|
|
134
|
+
- Combined tasks cover all epic requirements
|
|
135
|
+
|
|
136
|
+
## Output
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
Created {count} tasks for epic: $ARGUMENTS
|
|
140
|
+
|
|
141
|
+
Tasks:
|
|
142
|
+
001 - {title} (S, parallel)
|
|
143
|
+
002 - {title} (M, parallel)
|
|
144
|
+
003 - {title} (M, depends: 001)
|
|
145
|
+
...
|
|
146
|
+
|
|
147
|
+
Parallel: {count} | Sequential: {count}
|
|
148
|
+
|
|
149
|
+
Next: /oden:sync $ARGUMENTS
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Important
|
|
153
|
+
|
|
154
|
+
- Get REAL datetime: `date -u +"%Y-%m-%dT%H:%M:%SZ"`
|
|
155
|
+
- Keep tasks actionable and well-scoped
|
|
156
|
+
- Prefer fewer, well-defined tasks over many granular ones
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
---
|
|
2
|
+
allowed-tools: Bash, Read, Write, Edit, LS, Glob, Grep, Task, TodoWrite
|
|
3
|
+
description: Testing - estrategia, ejecución y análisis
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Oden Forge - Testing
|
|
7
|
+
|
|
8
|
+
Comandos para testing completo del proyecto.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
/oden:test [subcommand]
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Subcomandos
|
|
17
|
+
|
|
18
|
+
### `/oden:test strategy`
|
|
19
|
+
|
|
20
|
+
Crea estrategia de testing para el proyecto.
|
|
21
|
+
|
|
22
|
+
**Usa:** `test-engineer` agent
|
|
23
|
+
|
|
24
|
+
**Genera:**
|
|
25
|
+
- `docs/reference/testing-strategy.md`
|
|
26
|
+
- Estructura de tests recomendada
|
|
27
|
+
- Cobertura mínima por módulo
|
|
28
|
+
- Tipos de tests por feature
|
|
29
|
+
|
|
30
|
+
### `/oden:test run [scope]`
|
|
31
|
+
|
|
32
|
+
Ejecuta tests y analiza resultados.
|
|
33
|
+
|
|
34
|
+
**Usa:** `test-runner` agent
|
|
35
|
+
|
|
36
|
+
**Scope:**
|
|
37
|
+
- (vacío) - Todos los tests
|
|
38
|
+
- `unit` - Solo unit tests
|
|
39
|
+
- `integration` - Solo integration
|
|
40
|
+
- `e2e` - Solo end-to-end
|
|
41
|
+
- `module {name}` - Tests de un módulo
|
|
42
|
+
|
|
43
|
+
**Output:**
|
|
44
|
+
```
|
|
45
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
46
|
+
║ TEST RESULTS ║
|
|
47
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
48
|
+
║ ║
|
|
49
|
+
║ ✅ Passed: 45 ║
|
|
50
|
+
║ ❌ Failed: 3 ║
|
|
51
|
+
║ ⏭️ Skipped: 2 ║
|
|
52
|
+
║ ║
|
|
53
|
+
║ Coverage: 78% ║
|
|
54
|
+
║ ║
|
|
55
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
56
|
+
║ ║
|
|
57
|
+
║ FAILURES: ║
|
|
58
|
+
║ ║
|
|
59
|
+
║ 1. auth.test.ts:45 ║
|
|
60
|
+
║ Expected: 200 ║
|
|
61
|
+
║ Received: 401 ║
|
|
62
|
+
║ → Posible causa: Token expirado ║
|
|
63
|
+
║ ║
|
|
64
|
+
║ 2. orders.test.ts:123 ║
|
|
65
|
+
║ Expected: "completed" ║
|
|
66
|
+
║ Received: "pending" ║
|
|
67
|
+
║ → Posible causa: Estado no actualizado ║
|
|
68
|
+
║ ║
|
|
69
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### `/oden:test fix`
|
|
73
|
+
|
|
74
|
+
Analiza tests fallidos y sugiere fixes.
|
|
75
|
+
|
|
76
|
+
**Usa:** `debugger` + `code-analyzer` agents
|
|
77
|
+
|
|
78
|
+
**Proceso:**
|
|
79
|
+
1. Lee output de último test run
|
|
80
|
+
2. Analiza cada fallo
|
|
81
|
+
3. Identifica causa raíz
|
|
82
|
+
4. Sugiere fix específico
|
|
83
|
+
|
|
84
|
+
### `/oden:test coverage`
|
|
85
|
+
|
|
86
|
+
Analiza cobertura y sugiere tests faltantes.
|
|
87
|
+
|
|
88
|
+
**Usa:** `test-engineer` agent
|
|
89
|
+
|
|
90
|
+
**Output:**
|
|
91
|
+
```
|
|
92
|
+
╔══════════════════════════════════════════════════════════════╗
|
|
93
|
+
║ COVERAGE ANALYSIS ║
|
|
94
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
95
|
+
║ ║
|
|
96
|
+
║ MODULE COVERAGE TARGET STATUS ║
|
|
97
|
+
║ ─────────────────────────────────────────────────────────── ║
|
|
98
|
+
║ auth 92% 80% ✅ ║
|
|
99
|
+
║ orders 67% 80% ❌ (-13%) ║
|
|
100
|
+
║ payments 85% 80% ✅ ║
|
|
101
|
+
║ users 45% 80% ❌ (-35%) ║
|
|
102
|
+
║ ║
|
|
103
|
+
╠══════════════════════════════════════════════════════════════╣
|
|
104
|
+
║ ║
|
|
105
|
+
║ TESTS SUGERIDOS: ║
|
|
106
|
+
║ ║
|
|
107
|
+
║ orders: ║
|
|
108
|
+
║ - [ ] Test: cancelOrder con items parciales ║
|
|
109
|
+
║ - [ ] Test: refund cuando ya hay refund parcial ║
|
|
110
|
+
║ - [ ] Test: transición ACTIVE → COMPLETED ║
|
|
111
|
+
║ ║
|
|
112
|
+
║ users: ║
|
|
113
|
+
║ - [ ] Test: updateProfile con campos inválidos ║
|
|
114
|
+
║ - [ ] Test: deleteUser con órdenes activas ║
|
|
115
|
+
║ - [ ] Test: cambio de rol ║
|
|
116
|
+
║ ║
|
|
117
|
+
╚══════════════════════════════════════════════════════════════╝
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### `/oden:test generate [module]`
|
|
121
|
+
|
|
122
|
+
Genera tests basados en specs.
|
|
123
|
+
|
|
124
|
+
**Usa:** `test-engineer` agent
|
|
125
|
+
|
|
126
|
+
**Lee:**
|
|
127
|
+
- `docs/reference/modules/{module}-spec.md`
|
|
128
|
+
- Especialmente secciones de:
|
|
129
|
+
- Validaciones
|
|
130
|
+
- Estados y transiciones
|
|
131
|
+
- Edge cases
|
|
132
|
+
- Testing checklist
|
|
133
|
+
|
|
134
|
+
**Genera:**
|
|
135
|
+
- Unit tests para validaciones
|
|
136
|
+
- Integration tests para flujos
|
|
137
|
+
- Tests de transiciones de estado
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Integración con Specs
|
|
142
|
+
|
|
143
|
+
Los tests se generan basándose en las especificaciones:
|
|
144
|
+
|
|
145
|
+
### De la Spec → A Tests
|
|
146
|
+
|
|
147
|
+
| Sección Spec | Tipo de Test |
|
|
148
|
+
|--------------|--------------|
|
|
149
|
+
| Validaciones de campo | Unit tests |
|
|
150
|
+
| Transiciones de estado | State machine tests |
|
|
151
|
+
| API endpoints | Integration tests |
|
|
152
|
+
| Flujos de usuario | E2E tests |
|
|
153
|
+
| Edge cases | Específicos por caso |
|
|
154
|
+
|
|
155
|
+
### Ejemplo
|
|
156
|
+
|
|
157
|
+
Si la spec dice:
|
|
158
|
+
```markdown
|
|
159
|
+
### 5.1 Validaciones de Campo
|
|
160
|
+
| Campo | Regla | Mensaje |
|
|
161
|
+
| name | No vacío | "El nombre es requerido" |
|
|
162
|
+
| name | Max 100 chars | "El nombre no puede exceder 100 caracteres" |
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Genera:
|
|
166
|
+
```typescript
|
|
167
|
+
describe('Order validations', () => {
|
|
168
|
+
it('should require name', () => {
|
|
169
|
+
expect(() => createOrder({ name: '' }))
|
|
170
|
+
.toThrow('El nombre es requerido');
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('should reject name > 100 chars', () => {
|
|
174
|
+
expect(() => createOrder({ name: 'a'.repeat(101) }))
|
|
175
|
+
.toThrow('El nombre no puede exceder 100 caracteres');
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Flujo Recomendado
|
|
183
|
+
|
|
184
|
+
1. **Al crear spec:** `/oden:spec orders`
|
|
185
|
+
2. **Generar tests:** `/oden:test generate orders`
|
|
186
|
+
3. **Implementar código:** (desarrollo)
|
|
187
|
+
4. **Ejecutar tests:** `/oden:test run`
|
|
188
|
+
5. **Si fallan:** `/oden:test fix`
|
|
189
|
+
6. **Verificar coverage:** `/oden:test coverage`
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Guardar Resultados
|
|
194
|
+
|
|
195
|
+
Los resultados de tests se guardan en:
|
|
196
|
+
```
|
|
197
|
+
docs/development/current/{feature}/TEST_RESULTS_{fecha}.md
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Para referencia en daily logs.
|