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,82 @@
|
|
|
1
|
+
# Strip Frontmatter
|
|
2
|
+
|
|
3
|
+
Standard approach for removing YAML frontmatter before sending content to GitHub.
|
|
4
|
+
|
|
5
|
+
## The Problem
|
|
6
|
+
|
|
7
|
+
YAML frontmatter contains internal metadata that should not appear in GitHub issues:
|
|
8
|
+
- status, created, updated fields
|
|
9
|
+
- Internal references and IDs
|
|
10
|
+
- Local file paths
|
|
11
|
+
|
|
12
|
+
## The Solution
|
|
13
|
+
|
|
14
|
+
Use sed to strip frontmatter from any markdown file:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Strip frontmatter (everything between first two --- lines)
|
|
18
|
+
sed '1,/^---$/d; 1,/^---$/d' input.md > output.md
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This removes:
|
|
22
|
+
1. The opening `---` line
|
|
23
|
+
2. All YAML content
|
|
24
|
+
3. The closing `---` line
|
|
25
|
+
|
|
26
|
+
## When to Strip Frontmatter
|
|
27
|
+
|
|
28
|
+
Always strip frontmatter when:
|
|
29
|
+
- Creating GitHub issues from markdown files
|
|
30
|
+
- Posting file content as comments
|
|
31
|
+
- Displaying content to external users
|
|
32
|
+
- Syncing to any external system
|
|
33
|
+
|
|
34
|
+
## Examples
|
|
35
|
+
|
|
36
|
+
### Creating an issue from a file
|
|
37
|
+
```bash
|
|
38
|
+
# Bad - includes frontmatter
|
|
39
|
+
gh issue create --body-file task.md
|
|
40
|
+
|
|
41
|
+
# Good - strips frontmatter and specifies repo
|
|
42
|
+
remote_url=$(git remote get-url origin 2>/dev/null || echo "")
|
|
43
|
+
REPO=$(echo "$remote_url" | sed 's|.*github.com[:/]||' | sed 's|\.git$||')
|
|
44
|
+
[ -z "$REPO" ] && REPO="user/repo"
|
|
45
|
+
sed '1,/^---$/d; 1,/^---$/d' task.md > /tmp/clean.md
|
|
46
|
+
gh issue create --repo "$REPO" --body-file /tmp/clean.md
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Posting a comment
|
|
50
|
+
```bash
|
|
51
|
+
# Strip frontmatter before posting
|
|
52
|
+
sed '1,/^---$/d; 1,/^---$/d' progress.md > /tmp/comment.md
|
|
53
|
+
gh issue comment 123 --body-file /tmp/comment.md
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### In a loop
|
|
57
|
+
```bash
|
|
58
|
+
for file in *.md; do
|
|
59
|
+
# Strip frontmatter from each file
|
|
60
|
+
sed '1,/^---$/d; 1,/^---$/d' "$file" > "/tmp/$(basename $file)"
|
|
61
|
+
# Use the clean version
|
|
62
|
+
done
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Alternative Approaches
|
|
66
|
+
|
|
67
|
+
If sed is not available or you need more control:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Using awk
|
|
71
|
+
awk 'BEGIN{fm=0} /^---$/{fm++; next} fm==2{print}' input.md > output.md
|
|
72
|
+
|
|
73
|
+
# Using grep with line numbers
|
|
74
|
+
grep -n "^---$" input.md | head -2 | tail -1 | cut -d: -f1 | xargs -I {} tail -n +$(({}+1)) input.md
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Important Notes
|
|
78
|
+
|
|
79
|
+
- Always test with a sample file first
|
|
80
|
+
- Keep original files intact
|
|
81
|
+
- Use temporary files for cleaned content
|
|
82
|
+
- Some files may not have frontmatter - the command handles this gracefully
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Worktree Operations
|
|
2
|
+
|
|
3
|
+
Git worktrees enable parallel development by allowing multiple working directories for the same repository.
|
|
4
|
+
|
|
5
|
+
## Creating Worktrees
|
|
6
|
+
|
|
7
|
+
Always create worktrees from a clean main branch:
|
|
8
|
+
```bash
|
|
9
|
+
# Ensure main is up to date
|
|
10
|
+
git checkout main
|
|
11
|
+
git pull origin main
|
|
12
|
+
|
|
13
|
+
# Create worktree for epic
|
|
14
|
+
git worktree add ../epic-{name} -b epic/{name}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The worktree will be created as a sibling directory to maintain clean separation.
|
|
18
|
+
|
|
19
|
+
## Working in Worktrees
|
|
20
|
+
|
|
21
|
+
### Agent Commits
|
|
22
|
+
- Agents commit directly to the worktree
|
|
23
|
+
- Use small, focused commits
|
|
24
|
+
- Commit message format: `Issue #{number}: {description}`
|
|
25
|
+
- Example: `Issue #1234: Add user authentication schema`
|
|
26
|
+
|
|
27
|
+
### File Operations
|
|
28
|
+
```bash
|
|
29
|
+
# Working directory is the worktree
|
|
30
|
+
cd ../epic-{name}
|
|
31
|
+
|
|
32
|
+
# Normal git operations work
|
|
33
|
+
git add {files}
|
|
34
|
+
git commit -m "Issue #{number}: {change}"
|
|
35
|
+
|
|
36
|
+
# View worktree status
|
|
37
|
+
git status
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Parallel Work in Same Worktree
|
|
41
|
+
|
|
42
|
+
Multiple agents can work in the same worktree if they touch different files:
|
|
43
|
+
```bash
|
|
44
|
+
# Agent A works on API
|
|
45
|
+
git add src/api/*
|
|
46
|
+
git commit -m "Issue #1234: Add user endpoints"
|
|
47
|
+
|
|
48
|
+
# Agent B works on UI (no conflict!)
|
|
49
|
+
git add src/ui/*
|
|
50
|
+
git commit -m "Issue #1235: Add dashboard component"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Merging Worktrees
|
|
54
|
+
|
|
55
|
+
When epic is complete, merge back to main:
|
|
56
|
+
```bash
|
|
57
|
+
# From main repository (not worktree)
|
|
58
|
+
cd {main-repo}
|
|
59
|
+
git checkout main
|
|
60
|
+
git pull origin main
|
|
61
|
+
|
|
62
|
+
# Merge epic branch
|
|
63
|
+
git merge epic/{name}
|
|
64
|
+
|
|
65
|
+
# If successful, clean up
|
|
66
|
+
git worktree remove ../epic-{name}
|
|
67
|
+
git branch -d epic/{name}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Handling Conflicts
|
|
71
|
+
|
|
72
|
+
If merge conflicts occur:
|
|
73
|
+
```bash
|
|
74
|
+
# Conflicts will be shown
|
|
75
|
+
git status
|
|
76
|
+
|
|
77
|
+
# Human resolves conflicts
|
|
78
|
+
# Then continue merge
|
|
79
|
+
git add {resolved-files}
|
|
80
|
+
git commit
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Worktree Management
|
|
84
|
+
|
|
85
|
+
### List Active Worktrees
|
|
86
|
+
```bash
|
|
87
|
+
git worktree list
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Remove Stale Worktree
|
|
91
|
+
```bash
|
|
92
|
+
# If worktree directory was deleted
|
|
93
|
+
git worktree prune
|
|
94
|
+
|
|
95
|
+
# Force remove worktree
|
|
96
|
+
git worktree remove --force ../epic-{name}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Check Worktree Status
|
|
100
|
+
```bash
|
|
101
|
+
# From main repo
|
|
102
|
+
cd ../epic-{name} && git status && cd -
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Best Practices
|
|
106
|
+
|
|
107
|
+
1. **One worktree per epic** - Not per issue
|
|
108
|
+
2. **Clean before create** - Always start from updated main
|
|
109
|
+
3. **Commit frequently** - Small commits are easier to merge
|
|
110
|
+
4. **Delete after merge** - Don't leave stale worktrees
|
|
111
|
+
5. **Use descriptive branches** - `epic/feature-name` not `feature`
|
|
112
|
+
|
|
113
|
+
## Common Issues
|
|
114
|
+
|
|
115
|
+
### Worktree Already Exists
|
|
116
|
+
```bash
|
|
117
|
+
# Remove old worktree first
|
|
118
|
+
git worktree remove ../epic-{name}
|
|
119
|
+
# Then create new one
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Branch Already Exists
|
|
123
|
+
```bash
|
|
124
|
+
# Delete old branch
|
|
125
|
+
git branch -D epic/{name}
|
|
126
|
+
# Or use existing branch
|
|
127
|
+
git worktree add ../epic-{name} epic/{name}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Cannot Remove Worktree
|
|
131
|
+
```bash
|
|
132
|
+
# Force removal
|
|
133
|
+
git worktree remove --force ../epic-{name}
|
|
134
|
+
# Clean up references
|
|
135
|
+
git worktree prune
|
|
136
|
+
```
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
echo "Getting tasks..."
|
|
3
|
+
echo ""
|
|
4
|
+
echo ""
|
|
5
|
+
|
|
6
|
+
echo "π« Blocked Tasks"
|
|
7
|
+
echo "================"
|
|
8
|
+
echo ""
|
|
9
|
+
|
|
10
|
+
found=0
|
|
11
|
+
|
|
12
|
+
for epic_dir in .claude/epics/*/; do
|
|
13
|
+
[ -d "$epic_dir" ] || continue
|
|
14
|
+
epic_name=$(basename "$epic_dir")
|
|
15
|
+
|
|
16
|
+
for task_file in "$epic_dir"/[0-9]*.md; do
|
|
17
|
+
[ -f "$task_file" ] || continue
|
|
18
|
+
|
|
19
|
+
# Check if task is open
|
|
20
|
+
status=$(grep "^status:" "$task_file" | head -1 | sed 's/^status: *//')
|
|
21
|
+
if [ "$status" != "open" ] && [ -n "$status" ]; then
|
|
22
|
+
continue
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# Check for dependencies
|
|
26
|
+
# Extract dependencies from task file
|
|
27
|
+
deps_line=$(grep "^depends_on:" "$task_file" | head -1)
|
|
28
|
+
if [ -n "$deps_line" ]; then
|
|
29
|
+
deps=$(echo "$deps_line" | sed 's/^depends_on: *//')
|
|
30
|
+
deps=$(echo "$deps" | sed 's/^\[//' | sed 's/\]$//')
|
|
31
|
+
deps=$(echo "$deps" | sed 's/,/ /g')
|
|
32
|
+
# Trim whitespace and handle empty cases
|
|
33
|
+
deps=$(echo "$deps" | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//')
|
|
34
|
+
[ -z "$deps" ] && deps=""
|
|
35
|
+
else
|
|
36
|
+
deps=""
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
if [ -n "$deps" ] && [ "$deps" != "depends_on:" ]; then
|
|
40
|
+
task_name=$(grep "^name:" "$task_file" | head -1 | sed 's/^name: *//')
|
|
41
|
+
task_num=$(basename "$task_file" .md)
|
|
42
|
+
|
|
43
|
+
echo "βΈοΈ Task #$task_num - $task_name"
|
|
44
|
+
echo " Epic: $epic_name"
|
|
45
|
+
echo " Blocked by: [$deps]"
|
|
46
|
+
|
|
47
|
+
# Check status of dependencies
|
|
48
|
+
open_deps=""
|
|
49
|
+
for dep in $deps; do
|
|
50
|
+
dep_file="$epic_dir$dep.md"
|
|
51
|
+
if [ -f "$dep_file" ]; then
|
|
52
|
+
dep_status=$(grep "^status:" "$dep_file" | head -1 | sed 's/^status: *//')
|
|
53
|
+
[ "$dep_status" = "open" ] && open_deps="$open_deps #$dep"
|
|
54
|
+
fi
|
|
55
|
+
done
|
|
56
|
+
|
|
57
|
+
[ -n "$open_deps" ] && echo " Waiting for:$open_deps"
|
|
58
|
+
echo ""
|
|
59
|
+
((found++))
|
|
60
|
+
fi
|
|
61
|
+
done
|
|
62
|
+
done
|
|
63
|
+
|
|
64
|
+
if [ $found -eq 0 ]; then
|
|
65
|
+
echo "No blocked tasks found!"
|
|
66
|
+
echo ""
|
|
67
|
+
echo "π‘ All tasks with dependencies are either completed or in progress."
|
|
68
|
+
else
|
|
69
|
+
echo "π Total blocked: $found tasks"
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
exit 0
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
echo "Getting epics..."
|
|
3
|
+
echo ""
|
|
4
|
+
echo ""
|
|
5
|
+
|
|
6
|
+
if [ ! -d ".claude/epics" ]; then
|
|
7
|
+
echo "π No epics directory found. Create your first epic with: /pm:prd-parse <feature-name>"
|
|
8
|
+
exit 0
|
|
9
|
+
fi
|
|
10
|
+
epic_dirs=$(ls -d .claude/epics/*/ 2>/dev/null || true)
|
|
11
|
+
if [ -z "$epic_dirs" ]; then
|
|
12
|
+
echo "π No epics found. Create your first epic with: /pm:prd-parse <feature-name>"
|
|
13
|
+
exit 0
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
echo "π Project Epics"
|
|
17
|
+
echo "================"
|
|
18
|
+
echo ""
|
|
19
|
+
|
|
20
|
+
# Initialize arrays to store epics by status
|
|
21
|
+
planning_epics=""
|
|
22
|
+
in_progress_epics=""
|
|
23
|
+
completed_epics=""
|
|
24
|
+
|
|
25
|
+
# Process all epics
|
|
26
|
+
for dir in .claude/epics/*/; do
|
|
27
|
+
[ -d "$dir" ] || continue
|
|
28
|
+
[ -f "$dir/epic.md" ] || continue
|
|
29
|
+
|
|
30
|
+
# Extract metadata
|
|
31
|
+
n=$(grep "^name:" "$dir/epic.md" | head -1 | sed 's/^name: *//')
|
|
32
|
+
s=$(grep "^status:" "$dir/epic.md" | head -1 | sed 's/^status: *//' | tr '[:upper:]' '[:lower:]')
|
|
33
|
+
p=$(grep "^progress:" "$dir/epic.md" | head -1 | sed 's/^progress: *//')
|
|
34
|
+
g=$(grep "^github:" "$dir/epic.md" | head -1 | sed 's/^github: *//')
|
|
35
|
+
|
|
36
|
+
# Defaults
|
|
37
|
+
[ -z "$n" ] && n=$(basename "$dir")
|
|
38
|
+
[ -z "$p" ] && p="0%"
|
|
39
|
+
|
|
40
|
+
# Count tasks
|
|
41
|
+
t=$(ls "$dir"/[0-9]*.md 2>/dev/null | wc -l)
|
|
42
|
+
|
|
43
|
+
# Format output with GitHub issue number if available
|
|
44
|
+
if [ -n "$g" ]; then
|
|
45
|
+
i=$(echo "$g" | grep -o '/[0-9]*$' | tr -d '/')
|
|
46
|
+
entry=" π ${dir}epic.md (#$i) - $p complete ($t tasks)"
|
|
47
|
+
else
|
|
48
|
+
entry=" π ${dir}epic.md - $p complete ($t tasks)"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# Categorize by status (handle various status values)
|
|
52
|
+
case "$s" in
|
|
53
|
+
planning|draft|"")
|
|
54
|
+
planning_epics="${planning_epics}${entry}\n"
|
|
55
|
+
;;
|
|
56
|
+
in-progress|in_progress|active|started)
|
|
57
|
+
in_progress_epics="${in_progress_epics}${entry}\n"
|
|
58
|
+
;;
|
|
59
|
+
completed|complete|done|closed|finished)
|
|
60
|
+
completed_epics="${completed_epics}${entry}\n"
|
|
61
|
+
;;
|
|
62
|
+
*)
|
|
63
|
+
# Default to planning for unknown statuses
|
|
64
|
+
planning_epics="${planning_epics}${entry}\n"
|
|
65
|
+
;;
|
|
66
|
+
esac
|
|
67
|
+
done
|
|
68
|
+
|
|
69
|
+
# Display categorized epics
|
|
70
|
+
echo "π Planning:"
|
|
71
|
+
if [ -n "$planning_epics" ]; then
|
|
72
|
+
echo -e "$planning_epics" | sed '/^$/d'
|
|
73
|
+
else
|
|
74
|
+
echo " (none)"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
echo ""
|
|
78
|
+
echo "π In Progress:"
|
|
79
|
+
if [ -n "$in_progress_epics" ]; then
|
|
80
|
+
echo -e "$in_progress_epics" | sed '/^$/d'
|
|
81
|
+
else
|
|
82
|
+
echo " (none)"
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
echo ""
|
|
86
|
+
echo "β
Completed:"
|
|
87
|
+
if [ -n "$completed_epics" ]; then
|
|
88
|
+
echo -e "$completed_epics" | sed '/^$/d'
|
|
89
|
+
else
|
|
90
|
+
echo " (none)"
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Summary
|
|
94
|
+
echo ""
|
|
95
|
+
echo "π Summary"
|
|
96
|
+
total=$(ls -d .claude/epics/*/ 2>/dev/null | wc -l)
|
|
97
|
+
tasks=$(find .claude/epics -name "[0-9]*.md" 2>/dev/null | wc -l)
|
|
98
|
+
echo " Total epics: $total"
|
|
99
|
+
echo " Total tasks: $tasks"
|
|
100
|
+
|
|
101
|
+
exit 0
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
epic_name="$1"
|
|
4
|
+
|
|
5
|
+
if [ -z "$epic_name" ]; then
|
|
6
|
+
echo "β Please provide an epic name"
|
|
7
|
+
echo "Usage: /pm:epic-show <epic-name>"
|
|
8
|
+
exit 1
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
echo "Getting epic..."
|
|
12
|
+
echo ""
|
|
13
|
+
echo ""
|
|
14
|
+
|
|
15
|
+
epic_dir=".claude/epics/$epic_name"
|
|
16
|
+
epic_file="$epic_dir/epic.md"
|
|
17
|
+
|
|
18
|
+
if [ ! -f "$epic_file" ]; then
|
|
19
|
+
echo "β Epic not found: $epic_name"
|
|
20
|
+
echo ""
|
|
21
|
+
echo "Available epics:"
|
|
22
|
+
for dir in .claude/epics/*/; do
|
|
23
|
+
[ -d "$dir" ] && echo " β’ $(basename "$dir")"
|
|
24
|
+
done
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
# Display epic details
|
|
29
|
+
echo "π Epic: $epic_name"
|
|
30
|
+
echo "================================"
|
|
31
|
+
echo ""
|
|
32
|
+
|
|
33
|
+
# Extract metadata
|
|
34
|
+
status=$(grep "^status:" "$epic_file" | head -1 | sed 's/^status: *//')
|
|
35
|
+
progress=$(grep "^progress:" "$epic_file" | head -1 | sed 's/^progress: *//')
|
|
36
|
+
github=$(grep "^github:" "$epic_file" | head -1 | sed 's/^github: *//')
|
|
37
|
+
created=$(grep "^created:" "$epic_file" | head -1 | sed 's/^created: *//')
|
|
38
|
+
|
|
39
|
+
echo "π Metadata:"
|
|
40
|
+
echo " Status: ${status:-planning}"
|
|
41
|
+
echo " Progress: ${progress:-0%}"
|
|
42
|
+
[ -n "$github" ] && echo " GitHub: $github"
|
|
43
|
+
echo " Created: ${created:-unknown}"
|
|
44
|
+
echo ""
|
|
45
|
+
|
|
46
|
+
# Show tasks
|
|
47
|
+
echo "π Tasks:"
|
|
48
|
+
task_count=0
|
|
49
|
+
open_count=0
|
|
50
|
+
closed_count=0
|
|
51
|
+
|
|
52
|
+
for task_file in "$epic_dir"/[0-9]*.md; do
|
|
53
|
+
[ -f "$task_file" ] || continue
|
|
54
|
+
|
|
55
|
+
task_num=$(basename "$task_file" .md)
|
|
56
|
+
task_name=$(grep "^name:" "$task_file" | head -1 | sed 's/^name: *//')
|
|
57
|
+
task_status=$(grep "^status:" "$task_file" | head -1 | sed 's/^status: *//')
|
|
58
|
+
parallel=$(grep "^parallel:" "$task_file" | head -1 | sed 's/^parallel: *//')
|
|
59
|
+
|
|
60
|
+
if [ "$task_status" = "closed" ] || [ "$task_status" = "completed" ]; then
|
|
61
|
+
echo " β
#$task_num - $task_name"
|
|
62
|
+
((closed_count++))
|
|
63
|
+
else
|
|
64
|
+
echo " β¬ #$task_num - $task_name"
|
|
65
|
+
[ "$parallel" = "true" ] && echo -n " (parallel)"
|
|
66
|
+
((open_count++))
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
((task_count++))
|
|
70
|
+
done
|
|
71
|
+
|
|
72
|
+
if [ $task_count -eq 0 ]; then
|
|
73
|
+
echo " No tasks created yet"
|
|
74
|
+
echo " Run: /pm:epic-decompose $epic_name"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
echo ""
|
|
78
|
+
echo "π Statistics:"
|
|
79
|
+
echo " Total tasks: $task_count"
|
|
80
|
+
echo " Open: $open_count"
|
|
81
|
+
echo " Closed: $closed_count"
|
|
82
|
+
[ $task_count -gt 0 ] && echo " Completion: $((closed_count * 100 / task_count))%"
|
|
83
|
+
|
|
84
|
+
# Next actions
|
|
85
|
+
echo ""
|
|
86
|
+
echo "π‘ Actions:"
|
|
87
|
+
[ $task_count -eq 0 ] && echo " β’ Decompose into tasks: /pm:epic-decompose $epic_name"
|
|
88
|
+
[ -z "$github" ] && [ $task_count -gt 0 ] && echo " β’ Sync to GitHub: /pm:epic-sync $epic_name"
|
|
89
|
+
[ -n "$github" ] && [ "$status" != "completed" ] && echo " β’ Start work: /pm:epic-start $epic_name"
|
|
90
|
+
|
|
91
|
+
exit 0
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
echo "Getting status..."
|
|
4
|
+
echo ""
|
|
5
|
+
echo ""
|
|
6
|
+
|
|
7
|
+
epic_name="$1"
|
|
8
|
+
|
|
9
|
+
if [ -z "$epic_name" ]; then
|
|
10
|
+
echo "β Please specify an epic name"
|
|
11
|
+
echo "Usage: /pm:epic-status <epic-name>"
|
|
12
|
+
echo ""
|
|
13
|
+
echo "Available epics:"
|
|
14
|
+
for dir in .claude/epics/*/; do
|
|
15
|
+
[ -d "$dir" ] && echo " β’ $(basename "$dir")"
|
|
16
|
+
done
|
|
17
|
+
exit 1
|
|
18
|
+
else
|
|
19
|
+
# Show status for specific epic
|
|
20
|
+
epic_dir=".claude/epics/$epic_name"
|
|
21
|
+
epic_file="$epic_dir/epic.md"
|
|
22
|
+
|
|
23
|
+
if [ ! -f "$epic_file" ]; then
|
|
24
|
+
echo "β Epic not found: $epic_name"
|
|
25
|
+
echo ""
|
|
26
|
+
echo "Available epics:"
|
|
27
|
+
for dir in .claude/epics/*/; do
|
|
28
|
+
[ -d "$dir" ] && echo " β’ $(basename "$dir")"
|
|
29
|
+
done
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
echo "π Epic Status: $epic_name"
|
|
34
|
+
echo "================================"
|
|
35
|
+
echo ""
|
|
36
|
+
|
|
37
|
+
# Extract metadata
|
|
38
|
+
status=$(grep "^status:" "$epic_file" | head -1 | sed 's/^status: *//')
|
|
39
|
+
progress=$(grep "^progress:" "$epic_file" | head -1 | sed 's/^progress: *//')
|
|
40
|
+
github=$(grep "^github:" "$epic_file" | head -1 | sed 's/^github: *//')
|
|
41
|
+
|
|
42
|
+
# Count tasks
|
|
43
|
+
total=0
|
|
44
|
+
open=0
|
|
45
|
+
closed=0
|
|
46
|
+
blocked=0
|
|
47
|
+
|
|
48
|
+
# Use find to safely iterate over task files
|
|
49
|
+
for task_file in "$epic_dir"/[0-9]*.md; do
|
|
50
|
+
[ -f "$task_file" ] || continue
|
|
51
|
+
((total++))
|
|
52
|
+
|
|
53
|
+
task_status=$(grep "^status:" "$task_file" | head -1 | sed 's/^status: *//')
|
|
54
|
+
deps=$(grep "^depends_on:" "$task_file" | head -1 | sed 's/^depends_on: *\[//' | sed 's/\]//')
|
|
55
|
+
|
|
56
|
+
if [ "$task_status" = "closed" ] || [ "$task_status" = "completed" ]; then
|
|
57
|
+
((closed++))
|
|
58
|
+
elif [ -n "$deps" ] && [ "$deps" != "depends_on:" ]; then
|
|
59
|
+
((blocked++))
|
|
60
|
+
else
|
|
61
|
+
((open++))
|
|
62
|
+
fi
|
|
63
|
+
done
|
|
64
|
+
|
|
65
|
+
# Display progress bar
|
|
66
|
+
if [ $total -gt 0 ]; then
|
|
67
|
+
percent=$((closed * 100 / total))
|
|
68
|
+
filled=$((percent * 20 / 100))
|
|
69
|
+
empty=$((20 - filled))
|
|
70
|
+
|
|
71
|
+
echo -n "Progress: ["
|
|
72
|
+
[ $filled -gt 0 ] && printf '%0.sβ' $(seq 1 $filled)
|
|
73
|
+
[ $empty -gt 0 ] && printf '%0.sβ' $(seq 1 $empty)
|
|
74
|
+
echo "] $percent%"
|
|
75
|
+
else
|
|
76
|
+
echo "Progress: No tasks created"
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
echo ""
|
|
80
|
+
echo "π Breakdown:"
|
|
81
|
+
echo " Total tasks: $total"
|
|
82
|
+
echo " β
Completed: $closed"
|
|
83
|
+
echo " π Available: $open"
|
|
84
|
+
echo " βΈοΈ Blocked: $blocked"
|
|
85
|
+
|
|
86
|
+
[ -n "$github" ] && echo ""
|
|
87
|
+
[ -n "$github" ] && echo "π GitHub: $github"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
exit 0
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
echo "Helping..."
|
|
3
|
+
echo ""
|
|
4
|
+
echo ""
|
|
5
|
+
|
|
6
|
+
echo "π Claude Code PM - Project Management System"
|
|
7
|
+
echo "============================================="
|
|
8
|
+
echo ""
|
|
9
|
+
echo "π― Quick Start Workflow"
|
|
10
|
+
echo " 1. /pm:prd-new <name> - Create a new PRD"
|
|
11
|
+
echo " 2. /pm:prd-parse <name> - Convert PRD to epic"
|
|
12
|
+
echo " 3. /pm:epic-decompose <name> - Break into tasks"
|
|
13
|
+
echo " 4. /pm:epic-sync <name> - Push to GitHub"
|
|
14
|
+
echo " 5. /pm:epic-start <name> - Start parallel execution"
|
|
15
|
+
echo ""
|
|
16
|
+
echo "π PRD Commands"
|
|
17
|
+
echo " /pm:prd-new <name> - Launch brainstorming for new product requirement"
|
|
18
|
+
echo " /pm:prd-parse <name> - Convert PRD to implementation epic"
|
|
19
|
+
echo " /pm:prd-list - List all PRDs"
|
|
20
|
+
echo " /pm:prd-edit <name> - Edit existing PRD"
|
|
21
|
+
echo " /pm:prd-status - Show PRD implementation status"
|
|
22
|
+
echo ""
|
|
23
|
+
echo "π Epic Commands"
|
|
24
|
+
echo " /pm:epic-decompose <name> - Break epic into task files"
|
|
25
|
+
echo " /pm:epic-sync <name> - Push epic and tasks to GitHub"
|
|
26
|
+
echo " /pm:epic-oneshot <name> - Decompose and sync in one command"
|
|
27
|
+
echo " /pm:epic-list - List all epics"
|
|
28
|
+
echo " /pm:epic-show <name> - Display epic and its tasks"
|
|
29
|
+
echo " /pm:epic-status [name] - Show epic progress"
|
|
30
|
+
echo " /pm:epic-close <name> - Mark epic as complete"
|
|
31
|
+
echo " /pm:epic-edit <name> - Edit epic details"
|
|
32
|
+
echo " /pm:epic-refresh <name> - Update epic progress from tasks"
|
|
33
|
+
echo " /pm:epic-start <name> - Launch parallel agent execution"
|
|
34
|
+
echo ""
|
|
35
|
+
echo "π Issue Commands"
|
|
36
|
+
echo " /pm:issue-show <num> - Display issue and sub-issues"
|
|
37
|
+
echo " /pm:issue-status <num> - Check issue status"
|
|
38
|
+
echo " /pm:issue-start <num> - Begin work with specialized agent"
|
|
39
|
+
echo " /pm:issue-sync <num> - Push updates to GitHub"
|
|
40
|
+
echo " /pm:issue-close <num> - Mark issue as complete"
|
|
41
|
+
echo " /pm:issue-reopen <num> - Reopen closed issue"
|
|
42
|
+
echo " /pm:issue-edit <num> - Edit issue details"
|
|
43
|
+
echo " /pm:issue-analyze <num> - Analyze for parallel work streams"
|
|
44
|
+
echo ""
|
|
45
|
+
echo "π Workflow Commands"
|
|
46
|
+
echo " /pm:next - Show next priority tasks"
|
|
47
|
+
echo " /pm:status - Overall project dashboard"
|
|
48
|
+
echo " /pm:standup - Daily standup report"
|
|
49
|
+
echo " /pm:blocked - Show blocked tasks"
|
|
50
|
+
echo " /pm:in-progress - List work in progress"
|
|
51
|
+
echo ""
|
|
52
|
+
echo "π Sync Commands"
|
|
53
|
+
echo " /pm:sync - Full bidirectional sync with GitHub"
|
|
54
|
+
echo " /pm:import <issue> - Import existing GitHub issues"
|
|
55
|
+
echo ""
|
|
56
|
+
echo "π§ Maintenance Commands"
|
|
57
|
+
echo " /pm:validate - Check system integrity"
|
|
58
|
+
echo " /pm:clean - Archive completed work"
|
|
59
|
+
echo " /pm:search <query> - Search across all content"
|
|
60
|
+
echo ""
|
|
61
|
+
echo "βοΈ Setup Commands"
|
|
62
|
+
echo " /pm:init - Install dependencies and configure GitHub"
|
|
63
|
+
echo " /pm:help - Show this help message"
|
|
64
|
+
echo ""
|
|
65
|
+
echo "π‘ Tips"
|
|
66
|
+
echo " β’ Use /pm:next to find available work"
|
|
67
|
+
echo " β’ Run /pm:status for quick overview"
|
|
68
|
+
echo " β’ Epic workflow: prd-new β prd-parse β epic-decompose β epic-sync"
|
|
69
|
+
echo " β’ View README.md for complete documentation"
|
|
70
|
+
|
|
71
|
+
exit 0
|