feat(dashboard): add dashboard skill for milestone/issue overview
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
47
skills/dashboard/SKILL.md
Normal file
47
skills/dashboard/SKILL.md
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
name: dashboard
|
||||
description: >
|
||||
Display milestones with unblocked issues at a glance.
|
||||
Use when you want to see project progress and which issues are ready to work on.
|
||||
Invoke with /dashboard [milestone-name-filter]
|
||||
model: claude-haiku-4-5
|
||||
user-invocable: true
|
||||
context: fork
|
||||
allowed-tools:
|
||||
- Bash(~/.claude/skills/dashboard/scripts/generate-dashboard.sh*)
|
||||
---
|
||||
|
||||
# Dashboard
|
||||
|
||||
@~/.claude/skills/gitea/SKILL.md
|
||||
|
||||
Display all milestones and their unblocked issues. Issues are considered unblocked if they have no open blockers in their dependency list.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Run the dashboard script** with the milestone filter argument (if provided):
|
||||
```bash
|
||||
~/.claude/skills/dashboard/scripts/generate-dashboard.sh "$1"
|
||||
```
|
||||
|
||||
2. **Display the output** to the user
|
||||
|
||||
The script automatically:
|
||||
- Fetches all milestones from the repository
|
||||
- For each milestone, gets all open issues
|
||||
- For each issue, checks dependencies with `tea issues deps list`
|
||||
- Categorizes issues as unblocked (no open dependencies) or blocked (has open dependencies)
|
||||
- Displays results grouped by milestone in this format:
|
||||
|
||||
```
|
||||
## Milestone: Release 1.0
|
||||
|
||||
✓ Unblocked (3):
|
||||
#42 Implement feature X
|
||||
#43 Fix bug in Y
|
||||
#45 Add tests for Z
|
||||
|
||||
⊘ Blocked (2):
|
||||
#40 Feature A (blocked by #39)
|
||||
#41 Feature B (blocked by #38, #37)
|
||||
```
|
||||
83
skills/dashboard/scripts/generate-dashboard.sh
Executable file
83
skills/dashboard/scripts/generate-dashboard.sh
Executable file
@@ -0,0 +1,83 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Generate dashboard showing milestones with unblocked/blocked issues
|
||||
# Usage: ./generate-dashboard.sh [milestone-filter]
|
||||
|
||||
MILESTONE_FILTER="${1:-}"
|
||||
|
||||
# Get all milestones
|
||||
milestones_json=$(tea milestones -o json)
|
||||
|
||||
# Parse milestone names
|
||||
milestone_names=$(echo "$milestones_json" | jq -r '.[].title')
|
||||
|
||||
# Process each milestone
|
||||
while IFS= read -r milestone; do
|
||||
# Skip if filter provided and doesn't match
|
||||
if [[ -n "$MILESTONE_FILTER" && ! "$milestone" =~ $MILESTONE_FILTER ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "## Milestone: $milestone"
|
||||
echo ""
|
||||
|
||||
# Get open issues for this milestone
|
||||
issues_json=$(tea issues --milestones "$milestone" --state open -o json 2>/dev/null || echo "[]")
|
||||
|
||||
# Skip empty milestones or invalid JSON
|
||||
issue_count=$(echo "$issues_json" | jq -e 'length' 2>/dev/null || echo "0")
|
||||
if [[ "$issue_count" -eq 0 ]]; then
|
||||
echo "No open issues"
|
||||
echo ""
|
||||
continue
|
||||
fi
|
||||
|
||||
# Arrays for categorizing issues
|
||||
declare -a unblocked=()
|
||||
declare -a blocked=()
|
||||
|
||||
# Process each issue
|
||||
while IFS=$'\t' read -r number title; do
|
||||
# Check dependencies (tea returns plain text "Issue #N has no dependencies" when empty)
|
||||
deps_output=$(tea issues deps list "$number" -o json 2>/dev/null || echo "")
|
||||
|
||||
# If output contains "has no dependencies", treat as empty array
|
||||
if [[ "$deps_output" == *"has no dependencies"* ]]; then
|
||||
deps_json="[]"
|
||||
else
|
||||
deps_json="$deps_output"
|
||||
fi
|
||||
|
||||
# Count open dependencies
|
||||
open_deps=$(echo "$deps_json" | jq -r '[.[] | select(.state == "open")] | length' 2>/dev/null || echo "0")
|
||||
|
||||
if [[ "$open_deps" -eq 0 ]]; then
|
||||
# No open blockers - unblocked
|
||||
unblocked+=("#$number $title")
|
||||
else
|
||||
# Has open blockers - blocked
|
||||
blocker_list=$(echo "$deps_json" | jq -r '[.[] | select(.state == "open") | "#\(.index)"] | join(", ")')
|
||||
blocked+=("#$number $title (blocked by $blocker_list)")
|
||||
fi
|
||||
done < <(echo "$issues_json" | jq -r '.[] | [.index, .title] | @tsv')
|
||||
|
||||
# Display unblocked issues
|
||||
echo "✓ Unblocked (${#unblocked[@]}):"
|
||||
if [[ ${#unblocked[@]} -eq 0 ]]; then
|
||||
echo " (none)"
|
||||
else
|
||||
printf ' %s\n' "${unblocked[@]}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Display blocked issues
|
||||
echo "⊘ Blocked (${#blocked[@]}):"
|
||||
if [[ ${#blocked[@]} -eq 0 ]]; then
|
||||
echo " (none)"
|
||||
else
|
||||
printf ' %s\n' "${blocked[@]}"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
done <<< "$milestone_names"
|
||||
Reference in New Issue
Block a user