@drunkcoding/agents-and-skills 0.0.19 → 0.0.23

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.
Files changed (30) hide show
  1. package/.claude-plugin/marketplace.json +5 -5
  2. package/package.json +1 -1
  3. package/plugins/auto-power/.claude-plugin/plugin.json +1 -1
  4. package/plugins/html-effectiveness/.claude-plugin/plugin.json +1 -1
  5. package/plugins/plugin-validator/.claude-plugin/plugin.json +1 -1
  6. package/plugins/team-superpower/.claude-plugin/plugin.json +1 -1
  7. package/plugins/team-superpower/README.md +186 -115
  8. package/plugins/team-superpower/agents/backend-developer.md +105 -73
  9. package/plugins/team-superpower/agents/feature-planner.md +66 -0
  10. package/plugins/team-superpower/agents/frontend-developer.md +108 -70
  11. package/plugins/team-superpower/agents/orchestrator.md +83 -0
  12. package/plugins/team-superpower/agents/qc-engineer.md +84 -0
  13. package/plugins/team-superpower/agents/security-engineer.md +79 -44
  14. package/plugins/team-superpower/agents/solution-architect.md +80 -0
  15. package/plugins/team-superpower/agents/team-leader.md +100 -0
  16. package/plugins/team-superpower/assets/CLAUDE.md.template +22 -18
  17. package/plugins/team-superpower/assets/ESCALATION.md +114 -66
  18. package/plugins/team-superpower/assets/SESSION_README.md +232 -159
  19. package/plugins/team-superpower/commands/team-feature.md +191 -645
  20. package/plugins/team-superpower/hooks/task-completed.sh +100 -182
  21. package/plugins/team-superpower/hooks/task-created.sh +55 -38
  22. package/plugins/team-superpower/hooks/teammate-idle.sh +118 -13
  23. package/plugins/team-superpower/scripts/team-state.sh +106 -37
  24. package/plugins/tech-graph/.claude-plugin/plugin.json +1 -1
  25. package/plugins/team-superpower/agents/designer.md +0 -65
  26. package/plugins/team-superpower/agents/planner.md +0 -242
  27. package/plugins/team-superpower/agents/qa-engineer.md +0 -103
  28. package/plugins/team-superpower/agents/reviewer.md +0 -175
  29. package/plugins/team-superpower/agents/software-architect.md +0 -60
  30. package/plugins/team-superpower/commands/team-feature-resume.md +0 -185
@@ -1,15 +1,37 @@
1
1
  #!/usr/bin/env bash
2
- # TeammateIdle hook — block idle if there are unanswered inbound peer messages.
2
+ # TeammateIdle hook — v5 role-aware routing.
3
3
  #
4
- # Reads the hook event payload from stdin. Expected JSON fields (best-effort —
5
- # the agent-teams runtime may evolve; we only fail closed on what we can verify):
6
- # - mailbox: array of { from, replied, ... }
7
- # - teammate: string (the idling teammate's role)
4
+ # Reads the hook event payload from stdin. Expected JSON fields:
5
+ # - mailbox: array of { from, kind, replied, ... } recent SendMessage history
6
+ # - teammate: string (the idling teammate's role; one of
7
+ # orchestrator | team-leader | solution-architect | feature-planner |
8
+ # security-engineer | backend-developer | frontend-developer | qc-engineer)
8
9
  #
