@drunkcoding/agents-and-skills 0.0.14 → 0.0.16
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-plugin/marketplace.json +5 -5
- package/README.md +1 -1
- package/package.json +1 -1
- package/plugins/html-effectiveness/.claude-plugin/plugin.json +1 -1
- package/plugins/plugin-validator/.claude-plugin/plugin.json +1 -1
- package/plugins/team-superpower/.claude-plugin/plugin.json +2 -2
- package/plugins/team-superpower/README.md +24 -5
- package/plugins/team-superpower/agents/backend-developer.md +72 -7
- package/plugins/team-superpower/agents/designer.md +14 -0
- package/plugins/team-superpower/agents/frontend-developer.md +84 -5
- package/plugins/team-superpower/agents/planner.md +140 -17
- package/plugins/team-superpower/agents/qa-engineer.md +16 -0
- package/plugins/team-superpower/agents/reviewer.md +52 -6
- package/plugins/team-superpower/agents/security-engineer.md +99 -5
- package/plugins/team-superpower/agents/software-architect.md +14 -0
- package/plugins/team-superpower/assets/CLAUDE.md.template +96 -0
- package/plugins/team-superpower/assets/ESCALATION.md +34 -1
- package/plugins/team-superpower/assets/SESSION_README.md +102 -2
- package/plugins/team-superpower/commands/team-feature-resume.md +47 -8
- package/plugins/team-superpower/commands/team-feature.md +262 -13
- package/plugins/team-superpower/hooks/task-completed.sh +55 -10
- package/plugins/team-superpower/hooks/task-created.sh +81 -8
- package/plugins/team-superpower/hooks/teammate-idle.sh +1 -2
- package/plugins/team-superpower/scripts/detect-stack.sh +434 -0
- package/plugins/team-superpower/scripts/parse-claudemd.sh +194 -0
- package/plugins/team-superpower/scripts/team-state.sh +2 -2
- package/plugins/tech-graph/.claude-plugin/plugin.json +1 -1
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# parse-claudemd.sh — extract the team-superpower YAML block from CLAUDE.md.
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# parse-claudemd.sh extract [<path-to-CLAUDE.md>] prints the YAML block to stdout
|
|
6
|
+
# parse-claudemd.sh shape [<path-to-CLAUDE.md>] prints "full-stack" | "be-only" | "fe-only" | "none"
|
|
7
|
+
# parse-claudemd.sh get <dotted.key> [<path>] prints a single scalar value
|
|
8
|
+
# (limited: top-level group + leaf, e.g. backend.test_command)
|
|
9
|
+
#
|
|
10
|
+
# Exit codes:
|
|
11
|
+
# 0 success
|
|
12
|
+
# 1 CLAUDE.md missing or contains no `team-superpower` fenced block
|
|
13
|
+
# 2 bad arguments
|
|
14
|
+
# 3 key not found (only for `get`)
|
|
15
|
+
#
|
|
16
|
+
# Notes:
|
|
17
|
+
# - The fenced block is recognised by the literal opener "```team-superpower"
|
|
18
|
+
# (with no language indent) and the matching "```" closer.
|
|
19
|
+
# - Comments starting with `#` (after optional whitespace) are stripped before
|
|
20
|
+
# value extraction. Inline `# comment` tails are also stripped.
|
|
21
|
+
# - This is a deliberately tiny parser. It does NOT validate the schema.
|
|
22
|
+
# Schema validation is the lead's job (it halts on bad values per the spec).
|
|
23
|
+
|
|
24
|
+
set -euo pipefail
|
|
25
|
+
|
|
26
|
+
usage() {
|
|
27
|
+
sed -n '2,30p' "$0" | sed 's/^# \{0,1\}//'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
CLAUDE_FILE_DEFAULT="${CLAUDE_PROJECT_DIR:-$PWD}/CLAUDE.md"
|
|
31
|
+
|
|
32
|
+
extract_block() {
|
|
33
|
+
local file="$1"
|
|
34
|
+
[ -f "$file" ] || return 1
|
|
35
|
+
# awk: print lines strictly between the opener and closer fences.
|
|
36
|
+
awk '
|
|
37
|
+
/^```team-superpower[[:space:]]*$/ { in_block = 1; next }
|
|
38
|
+
in_block && /^```[[:space:]]*$/ { in_block = 0; exit }
|
|
39
|
+
in_block { print }
|
|
40
|
+
' "$file"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
block_has_content() {
|
|
44
|
+
# Returns 0 if the YAML block extracted to stdin has at least one non-comment,
|
|
45
|
+
# non-blank line; 1 otherwise.
|
|
46
|
+
local payload
|
|
47
|
+
payload="$(cat || true)"
|
|
48
|
+
printf '%s' "$payload" | grep -vE '^[[:space:]]*(#|$)' | head -n1 | grep -q .
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# Strip an inline `# comment` tail (but not `#` inside a quoted string — we
|
|
52
|
+
# tolerate the simple case here, the spec doesn't ship complex YAML values).
|
|
53
|
+
strip_comment() {
|
|
54
|
+
sed -E 's/[[:space:]]+#[^"\x27]*$//' | sed -E 's/^[[:space:]]*#.*$//'
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
cmd_extract() {
|
|
58
|
+
local file="${1:-$CLAUDE_FILE_DEFAULT}"
|
|
59
|
+
if [ ! -f "$file" ]; then
|
|
60
|
+
echo "parse-claudemd: $file does not exist" >&2
|
|
61
|
+
return 1
|
|
62
|
+
fi
|
|
63
|
+
local block
|
|
64
|
+
block="$(extract_block "$file")"
|
|
65
|
+
if [ -z "$block" ] || ! printf '%s' "$block" | block_has_content; then
|
|
66
|
+
echo "parse-claudemd: no \`team-superpower\` block found in $file" >&2
|
|
67
|
+
return 1
|
|
68
|
+
fi
|
|
69
|
+
printf '%s\n' "$block"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# Read a top-level scalar like `backend: none` or detect whether a group is
|
|
73
|
+
# explicitly "none".
|
|
74
|
+
group_is_none() {
|
|
75
|
+
# group_is_none <yaml-block-on-stdin> <group-name>
|
|
76
|
+
local group="$2"
|
|
77
|
+
awk -v g="$group" '
|
|
78
|
+
BEGIN { found = 0 }
|
|
79
|
+
{
|
|
80
|
+
sub(/[[:space:]]+#[^"\x27]*$/, "")
|
|
81
|
+
sub(/^[[:space:]]*#.*$/, "")
|
|
82
|
+
}
|
|
83
|
+
$0 ~ "^"g":[[:space:]]+none[[:space:]]*$" { found = 1; exit }
|
|
84
|
+
END { exit found ? 0 : 1 }
|
|
85
|
+
' <<<"$1"
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
# A group is "present" if there is `group:` followed (on subsequent indented
|
|
89
|
+
# lines) by at least one non-comment, non-blank key/value pair.
|
|
90
|
+
group_is_present() {
|
|
91
|
+
# group_is_present <yaml-block> <group-name>
|
|
92
|
+
local group="$2"
|
|
93
|
+
awk -v g="$group" '
|
|
94
|
+
BEGIN { state = 0; has_keys = 0 }
|
|
95
|
+
{
|
|
96
|
+
line = $0
|
|
97
|
+
# strip comments
|
|
98
|
+
sub(/[[:space:]]+#[^"\x27]*$/, "", line)
|
|
99
|
+
sub(/^[[:space:]]*#.*$/, "", line)
|
|
100
|
+
}
|
|
101
|
+
line ~ "^"g":[[:space:]]*$" { state = 1; next }
|
|
102
|
+
line ~ "^"g":[[:space:]]+none" { state = 0; exit }
|
|
103
|
+
state == 1 && line ~ /^[^[:space:]]/ { state = 0 }
|
|
104
|
+
state == 1 && line ~ /^[[:space:]]+[A-Za-z_][A-Za-z0-9_]*:/ { has_keys = 1 }
|
|
105
|
+
END { exit has_keys ? 0 : 1 }
|
|
106
|
+
' <<<"$1"
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
cmd_shape() {
|
|
110
|
+
local file="${1:-$CLAUDE_FILE_DEFAULT}"
|
|
111
|
+
local block
|
|
112
|
+
block="$(cmd_extract "$file")" || return 1
|
|
113
|
+
|
|
114
|
+
local be_present=1 fe_present=1
|
|
115
|
+
group_is_present "$block" backend || be_present=0
|
|
116
|
+
group_is_present "$block" frontend || fe_present=0
|
|
117
|
+
|
|
118
|
+
if [ "$be_present" -eq 1 ] && [ "$fe_present" -eq 1 ]; then echo "full-stack"
|
|
119
|
+
elif [ "$be_present" -eq 1 ]; then echo "be-only"
|
|
120
|
+
elif [ "$fe_present" -eq 1 ]; then echo "fe-only"
|
|
121
|
+
else echo "none"
|
|
122
|
+
fi
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
cmd_get() {
|
|
126
|
+
local key="${1:-}"
|
|
127
|
+
local file="${2:-$CLAUDE_FILE_DEFAULT}"
|
|
128
|
+
if [ -z "$key" ]; then usage >&2; return 2; fi
|
|
129
|
+
local block
|
|
130
|
+
block="$(cmd_extract "$file")" || return 1
|
|
131
|
+
|
|
132
|
+
case "$key" in
|
|
133
|
+
*.*)
|
|
134
|
+
local group leaf
|
|
135
|
+
group="${key%%.*}"
|
|
136
|
+
leaf="${key#*.}"
|
|
137
|
+
local value
|
|
138
|
+
value="$(awk -v g="$group" -v k="$leaf" '
|
|
139
|
+
BEGIN { in_group = 0; pat = "^[[:space:]]+" k "[[:space:]]*:[[:space:]]*" }
|
|
140
|
+
{
|
|
141
|
+
line = $0
|
|
142
|
+
sub(/[[:space:]]+#[^"\x27]*$/, "", line)
|
|
143
|
+
sub(/^[[:space:]]*#.*$/, "", line)
|
|
144
|
+
}
|
|
145
|
+
line ~ "^"g":[[:space:]]*$" { in_group = 1; next }
|
|
146
|
+
in_group && line ~ /^[^[:space:]]/ { in_group = 0 }
|
|
147
|
+
in_group && line ~ pat {
|
|
148
|
+
v = line
|
|
149
|
+
sub(pat, "", v)
|
|
150
|
+
sub(/[[:space:]]+$/, "", v)
|
|
151
|
+
gsub(/^"|"$/, "", v)
|
|
152
|
+
gsub(/^\x27|\x27$/, "", v)
|
|
153
|
+
print v
|
|
154
|
+
exit
|
|
155
|
+
}
|
|
156
|
+
' <<<"$block")"
|
|
157
|
+
if [ -z "$value" ]; then return 3; fi
|
|
158
|
+
printf '%s\n' "$value"
|
|
159
|
+
;;
|
|
160
|
+
*)
|
|
161
|
+
# Top-level scalar (e.g. "backend" for `backend: none`)
|
|
162
|
+
local value
|
|
163
|
+
value="$(awk -v k="$key" '
|
|
164
|
+
BEGIN { pat = "^" k ":[[:space:]]+" }
|
|
165
|
+
{
|
|
166
|
+
line = $0
|
|
167
|
+
sub(/[[:space:]]+#[^"\x27]*$/, "", line)
|
|
168
|
+
sub(/^[[:space:]]*#.*$/, "", line)
|
|
169
|
+
}
|
|
170
|
+
line ~ pat {
|
|
171
|
+
v = line; sub(pat, "", v); sub(/[[:space:]]+$/, "", v)
|
|
172
|
+
print v
|
|
173
|
+
exit
|
|
174
|
+
}
|
|
175
|
+
' <<<"$block")"
|
|
176
|
+
if [ -z "$value" ]; then return 3; fi
|
|
177
|
+
printf '%s\n' "$value"
|
|
178
|
+
;;
|
|
179
|
+
esac
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
main() {
|
|
183
|
+
local sub="${1:-}"
|
|
184
|
+
shift || true
|
|
185
|
+
case "$sub" in
|
|
186
|
+
extract) cmd_extract "$@" ;;
|
|
187
|
+
shape) cmd_shape "$@" ;;
|
|
188
|
+
get) cmd_get "$@" ;;
|
|
189
|
+
-h|--help|"") usage; [ -z "$sub" ] && return 2 || return 0 ;;
|
|
190
|
+
*) echo "unknown subcommand: $sub" >&2; usage >&2; return 2 ;;
|
|
191
|
+
esac
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
main "$@"
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
# 1 dry-run completed with items to remove (caller should re-run with --force)
|
|
29
29
|
# 2 bad arguments
|
|
30
30
|
# 3 heartbeat indicates a live lead; refuse without --ignore-heartbeat
|
|
31
|
-
# 4 nothing to clean up (cleanup
|
|
31
|
+
# 4 nothing to clean up (cleanup only; scan is read-only and always exits 0)
|
|
32
32
|
|
|
33
33
|
set -euo pipefail
|
|
34
34
|
|
|
@@ -82,7 +82,7 @@ cmd_scan() {
|
|
|
82
82
|
slugs="$(list_all_team_slugs)"
|
|
83
83
|
if [ -z "$slugs" ]; then
|
|
84
84
|
echo "No team-superpower teams found under $TEAMS_DIR"
|
|
85
|
-
return
|
|
85
|
+
return 0
|
|
86
86
|
fi
|
|
87
87
|
echo "team-superpower teams on this machine:"
|
|
88
88
|
while IFS= read -r s; do
|