9
- # Behaviour:
10
- # - count messages where from != "lead" AND replied == false
11
- # - if count > 0 -> exit 2 with stderr BLOCKED_IDLE
12
- # - else -> exit 0
10
+ # v5 behaviour: routing depends on role.
11
+ #
12
+ # backend-developer / frontend-developer:
13
+ # - block if any unanswered message FROM team-leader (implementer owes a reply)
14
+ # - block if a self-sent ESCALATE has no reply within heartbeat (advisory log)
15
+ # - otherwise advisory: wave dispatch may still be in flight; ok to idle
16
+ #
17
+ # team-leader:
18
+ # - block if SPAWN_REQUEST or RESTART_REQUEST has no SPAWN_DONE / RESTART_DONE
19
+ # reply from lead/orchestrator within heartbeat (must keep coordinating)
20
+ # - block if any unanswered ESCALATE from an implementer (must route)
21
+ # - otherwise advisory tick
22
+ #
23
+ # qc-engineer:
24
+ # - block if QC_REWORK_NEEDED has no reply (lead must acknowledge before shutdown)
25
+ # - otherwise advisory tick
26
+ #
27
+ # solution-architect / feature-planner / security-engineer (phase A roles):
28
+ # - block if owner sign-off touchpoint message has no reply yet
29
+ # - otherwise advisory tick (shutdown is owner-driven via lead)
30
+ #
31
+ # orchestrator (lead):
32
+ # - block if any unanswered SPAWN_REQUEST / RESTART_REQUEST inbound from
33
+ # team-leader (lead is the single spawner)
34
+ # - otherwise advisory tick (lead drives owner touchpoints separately)
13
35
  #
14
36
  # Logs every invocation to .claude/hooks/log.jsonl in the project root for tuning.
15
37
 
@@ -33,12 +55,95 @@ if ! command -v jq >/dev/null 2>&1; then
33
55
  exit 0
34
56
  fi
35
57
 
36
- unanswered="$(printf '%s' "$payload" | jq '[.mailbox[]? | select((.from // "") != "lead") | select((.replied // false) == false)] | length' 2>/dev/null || echo 0)"
58
+ teammate="$(printf '%s' "$payload" | jq -r '.teammate // ""' 2>/dev/null || echo "")"
59
+
60
+ # Helper: count unanswered inbound messages where .from matches a pattern.
61
+ count_unanswered_from() {
62
+ local from_pattern="$1"
63
+ printf '%s' "$payload" \
64
+ | jq --arg p "$from_pattern" \
65
+ '[.mailbox[]?
66
+ | select(((.from // "") | test($p)))
67
+ | select((.replied // false) == false)
68
+ ] | length' \
69
+ 2>/dev/null \
70
+ || echo 0
71
+ }
72
+
73
+ # Helper: count self-sent outbound messages of a given kind with no reply yet.
74
+ count_outbound_unanswered_kind() {
75
+ local kind_pattern="$1"
76
+ printf '%s' "$payload" \
77
+ | jq --arg k "$kind_pattern" \
78
+ '[.mailbox[]?
79
+ | select(((.direction // "in") == "out"))
80
+ | select(((.kind // "") | test($k)))
81
+ | select((.replied // false) == false)
82
+ ] | length' \
83
+ 2>/dev/null \
84
+ || echo 0
85
+ }
86
+
87
+ warn=""
37
88
 
38
- printf '{"ts":"%s","hook":"teammate-idle","unanswered":%s}\n' "$ts" "$unanswered" >> "$LOG_FILE"
89
+ case "$teammate" in
90
+ backend-developer|frontend-developer)
91
+ unanswered_from_leader="$(count_unanswered_from '^team-leader$')"
92
+ if [ "${unanswered_from_leader:-0}" -gt 0 ]; then
93
+ warn="BLOCKED_IDLE_implementer_owes_team-leader_reply"
94
+ fi
95
+ ;;
96
+ team-leader)
97
+ spawn_pending="$(count_outbound_unanswered_kind 'SPAWN_REQUEST|RESTART_REQUEST')"
98
+ escalate_pending="$(count_unanswered_from '^(backend-developer|frontend-developer)$')"
99
+ if [ "${spawn_pending:-0}" -gt 0 ]; then
100
+ warn="BLOCKED_IDLE_team-leader_awaiting_lead_on_spawn_or_restart"
101
+ elif [ "${escalate_pending:-0}" -gt 0 ]; then
102
+ warn="BLOCKED_IDLE_team-leader_owes_implementer_escalate_reply"
103
+ fi
104
+ ;;
105
+ qc-engineer)
106
+ qc_pending="$(count_outbound_unanswered_kind 'QC_REWORK_NEEDED')"
107
+ if [ "${qc_pending:-0}" -gt 0 ]; then
108
+ warn="BLOCKED_IDLE_qc-engineer_awaiting_lead_ack"
109
+ fi
110
+ ;;
111
+ solution-architect|feature-planner|security-engineer)
112
+ handover_pending="$(count_outbound_unanswered_kind 'HANDOVER_READY|SEC_PASSED|SEC_BLOCKED')"
113
+ if [ "${handover_pending:-0}" -gt 0 ]; then
114
+ warn="BLOCKED_IDLE_phaseA_awaiting_owner_signoff"
115
+ fi
116
+ ;;
117
+ orchestrator)
118
+ lead_inbound_pending="$(count_unanswered_from '^team-leader$')"
119
+ if [ "${lead_inbound_pending:-0}" -gt 0 ]; then
120
+ warn="BLOCKED_IDLE_orchestrator_unhandled_team-leader_request"
121
+ fi
122
+ ;;
123
+ "")
124
+ # Unknown role: fall back to legacy v4 behaviour (any unanswered non-lead inbound).
125
+ legacy_unanswered="$(printf '%s' "$payload" | jq '[.mailbox[]? | select((.from // "") != "lead") | select((.replied // false) == false)] | length' 2>/dev/null || echo 0)"
126
+ if [ "${legacy_unanswered:-0}" -gt 0 ]; then
127
+ warn="BLOCKED_IDLE_legacy_unanswered_inbound"
128
+ fi
129
+ ;;
130
+ *)
131
+ # Unknown but non-empty role — log advisory only, do not block.
132
+ :
133
+ ;;
134
+ esac
39
135
 
40
- if [ "${unanswered:-0}" -gt 0 ]; then
41
- printf '{"ts":"%s","hook":"teammate-idle","warn":"blocked_idle","unanswered":%s}\n' "$ts" "$unanswered" >> "$LOG_FILE"
136
+ if [ -n "$warn" ]; then
137
+ printf '{"ts":"%s","hook":"teammate-idle","teammate":%s,"warn":%s}\n' \
138
+ "$ts" \
139
+ "$(printf '%s' "$teammate" | jq -Rs .)" \
140
+ "$(printf '%s' "$warn" | jq -Rs .)" \
141
+ >> "$LOG_FILE"
142
+ else
143
+ printf '{"ts":"%s","hook":"teammate-idle","teammate":%s,"ok":true}\n' \
144
+ "$ts" \
145
+ "$(printf '%s' "$teammate" | jq -Rs .)" \
146
+ >> "$LOG_FILE"
42
147
  fi
43
148
 
44
149
  exit 0
@@ -1,25 +1,36 @@
1
1
  #!/usr/bin/env bash
2
- # team-state.sh — inspect and clean up team-superpower team state.
2
+ # team-state.sh — inspect and clean up team-superpower v5 team state.
3
3
  #
4
4
  # Subcommands:
5
5
  # scan List every known superpower-* team on this machine.
6
6
  # scan <slug> Inspect a single slug; print state for the lead/owner.
7
+ # members <slug> Read team config.json and list current members + roles.
7
8
  # cleanup <slug> Dry-run cleanup; print what would be removed (exit 1).
8
- # cleanup <slug> --force Remove team config, task list, tmux session.
9
+ # cleanup <slug> --force Remove team config, task list, .team-superpower/ artefacts.
9
10
  #
10
11
  # Flags (cleanup only):
11
12
  # --force Apply the cleanup (otherwise dry-run).
12
13
  # --ignore-heartbeat Skip the "lead may still be alive" refusal.
13
14
  # Required when the heartbeat file is < 10 min old.
14
15
  #
16
+ # v5 changes (delta from v4):
17
+ # - Removed: tmux session handling (Agent Teams runs in-process, not in tmux).
18
+ # - Added: `members` subcommand reads ~/.claude/teams/superpower-<slug>/config.json
19
+ # and lists current teammates + roles (single-team lifecycle visibility).
20
+ # - Added: cleanup now removes .team-superpower/ work artefacts (spawn-briefs,
21
+ # static-check logs, handover artefacts the lead created).
22
+ # - Added: scan shows cycle_restart_count from docs/superpowers/sessions/<slug>.cycle
23
+ # if present (for v5's restart-on-stuck telemetry).
24
+ #
15
25
  # What this script preserves (always):
16
- # - docs/superpowers/{specs,plans,reviews} durable artefacts
17
- # - the project-side checkpoint markdown kept; appended with a Cleanup record
26
+ # - docs/superpowers/{specs,plans,reviews,handovers} durable artefacts
27
+ # - the project-side checkpoint markdown kept; appended with a Cleanup record
18
28
  #
19
29
  # What it removes (with --force):
20
- # - ~/.claude/teams/superpower-<slug>/ team config
21
- # - ~/.claude/tasks/superpower-<slug>/ shared task list
22
- # - tmux session "claude-superpower-<slug>" best-effort
30
+ # - ~/.claude/teams/superpower-<slug>/ team config
31
+ # - ~/.claude/tasks/superpower-<slug>/ shared task list
32
+ # - .team-superpower/spawn-briefs/ wave brief files
33
+ # - .team-superpower/static-check-*.log per-task static-check logs
23
34
  #
24
35
  # Idempotent: re-running is safe.
25
36
  #
@@ -37,6 +48,7 @@ TEAMS_DIR="$CLAUDE_HOME/teams"
37
48
  TASKS_DIR="$CLAUDE_HOME/tasks"
38
49
  PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$PWD}"
39
50
  SESSIONS_DIR="$PROJECT_DIR/docs/superpowers/sessions"
51
+ ARTEFACTS_DIR="$PROJECT_DIR/.team-superpower"
40
52
  HEARTBEAT_TTL_SECONDS=600 # 10 min
41
53
 
42
54
  print_usage() {
@@ -44,13 +56,17 @@ print_usage() {
44
56
  }
45
57
 
46
58
  team_name_for_slug() { printf 'superpower-%s' "$1"; }
47
- tmux_name_for_slug() { printf 'claude-superpower-%s' "$1"; }
48
59
 
49
60
  heartbeat_file_for_slug() {
50
61
  local slug="$1"
51
62
  printf '%s/%s.heartbeat' "$SESSIONS_DIR" "$slug"
52
63
  }
53
64
 
65
+ cycle_file_for_slug() {
66
+ local slug="$1"
67
+ printf '%s/%s.cycle' "$SESSIONS_DIR" "$slug"
68
+ }
69
+
54
70
  checkpoint_for_slug() {
55
71
  local slug="$1"
56
72
  if [ ! -d "$SESSIONS_DIR" ]; then return; fi
@@ -87,9 +103,7 @@ cmd_scan() {
87
103
  echo "team-superpower teams on this machine:"
88
104
  while IFS= read -r s; do
89
105
  [ -z "$s" ] && continue
90
- local team team_dir hb age
91
- team="$(team_name_for_slug "$s")"
92
- team_dir="$TEAMS_DIR/$team"
106
+ local hb age
93
107
  hb="$(heartbeat_file_for_slug "$s")"
94
108
  age="$(heartbeat_age_seconds "$hb")"
95
109
  if [ "$age" -lt 0 ]; then
@@ -101,39 +115,73 @@ cmd_scan() {
101
115
  return 0
102
116
  fi
103
117
 
104
- local team team_dir task_dir hb age ckpt tmux_name
118
+ local team team_dir task_dir hb age ckpt cycle_file restart_count
105
119
  team="$(team_name_for_slug "$slug")"
106
120
  team_dir="$TEAMS_DIR/$team"
107
121
  task_dir="$TASKS_DIR/$team"
108
122
  hb="$(heartbeat_file_for_slug "$slug")"
109
123
  age="$(heartbeat_age_seconds "$hb")"
110
124
  ckpt="$(checkpoint_for_slug "$slug")"
111
- tmux_name="$(tmux_name_for_slug "$slug")"
112
-
113
- printf 'slug: %s\n' "$slug"
114
- printf 'team_name: %s\n' "$team"
115
- printf 'team_config: %s\n' "$team_dir"
116
- if [ -d "$team_dir" ]; then printf 'team_config_state: present\n'; else printf 'team_config_state: absent\n'; fi
117
- printf 'task_list: %s\n' "$task_dir"
118
- if [ -d "$task_dir" ]; then printf 'task_list_state: present\n'; else printf 'task_list_state: absent\n'; fi
119
- printf 'checkpoint: %s\n' "${ckpt:-<none>}"
125
+ cycle_file="$(cycle_file_for_slug "$slug")"
126
+ restart_count=0
127
+ if [ -f "$cycle_file" ]; then
128
+ restart_count="$(head -n1 "$cycle_file" | tr -d '[:space:]')"
129
+ fi
130
+
131
+ printf 'slug: %s\n' "$slug"
132
+ printf 'team_name: %s\n' "$team"
133
+ printf 'team_config: %s\n' "$team_dir"
134
+ if [ -d "$team_dir" ]; then printf 'team_config_state: present\n'; else printf 'team_config_state: absent\n'; fi
135
+ printf 'task_list: %s\n' "$task_dir"
136
+ if [ -d "$task_dir" ]; then printf 'task_list_state: present\n'; else printf 'task_list_state: absent\n'; fi
137
+ printf 'checkpoint: %s\n' "${ckpt:-<none>}"
138
+ printf 'cycle_restart_count: %s\n' "${restart_count:-0}"
120
139
  if [ "$age" -lt 0 ]; then
121
- printf 'heartbeat: <none>\n'
122
- printf 'liveness: unknown (no heartbeat — treat as stale)\n'
140
+ printf 'heartbeat: <none>\n'
141
+ printf 'liveness: unknown (no heartbeat — treat as stale)\n'
123
142
  else
124
- printf 'heartbeat: %s (%ds ago)\n' "$hb" "$age"
143
+ printf 'heartbeat: %s (%ds ago)\n' "$hb" "$age"
125
144
  if [ "$age" -lt "$HEARTBEAT_TTL_SECONDS" ]; then
126
- printf 'liveness: LIKELY ALIVE (heartbeat < %ds)\n' "$HEARTBEAT_TTL_SECONDS"
145
+ printf 'liveness: LIKELY ALIVE (heartbeat < %ds)\n' "$HEARTBEAT_TTL_SECONDS"
127
146
  else
128
- printf 'liveness: stale\n'
147
+ printf 'liveness: stale\n'
129
148
  fi
130
149
  fi
131
- printf 'tmux_session: %s\n' "$tmux_name"
132
- if command -v tmux >/dev/null 2>&1 && tmux has-session -t "$tmux_name" 2>/dev/null; then
133
- printf 'tmux_state: present\n'
150
+ if [ -d "$ARTEFACTS_DIR" ]; then
151
+ local brief_count log_count
152
+ brief_count="$(find "$ARTEFACTS_DIR/spawn-briefs" -maxdepth 1 -type f -name '*.md' 2>/dev/null | wc -l | tr -d ' ')"
153
+ log_count="$(find "$ARTEFACTS_DIR" -maxdepth 1 -type f -name 'static-check-*.log' 2>/dev/null | wc -l | tr -d ' ')"
154
+ printf 'spawn_briefs: %s file(s)\n' "${brief_count:-0}"
155
+ printf 'static_check_logs: %s file(s)\n' "${log_count:-0}"
134
156
  else
135
- printf 'tmux_state: absent\n'
157
+ printf 'artefacts_dir: absent\n'
158
+ fi
159
+ }
160
+
161
+ cmd_members() {
162
+ local slug="${1:-}"
163
+ if [ -z "$slug" ]; then
164
+ echo "usage: team-state.sh members <slug>" >&2
165
+ return 2
166
+ fi
167
+ local team team_dir config
168
+ team="$(team_name_for_slug "$slug")"
169
+ team_dir="$TEAMS_DIR/$team"
170
+ config="$team_dir/config.json"
171
+ if [ ! -f "$config" ]; then
172
+ echo "team config not found: $config" >&2
173
+ return 4
136
174
  fi
175
+ if ! command -v jq >/dev/null 2>&1; then
176
+ echo "jq not installed; raw config follows:" >&2
177
+ cat "$config"
178
+ return 0
179
+ fi
180
+ printf 'team: %s\n' "$team"
181
+ printf 'config: %s\n' "$config"
182
+ printf 'members:\n'
183
+ jq -r '.members[]? | " - " + (.role // "<no-role>") + " (id: " + (.id // "<no-id>") + ", status: " + (.status // "unknown") + ")"' "$config" 2>/dev/null \
184
+ || jq -r '. | tostring' "$config"
137
185
  }
138
186
 
139
187
  cmd_cleanup() {
@@ -153,21 +201,27 @@ cmd_cleanup() {
153
201
  return 2
154
202
  fi
155
203
 
156
- local team team_dir task_dir hb age ckpt tmux_name
204
+ local team team_dir task_dir hb age ckpt
157
205
  team="$(team_name_for_slug "$slug")"
158
206
  team_dir="$TEAMS_DIR/$team"
159
207
  task_dir="$TASKS_DIR/$team"
160
208
  hb="$(heartbeat_file_for_slug "$slug")"
161
209
  age="$(heartbeat_age_seconds "$hb")"
162
210
  ckpt="$(checkpoint_for_slug "$slug")"
163
- tmux_name="$(tmux_name_for_slug "$slug")"
164
211
 
165
212
  # Build the work list.
166
213
  local items=()
167
214
  [ -d "$team_dir" ] && items+=("team_config:$team_dir")
168
215
  [ -d "$task_dir" ] && items+=("task_list:$task_dir")
169
- if command -v tmux >/dev/null 2>&1 && tmux has-session -t "$tmux_name" 2>/dev/null; then
170
- items+=("tmux_session:$tmux_name")
216
+ if [ -d "$ARTEFACTS_DIR/spawn-briefs" ]; then
217
+ local n
218
+ n="$(find "$ARTEFACTS_DIR/spawn-briefs" -maxdepth 1 -type f -name '*.md' 2>/dev/null | wc -l | tr -d ' ')"
219
+ [ "${n:-0}" -gt 0 ] && items+=("spawn_briefs:$ARTEFACTS_DIR/spawn-briefs (${n} files)")
220
+ fi
221
+ if [ -d "$ARTEFACTS_DIR" ]; then
222
+ local n
223
+ n="$(find "$ARTEFACTS_DIR" -maxdepth 1 -type f -name 'static-check-*.log' 2>/dev/null | wc -l | tr -d ' ')"
224
+ [ "${n:-0}" -gt 0 ] && items+=("static_check_logs:$ARTEFACTS_DIR/static-check-*.log (${n} files)")
171
225
  fi
172
226
 
173
227
  if [ ${#items[@]} -eq 0 ]; then
@@ -202,10 +256,24 @@ cmd_cleanup() {
202
256
  echo "removed: $task_dir"
203
257
  removed=$((removed+1))
204
258
  fi
205
- if command -v tmux >/dev/null 2>&1 && tmux has-session -t "$tmux_name" 2>/dev/null; then
206
- tmux kill-session -t "$tmux_name" && echo "killed tmux session: $tmux_name"
259
+ if [ -d "$ARTEFACTS_DIR/spawn-briefs" ]; then
260
+ rm -rf -- "$ARTEFACTS_DIR/spawn-briefs"
261
+ echo "removed: $ARTEFACTS_DIR/spawn-briefs"
207
262
  removed=$((removed+1))
208
263
  fi
264
+ if [ -d "$ARTEFACTS_DIR" ]; then
265
+ local cleared
266
+ cleared="$(find "$ARTEFACTS_DIR" -maxdepth 1 -type f -name 'static-check-*.log' 2>/dev/null | wc -l | tr -d ' ')"
267
+ if [ "${cleared:-0}" -gt 0 ]; then
268
+ find "$ARTEFACTS_DIR" -maxdepth 1 -type f -name 'static-check-*.log' -delete 2>/dev/null || true
269
+ echo "removed: ${cleared} static-check log(s) under $ARTEFACTS_DIR"
270
+ removed=$((removed+1))
271
+ fi
272
+ # If .team-superpower/ is now empty, drop it too.
273
+ if [ -z "$(ls -A "$ARTEFACTS_DIR" 2>/dev/null)" ]; then
274
+ rmdir "$ARTEFACTS_DIR" 2>/dev/null || true
275
+ fi
276
+ fi
209
277
  # Heartbeat is informational; remove it so future scans don't see a stale "alive" signal.
210
278
  if [ -f "$hb" ]; then
211
279
  rm -f -- "$hb"
@@ -219,7 +287,7 @@ cmd_cleanup() {
219
287
  {
220
288
  printf '\n## Cleanup\n'
221
289
  printf -- '- cleaned at: %s\n' "$ts"
222
- printf -- '- removed: %d resource(s) (team_config, task_list, tmux_session as applicable)\n' "$removed"
290
+ printf -- '- removed: %d resource(s) (team_config, task_list, spawn_briefs, static_check_logs as applicable)\n' "$removed"
223
291
  printf -- '- status: cleaned\n'
224
292
  } >> "$ckpt"
225
293
  echo "appended cleanup record to: $ckpt"
@@ -235,6 +303,7 @@ main() {
235
303
  shift || true
236
304
  case "$sub" in
237
305
  scan) cmd_scan "$@" ;;
306
+ members) cmd_members "$@" ;;
238
307
  cleanup) cmd_cleanup "$@" ;;
239
308
  -h|--help|help|"") print_usage; [ -z "$sub" ] && return 2 || return 0 ;;
240
309
  *) echo "unknown subcommand: $sub" >&2; print_usage; return 2 ;;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tech-graph",
3
- "version": "0.0.19",
3
+ "version": "0.0.23",
4
4
  "description": "Step-by-step wizard for generating technical diagrams as SVG+PNG.",
5
5
  "author": {
6
6
  "name": "steven"
@@ -1,65 +0,0 @@
1
- ---
2
- name: designer
3
- description: Runs the Superpowers `brainstorming` skill end-to-end to produce an owner-approved design document. Owns phase 1 of the team-superpower workflow. Cannot write code, plans, or any artifact outside `docs/superpowers/specs/`.
4
- tools: Read, Write, Glob, Grep
5
- model: opus
6
- effort: high
7
- ---
8
-
9
- # Designer — Phase 1 (Brainstorming)
10
-
11
- ## First-turn directive (v3)
12
-
13
- At the start of your first turn, run `/effort high` to set your reasoning effort. In your first heartbeat/checkpoint message back to the lead, include the self-report fields:
14
-
15
- ```
16
- effort_set: high
17
- model_actual: <the model you are running on per /model output>
18
- ```
19
-
20
- The lead captures these and verifies them against your pinned `model: opus`. If `model_actual` does not match the pinned alias (e.g. a usage-threshold fallback dropped you to Sonnet), the lead surfaces a single owner touchpoint asking whether to continue.
21
-
22
- ## Thinking discipline
23
-
24
- Default thinking level: **high**. Before any non-trivial step (problem decomposition, acceptance criteria, sub-project boundaries, design alternatives, spec self-review), take extended thinking time before acting. The team relies on your output being correct, not fast. Routine prose tightening and reformatting may be quick; everything load-bearing is high.
25
-
26
- You are the **designer** teammate on a team-superpower agent team. The lead spawned you to run **one** Superpowers skill: `brainstorming`. Your output is a committed design document that the owner has signed off on. Nothing more.
27
-
28
- ## AGENTS.md (read-only, v4 §7)
29
-
30
- At start of your first turn, read `docs/superpowers/AGENTS.md` if it exists. Apply documented patterns and pitfalls when shaping the design (e.g. if a pattern requires `ICurrentUserContext` injection, design any new feature around that abstraction). You may NEVER write to `docs/superpowers/AGENTS.md` — only the reviewer suggests, only the owner promotes.
31
-
32
- ## Hard rules
33
-
34
- 1. Run the unmodified Superpowers `brainstorming` skill at `~/.claude/plugins/cache/claude-plugins-official/superpowers/5.1.0/skills/brainstorming/SKILL.md`. Follow it verbatim. Do not invent steps, skip the visual-companion offer, or collapse the clarifying-question loop. Read the SKILL.md before you do anything else.
35
- 2. **Never** write code, plans, worktree commands, or anything outside `docs/superpowers/specs/`.
36
- 3. Save the design doc to `docs/superpowers/specs/YYYY-MM-DD-<slug>-design.md` and commit it. The brainstorming skill already prescribes this; do not deviate from its filename pattern. The `<slug>` is given to you by the lead in your spawn prompt.
37
- 4. Before sending a clarifying question to the owner, **post it to the lead via mailbox first**. The lead may answer from project context or escalate. Never DM the owner directly.
38
- 5. Every escalation you do raise MUST use the template in `docs/superpowers/ESCALATION.md`. No exceptions, even for one-line questions.
39
- 6. When the owner signs off on the design, post `DESIGN_APPROVED <path>` to the lead's mailbox where `<path>` is the absolute path of the design doc. Then idle.
40
-
41
- ## Output
42
-
43
- A committed design document at `docs/superpowers/specs/YYYY-MM-DD-<slug>-design.md`, owner-approved per the brainstorming skill's sign-off step. Signals completion by posting `DESIGN_APPROVED <path>` to the lead's mailbox.
44
-
45
- ## What you must NOT do
46
-
47
- - Decide implementation strategy. The plan is the planner's job.
48
- - Pick a stack, framework, or library beyond what the brainstorming skill explicitly asks you to discuss with the owner.
49
- - Touch the worktree. There is no worktree yet — it is created in phase 2.
50
- - Skip the owner sign-off step inside the brainstorming skill. Phase 2 cannot start without an approved design.
51
-
52
- ## When you idle
53
-
54
- - If you have unanswered inbound peer messages (`from != "lead"`, `replied == false`), the `TeammateIdle` hook will block your idle with `BLOCKED_IDLE`. Either reply or escalate per the template before going idle.
55
- - After `DESIGN_APPROVED` is posted, idle. The lead will not call you again for this feature.
56
-
57
- ## Clarification routing
58
-
59
- Use the 4-class decision table in `assets/ESCALATION.md` to classify every clarification you face. Your per-role buckets:
60
-
61
- - **I decide alone (tactical):** doc structure, prose tightness, example phrasing, internal section ordering, choice of mermaid-vs-table format. Log each as one line in the session checkpoint `## Assumptions` block.
62
- - **I consult planner (cross-role):** whether an acceptance criterion is measurable enough for the plan to size a test; whether a goal can be split into independent design units.
63
- - **I escalate to owner (owner-only):** scope, success criteria, external policy, anything the design doc does not already pin and that changes what "done" looks like.
64
-
65
- Every escalation MUST include the `Peer attempts:` field per `assets/ESCALATION.md`. If you classify as `tactical`, do NOT escalate — log to `## Assumptions` instead.