@drunkcoding/agents-and-skills 0.0.25 → 0.0.26

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 (41) hide show
  1. package/.claude-plugin/marketplace.json +14 -33
  2. package/README.md +1 -0
  3. package/package.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-share/.claude-plugin/plugin.json +17 -0
  7. package/plugins/team-share/README.md +30 -0
  8. package/plugins/team-share/agents/team-share.md +140 -0
  9. package/plugins/team-share/commands/team-share.md +4 -0
  10. package/plugins/tech-graph/.claude-plugin/plugin.json +1 -1
  11. package/plugins/auto-power/.claude-plugin/plugin.json +0 -17
  12. package/plugins/auto-power/README.md +0 -80
  13. package/plugins/auto-power/assets/CHECKPOINT_SCHEMA.md +0 -69
  14. package/plugins/auto-power/assets/ESCALATION_TEMPLATE.md +0 -67
  15. package/plugins/auto-power/commands/auto-power-resume.md +0 -32
  16. package/plugins/auto-power/commands/auto-power.md +0 -46
  17. package/plugins/auto-power/skills/auto-power-runtime/SKILL.md +0 -220
  18. package/plugins/team-superpower/.claude-plugin/plugin.json +0 -21
  19. package/plugins/team-superpower/README.md +0 -294
  20. package/plugins/team-superpower/agents/backend-developer.md +0 -221
  21. package/plugins/team-superpower/agents/feature-planner.md +0 -66
  22. package/plugins/team-superpower/agents/frontend-developer.md +0 -242
  23. package/plugins/team-superpower/agents/qc-engineer.md +0 -84
  24. package/plugins/team-superpower/agents/security-engineer.md +0 -175
  25. package/plugins/team-superpower/agents/solution-architect.md +0 -80
  26. package/plugins/team-superpower/agents/team-leader.md +0 -100
  27. package/plugins/team-superpower/assets/AGENTS.md.template +0 -23
  28. package/plugins/team-superpower/assets/CLAUDE.md.template +0 -117
  29. package/plugins/team-superpower/assets/ESCALATION.md +0 -142
  30. package/plugins/team-superpower/assets/SESSION_README.md +0 -337
  31. package/plugins/team-superpower/commands/team-cleanup.md +0 -70
  32. package/plugins/team-superpower/commands/team-feature.md +0 -319
  33. package/plugins/team-superpower/hooks/hooks.json +0 -25
  34. package/plugins/team-superpower/hooks/task-completed.sh +0 -254
  35. package/plugins/team-superpower/hooks/task-created.sh +0 -174
  36. package/plugins/team-superpower/hooks/teammate-idle.sh +0 -142
  37. package/plugins/team-superpower/scripts/assess-complexity.sh +0 -194
  38. package/plugins/team-superpower/scripts/detect-stack.sh +0 -473
  39. package/plugins/team-superpower/scripts/parse-claudemd.sh +0 -194
  40. package/plugins/team-superpower/scripts/team-state.sh +0 -313
  41. package/plugins/team-superpower/scripts/wave-collision-check.sh +0 -60
@@ -1,319 +0,0 @@
1
- ---
2
- description: Launch a Superpowers-compliant agent team (v6 single-session lifecycle) to deliver a feature end-to-end with at most 3 owner touchpoints, with automatic cleanup after the finish phase.
3
- argument-hint: <one-line feature idea>
4
- ---
5
-
6
- You are the **main session** of the team-superpower v6 single-session lifecycle. The main session owns the full lifecycle directly — no separate lead/coordinator agent is spawned. You run mode pick, TeamCreate, phase A → H, SPAWN_REQUEST handling, RESTART_REQUEST handling, qc-engineer spawn, cleanup, push. You are the **sole spawner** for the team — no teammate can spawn (platform rule: "no nested teams").
7
-
8
- > **Main-session model:** run this command in an **Opus** session. The main session carries cross-phase reasoning (mode pick, escalation triage, restart approval, finish-branch recovery). Teammates are pinned via their agent frontmatter — they spawn on their pinned model regardless of the main session's model. If the main session is started on Sonnet, halt and ask the owner to relaunch on Opus.
9
- >
10
- > **Thinking discipline:** adaptive. Use extended (high-effort) thinking for every gate decision, SPAWN_REQUEST classification, RESTART_REQUEST approval, escalation triage, FINISH_BLOCKED recovery, worktree cleanup branching. Routine heartbeats, SendMessage forwarding, and shared-task-list status reads may be quick.
11
-
12
- Set effort high at the start of your first turn: `/effort xhigh` and report `effort_set: xhigh`.
13
-
14
- Owner's feature request:
15
-
16
- $ARGUMENTS
17
-
18
- ## Parsing the launch flags
19
-
20
- Before doing anything else, parse override flags from the owner's request. Tokens are space-separated, may appear before the feature description, and use `=` to bind their value:
21
-
22
- - `--mode=<solo|single-agent|team>` — force execution mode; skip the heuristic ladder.
23
- - `--size=<minimal|standard|full>` — force team size (only meaningful with `--mode=team`).
24
- - `--explain` — run mode pick, print the decision, and STOP. Do not spawn anything.
25
-
26
- If any of these flags appear, strip them from `$ARGUMENTS` and treat the remainder as the actual launch message. Record the flags used in the checkpoint field `overrides_applied:`.
27
-
28
- ## Required prechecks (run these first, in order)
29
-
30
- 0. **Main-session model self-attestation.** State which model you are running on. If not Opus, halt and instruct the owner: "Main session must be on Opus. Relaunch with `claude --model opus` and rerun `/team-feature`."
31
- 1. Confirm Superpowers plugin is installed: `claude plugin list | grep superpowers`. If missing, halt and instruct: `/plugin install superpowers@claude-plugins-official`. Capture version (`claude plugin list --json`) — write it to the checkpoint.
32
- 2. Confirm Claude Code version `2.1.32` or later: `claude --version`. If older, halt.
33
- 3. Confirm `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1` is set. If not, halt and instruct the owner to add it to `~/.claude/settings.json` under `env`.
34
- 4. Generate a kebab-case `<slug>` from the owner's request. Use it in every artifact filename. The team MUST be named exactly `superpower-<slug>` — every cleanup primitive depends on that convention.
35
- 5. Create directories if missing: `docs/superpowers/{sessions,specs,plans,handovers,reviews}`.
36
- 6. Seed `docs/superpowers/ESCALATION.md` from `${CLAUDE_PLUGIN_ROOT}/assets/ESCALATION.md` if not present. Seed `docs/superpowers/README.md` from `${CLAUDE_PLUGIN_ROOT}/assets/SESSION_README.md` if missing. Commit any seeded files.
37
-
38
- ## Auto-resume detection (run before mode pick)
39
-
40
- On invocation, before picking mode, scan for in-progress features:
41
-
42
- 1. List `~/.claude/teams/superpower-*/config.json` files. Each is a candidate slug.
43
- 2. List `docs/superpowers/handovers/*-handover.md` files with NO matching `docs/superpowers/reviews/*-qc-report.md`.
44
- 3. List plans referenced by handovers in (2) with incomplete `PHASE_COMPLETE` markers.
45
- 4. Check `git log --oneline <base>..HEAD` for partial plan-task commits not pushed.
46
- 5. Match slug against the worktree dir name or the owner's launch text.
47
-
48
- If any candidate matches, present:
49
-
50
- ```
51
- Found in-progress feature: <slug> at phase <X>
52
- Spec: <path>
53
- Arch-map: <path>
54
- Plan: <path>
55
- Handover: <path>
56
- Last commit: <sha> "<msg>"
57
- Continue this feature, or start fresh?
58
- [1] Continue (re-spawn teammates per current phase)
59
- [2] Start fresh (archive prior artefacts; new feature)
60
- ```
61
-
62
- On `[1] Continue`:
63
- - If team config (`~/.claude/teams/superpower-<slug>/`) still exists: skip TeamCreate.
64
- - If gone: `TeamCreate(superpower-<slug>)`.
65
- - Re-spawn teammates per current phase (team-leader for B–F, qc-engineer for G, finish flow for H).
66
- - Spawn prompts include `"this is a resume; read existing handover/spec/plan; continue from current state; do not re-run completed work"`.
67
-
68
- On `[2] Start fresh`:
69
- - Move existing artefacts under `docs/superpowers/archive/YYYY-MM-DD-<slug>/`.
70
- - Run cleanup on stale team config.
71
- - Proceed to mode pick for new feature.
72
-
73
- If multiple candidates: list all, owner picks one or `[0] start fresh`.
74
- If none: skip to mode pick.
75
-
76
- ## Modes
77
-
78
- ### Solo mode (1 touchpoint)
79
-
80
- For bug fix, typo, rename, version bump, single-file/≤10-line diff.
81
-
82
- No TeamCreate, no teammates. The main session runs the work itself: locates affected files, drafts a combined briefing (bug statement + diff preview + verification step), presents to owner for approval (touchpoint 1), applies the change, runs `test_command`, commits, pushes, notifies. See spec §9.1.
83
-
84
- ### Single-agent mode (1 touchpoint)
85
-
86
- For small enhancement, 1–3 files, no architecture impact.
87
-
88
- The main session drafts a combined briefing (one-paragraph spec + one-task plan), presents to owner for combined approval (touchpoint 1). On approval: `TeamCreate`, spawn exactly 1 implementer (Sonnet/medium). Implementer runs TDD, static checks, commits. Main session shuts down implementer, spawns qc-engineer for a single round. On pass: push + cleanup + notify. On blocking after 3 rounds: recovery escalation. See spec §9.2.
89
-
90
- ### Team mode (2 touchpoints + finish)
91
-
92
- For feature work spanning ≥2 modules or ≥4 files, or introducing a new component.
93
-
94
- The main session runs the full single-team lifecycle (below). Owner touchpoints: spec sign-off (after architect drives discussion), plan approval (after planner produces it), finish-branch decision (in phase H).
95
-
96
- #### Heuristic ladder (when `--mode` is not set)
97
-
98
- 1. Trivial keywords (`typo`, `rename`, `bump`, `comment-out`, `revert`, `hotfix`) OR single-file scope OR ≤10-line diff → **solo**.
99
- 2. Small-scope verb (`add`, `tweak`, `expose`) + single-side signal (BE-only or FE-only) + no discovery language → **single-agent**.
100
- 3. Otherwise → **team**.
101
-
102
- Forced overrides:
103
- - `security.domain ∈ {payments, healthcare}` OR `security.pii: yes` in CLAUDE.md → forces `team` mode + `size=full` (security-engineer must run in phase A).
104
- - Regulated keywords (`PCI`, `HIPAA`, `GDPR`, `audit`, `compliance`, `legal`) in launch message → same.
105
-
106
- #### Team size (team mode only)
107
-
108
- - **minimal** — solution-architect + feature-planner + team-leader + 1 BE or 1 FE + qc-engineer (5).
109
- - **standard** (default) — adds the second implementer side when shape is full-stack (6).
110
- - **full** — adds security-engineer in phase A (7 lifetime).
111
-
112
- ## Team-mode lifecycle (spec §3.1)
113
-
114
- 1. `TeamCreate(superpower-<slug>)`.
115
- 2. Spawn phase-A members:
116
- - `solution-architect` (Opus / high)
117
- - `feature-planner` (Sonnet / high)
118
- - `security-engineer` IFF CLAUDE.md `security.domain` is one of `payments | healthcare | regulated`.
119
- 3. Hand owner control. Architect drives spec discussion. **Touchpoint 1 = spec sign-off.**
120
- 4. Architect produces arch-map. Planner produces plan. **Touchpoint 2 = plan approval.**
121
- 5. Architect writes handover artefact at `docs/superpowers/handovers/YYYY-MM-DD-<slug>-handover.md`.
122
- 6. Architect posts `HANDOVER_READY <slug>`.
123
- 7. Main session shuts down planner, security-engineer, architect (SendMessage shutdown request; teammate approves and exits).
124
- 8. Main session spawns `team-leader` (Opus / high). Spawn prompt names the handover path.
125
- 9. Main session awaits messages from team-leader:
126
- - `SPAWN_REQUEST wave=<id> roles_needed=<map> brief_path=<path> expected_tasks=<list>` → see "SPAWN_REQUEST handling" below.
127
- - `PHASE_COMPLETE <N>` → ack; await next.
128
- - `PLAN_COMPLETE` → shut down team-leader + all implementers. Transition to phase G.
129
- - `RESTART_REQUEST <reason>` → see "RESTART_REQUEST handling" below.
130
- 10. Phase G: spawn `qc-engineer` (Sonnet / high). Spawn prompt names spec + plan + handover paths.
131
- 11. Await qc-engineer:
132
- - `QC_PASS` → shut down qc-engineer. Phase H.
133
- - `QC_REWORK_NEEDED <count>` → shut down qc-engineer; re-spawn team-leader for rework dispatch; loop back to step 9. Max `limits.max_qc_rounds` (default 3) QC rounds.
134
- 12. Phase H: run finish-branch decision (below), then cleanup, then notify owner with final summary.
135
-
136
- There is **no architect standby**. Architecturally significant questions during phases B–F trigger `RESTART_REQUEST`, which presents a recovery touchpoint to the owner.
137
-
138
- ## SPAWN_REQUEST handling
139
-
140
- When team-leader posts:
141
-
142
- ```
143
- SPAWN_REQUEST wave=<plan-phase>.<wave>
144
- roles_needed: { backend-developer: N, frontend-developer: M }
145
- brief_path: .team-superpower/spawn-briefs/wave-<plan-phase>.<wave>.md
146
- expected_tasks: [<task-id-1>, <task-id-2>, ...]
147
- ```
148
-
149
- Main session:
150
- 1. Reads the brief file at `brief_path`.
151
- 2. `TaskCreate` for each task-id in `expected_tasks`. Title carries the `impl:` prefix per spec §8.2; metadata carries `wave: <plan-phase>.<wave>` (so the TaskCreated hook accepts it); body excerpted from the brief.
152
- 3. Spawns the requested `roles_needed` counts. Each implementer's spawn prompt:
153
-
154
- ```
155
- You are a <role> on team superpower-<slug>. Read the next unclaimed unblocked task in the shared task list at ~/.claude/tasks/superpower-<slug>/. Follow its brief: TDD (RED → GREEN → REFACTOR), then lint+format+typecheck (capture to .team-superpower/static-check-<task-id>.log), then commit per team format. After commit, self-claim next unclaimed unblocked task or shut down if none.
156
- ```
157
-
158
- 4. Replies to team-leader: `SPAWN_DONE wave=<plan-phase>.<wave> agent_ids=[...]`.
159
-
160
- Concurrency cap: refuse to spawn beyond `limits.max_concurrent_teammates` (default 5). Excess spawns are queued; reply notes `queued: <ids>`.
161
-
162
- ## RESTART_REQUEST handling
163
-
164
- When team-leader (or qc-engineer) posts `RESTART_REQUEST <reason>`:
165
-
166
- 1. Read `.team-superpower/restart-count` (default 0). If ≥ `limits.max_cycle_restarts` (default 2): escalate to owner with "Manual intervention required after N restarts. Feature appears not tractable in this shape."
167
- 2. Otherwise present recovery touchpoint to owner:
168
-
169
- ```
170
- Cycle restart needed: <reason>
171
- Current state:
172
- Phase: <X>
173
- Last commit: <sha> "<msg>"
174
- Restart count: <n>/<max>
175
-
176
- Approve restart from phase A?
177
- [1] Approve restart
178
- [2] Cancel feature (manual takeover)
179
- ```
180
-
181
- 3. On approval: increment `.team-superpower/restart-count`. Shut down all current teammates. Re-spawn solution-architect + feature-planner (+ security-engineer if originally spawned). Spawn prompts name the existing spec, arch-map, plan, and partial commits as input. Phase A re-runs with delta scope; the new handover supersedes the prior one.
182
-
183
- Recovery touchpoints from RESTART_REQUEST do **not** count against the 3-touchpoint budget.
184
-
185
- ## Phase H — finish-branch and CI gate
186
-
187
- After QC pass, the main session drives the finish-branch decision:
188
-
189
- 1. Push the branch.
190
- 2. If `ci.provider != none`: poll the CI provider for `ci.required_checks` up to `ci.poll_timeout_minutes` (default 20).
191
- 3. Surface one finish-branch menu (see below) to owner. This is the third (and final) touchpoint in team mode.
192
-
193
- ### CI-specific menus
194
-
195
- | CI state | Menu |
196
- |---|---|
197
- | green | `merge / pr_opened / keep / discarded` |
198
- | red | `merge / pr_opened / keep / discarded / show_ci_logs` |
199
- | timeout | `re-poll / switch_to_pr_opened / escalate` |
200
-
201
- ### 5-option merge-failure menu
202
-
203
- If merge fails (`conflict` / `non-ff` / `dirty-worktree` / `push-rejected`):
204
-
205
- ```
206
- FINISH_BLOCKED <reason>
207
- [1] retry — re-attempt merge (cap 3)
208
- [2] pr_opened — open PR instead of merging
209
- [3] kept — leave branch alone, end session
210
- [4] discarded — discard branch
211
- [5] escalate — open an escalation
212
- ```
213
-
214
- Retry cap: 3. After the 3rd failed retry the menu drops `retry` and forces a different choice.
215
-
216
- ## Automatic cleanup (runs after `FINISH_DONE`)
217
-
218
- Main session runs cleanup immediately after `FINISH_DONE`:
219
-
220
- ### Step A — Verify safety preconditions
221
-
222
- - All phases marked complete in checkpoint.
223
- - Every expected commit present on the branch.
224
- - Every teammate `idle` (no in-flight task).
225
- - `restart_count` and `qc_rounds` recorded in checkpoint.
226
-
227
- If any precondition fails, halt with the failed item and leave platform state intact for `/team-cleanup`.
228
-
229
- ### Step B — Shut down teammates gracefully
230
-
231
- For each remaining teammate: request shutdown via SendMessage; teammate approves and exits. If any teammate refuses, escalate; do not force.
232
-
233
- ### Step C — Run the canonical team cleanup
234
-
235
- Invoke the canonical Agent-Teams "clean up the team" primitive (removes `~/.claude/teams/superpower-<slug>/` and `~/.claude/tasks/superpower-<slug>/`).
236
-
237
- ### Step D — Manual sweep (only if Step C left residue)
238
-
239
- Remove residual files via `bash plugins/team-superpower/scripts/team-state.sh cleanup <slug>` — this also clears `.team-superpower/spawn-briefs/` and `.team-superpower/static-check-*.log`.
240
-
241
- ### Step D.5 — Worktree removal (on successful merge only)
242
-
243
- If `decision = merged` AND `worktree_origin != reused`: `git worktree remove <path>`. On failure surface the 4-option remove-failure menu (show files + retry / force-remove with confirmation / keep / escalate).
244
-
245
- If `worktree_origin = reused`, skip; record `worktree: removal-skipped:reused-existing-worktree`.
246
-
247
- ### Step E — Final checkpoint commit
248
-
249
- Append `## Closing` block to the checkpoint:
250
-
251
- ```
252
- finished at: <ISO datetime>
253
- decision: <merged|pr_opened|kept|discarded>
254
- cleanup: complete
255
- cycle_restart_count: <N>
256
- qc_rounds: <N>
257
- worktree: <state>
258
- worktree_path: <path> (only when state implies the dir still exists)
259
- ```
260
-
261
- Commit the checkpoint.
262
-
263
- ### Step F — If anything failed
264
-
265
- Halt with the failure mode. The owner runs `/team-cleanup <slug>` from a fresh session.
266
-
267
- ## Within-phase stall watchdog
268
-
269
- The main session detects no SendMessage activity AND no shared-task-list transitions for `limits.phase_stall_minutes` (default 30) within the current phase: pings the most-recently-active teammate. If the next 30-minute window is also silent, surfaces a §7 escalation. Heartbeat-at-phase-boundaries alone does not catch silent hangs.
270
-
271
- ## Owner touchpoints (the ONLY allowed pings to the owner)
272
-
273
- Team mode (3 max):
274
- 1. **Spec sign-off** (mid phase A).
275
- 2. **Plan approval** (end phase A).
276
- 3. **Finish-branch decision** (phase H).
277
-
278
- Single-agent mode (1):
279
- 1. **Combined spec + plan approval**.
280
-
281
- Solo mode (1):
282
- 1. **Diff preview + verification step**.
283
-
284
- Recovery touchpoints (these do **not** count against the budget):
285
- - Model fallback (teammate running on different model than pinned).
286
- - `RESTART_REQUEST` approval.
287
- - CI timeout decision.
288
- - Manual intervention after restart cap.
289
-
290
- Anything else that reaches the owner MUST use the §7 escalation template in `assets/ESCALATION.md`.
291
-
292
- ## Checkpointing
293
-
294
- `docs/superpowers/sessions/YYYY-MM-DD-<slug>.md` is updated by the main session at every phase boundary. Frontmatter carries `slug`, `mode`, `size`, `mode_reasoning`, `overrides_applied`, `superpowers_version`, `worktree_origin`, `cycle_restart_count`.
295
-
296
- Body sections:
297
-
298
- ```
299
- ## Phases — checklist with file paths to artefacts
300
- ## Teammates — role / agent id / current task or idle
301
- ## Open escalations
302
- ## Assumptions — one line per non-owner decision
303
- ## Cycle history — one row per RESTART_REQUEST
304
- ## Closing — final block written by Step E
305
- ```
306
-
307
- The main session commits this file after every phase transition. If the main session crashes, the feature lives in this file.
308
-
309
- ## Hard rules
310
-
311
- 1. **Main session is the sole spawner.** team-leader, qc-engineer, and implementers never call `Agent` themselves — they post `SPAWN_REQUEST` and let the main session handle it. This honours the Claude Code Agent Teams "no nested teams" constraint.
312
- 2. **Main session does not run phase work in team mode.** All feature implementation is delegated to teammates. In solo mode the main session does the work itself; in single-agent mode the main session spawns one implementer.
313
- 3. **One team per feature.** A single `TeamCreate superpower-<slug>` runs the entire lifecycle. Membership rolls forward by spawn + shutdown across phases A–H.
314
- 4. **No per-task QA loop.** Implementers self-enforce TDD + static checks; the `TaskCompleted` hook gates on `.team-superpower/static-check-<task-id>.log`.
315
- 5. **Owner-touchpoint budget is sacred.** 3 in team mode, 1 in single-agent / solo. Recovery touchpoints are separate.
316
- 6. **Restart cap is sacred.** 2 `RESTART_REQUEST` cycles per feature; a 3rd cycle escalates as "feature not tractable in this shape".
317
- 7. **QC rounds cap is sacred.** 3 end-of-plan QC rounds; a 4th triggers owner escalation.
318
- 8. **AGENTS.md is a read-only contract for agents.** The `TaskCompleted` hook rejects any commit that modifies it from inside a teammate; only the main session may write it.
319
- 9. **No `--dangerously-skip-permissions`.** Hooks exist because Superpowers gates exist. Use the §7 escalation template instead.
@@ -1,25 +0,0 @@
1
- {
2
- "hooks": {
3
- "TeammateIdle": [
4
- {
5
- "hooks": [
6
- { "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/teammate-idle.sh" }
7
- ]
8
- }
9
- ],
10
- "TaskCreated": [
11
- {
12
- "hooks": [
13
- { "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/task-created.sh" }
14
- ]
15
- }
16
- ],
17
- "TaskCompleted": [
18
- {
19
- "hooks": [
20
- { "type": "command", "command": "${CLAUDE_PLUGIN_ROOT}/hooks/task-completed.sh" }
21
- ]
22
- }
23
- ]
24
- }
25
- }
@@ -1,254 +0,0 @@
1
- #!/usr/bin/env bash
2
- # TaskCompleted hook — v5 gate for implementation completions.
3
- #
4
- # Accepts a JSON payload on stdin with at minimum:
5
- # - task.title: string
6
- # - task.metadata.wave: string (e.g. "1.1", "1.rework", "qc-rework")
7
- # - task.metadata.iteration_count: integer (optional)
8
- # - task.metadata.reflection: string (optional, required when iteration_count > cap)
9
- # - task.metadata.retrieval_requests: integer (optional)
10
- # - task.metadata.commits: array of git SHAs (optional)
11
- # - task.metadata.contract_files: array of paths (optional, for contract-publish)
12
- #
13
- # v5 checks (delta from v4):
14
- # - REMOVED: per-task QA verification (qa_verified_at, QA-verified commit line, qa_rounds cap, trivial=true claims)
15
- # - REMOVED: 6-field escalation template validation (Phase/Context/Options/Recommendation/Need from you/Peer attempts)
16
- # - REMOVED: v4 wave format (single integer); v5 wave is dotted (e.g. "1.1") or rework label
17
- # - ADDED: MISSING_STATIC_CHECKS — every impl:* task must have a .team-superpower/static-check-<task-id>.log
18
- # containing exit=0 for all sections (lint, format, typecheck).
19
- # - ADDED: MISSING_REWORK_REFERENCE — every impl:rework-* task must have a `Reworks: <orig-id>` line
20
- # in at least one commit body.
21
- #
22
- # v5 preserved checks:
23
- # - migration serialization (impl:*-migration-* anti-race)
24
- # - contract-publish must touch a contracts file
25
- # - AGENTS.md protection (no agent commit may touch docs/superpowers/AGENTS.md)
26
- # - retrieval budget cap + premature Flagged-assumptions guard
27
- # - MAX_ITERATIONS guardrail
28
-
29
- set -euo pipefail
30
-
31
- LOG_DIR="${CLAUDE_PROJECT_DIR:-$PWD}/.claude/hooks"
32
- LOG_FILE="$LOG_DIR/log.jsonl"
33
- mkdir -p "$LOG_DIR"
34
-
35
- ts="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
36
-
37
- payload="$(cat || true)"
38
-
39
- if [ -z "$payload" ]; then
40
- printf '{"ts":"%s","hook":"task-completed","skipped":"empty payload"}\n' "$ts" >> "$LOG_FILE"
41
- exit 0
42
- fi
43
-
44
- if ! command -v jq >/dev/null 2>&1; then
45
- printf '{"ts":"%s","hook":"task-completed","skipped":"jq not installed"}\n' "$ts" >> "$LOG_FILE"
46
- exit 0
47
- fi
48
-
49
- title="$(printf '%s' "$payload" | jq -r '.task.title // .title // ""' 2>/dev/null || echo "")"
50
-
51
- printf '{"ts":"%s","hook":"task-completed","title":%s}\n' \
52
- "$ts" \
53
- "$(printf '%s' "$title" | jq -Rs .)" \
54
- >> "$LOG_FILE"
55
-
56
- # Resolve parse-claudemd.sh helper for limits.* lookups.
57
- parse_helper="${CLAUDE_PLUGIN_ROOT:-}/scripts/parse-claudemd.sh"
58
- if [ -z "${CLAUDE_PLUGIN_ROOT:-}" ]; then
59
- hook_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
60
- parse_helper="$hook_dir/../scripts/parse-claudemd.sh"
61
- fi
62
-
63
- # v5: wave metadata. impl:* tasks must carry a `wave:` string. Accepted shapes:
64
- # - "<plan-phase>.<wave>" e.g. "1.1", "2.3"
65
- # - "<plan-phase>.rework" e.g. "1.rework"
66
- # - "qc-rework"
67
- case "$title" in
68
- impl:*)
69
- wave="$(printf '%s' "$payload" | jq -r '.task.metadata.wave // .metadata.wave // ""' 2>/dev/null || echo "")"
70
- if [ -z "$wave" ] || ! printf '%s' "$wave" | grep -qE '^([0-9]+\.[0-9]+|[0-9]+\.rework|qc-rework)$'; then
71
- printf '{"ts":"%s","hook":"task-completed","warn":"MISSING_WAVE_METADATA","title":%s,"wave":%s}\n' \
72
- "$ts" \
73
- "$(printf '%s' "$title" | jq -Rs .)" \
74
- "$(printf '%s' "$wave" | jq -Rs .)" \
75
- >> "$LOG_FILE"
76
- fi
77
- ;;
78
- esac
79
-
80
- # v5 check 10: MISSING_STATIC_CHECKS. Every impl:* task must have a
81
- # .team-superpower/static-check-<task-id>.log with exit=0 across lint/format/typecheck.
82
- case "$title" in
83
- impl:*)
84
- project_dir="${CLAUDE_PROJECT_DIR:-$PWD}"
85
- static_log="$project_dir/.team-superpower/static-check-${title}.log"
86
- if [ ! -f "$static_log" ]; then
87
- printf '{"ts":"%s","hook":"task-completed","warn":"MISSING_STATIC_CHECKS","title":%s,"reason":"log file not found","path":%s}\n' \
88
- "$ts" \
89
- "$(printf '%s' "$title" | jq -Rs .)" \
90
- "$(printf '%s' "$static_log" | jq -Rs .)" \
91
- >> "$LOG_FILE"
92
- else
93
- # Any exit= line with a non-zero value fails the check.
94
- if grep -E '^exit=' "$static_log" | grep -qvE '^exit=0$'; then
95
- bad="$(grep -E '^exit=' "$static_log" | grep -vE '^exit=0$' | head -n1 || true)"
96
- printf '{"ts":"%s","hook":"task-completed","warn":"MISSING_STATIC_CHECKS","title":%s,"reason":"non-zero exit","line":%s}\n' \
97
- "$ts" \
98
- "$(printf '%s' "$title" | jq -Rs .)" \
99
- "$(printf '%s' "$bad" | jq -Rs .)" \
100
- >> "$LOG_FILE"
101
- fi
102
- fi
103
- ;;
104
- esac
105
-
106
- # v5 check 11: MISSING_REWORK_REFERENCE. impl:rework-* tasks must carry a
107
- # `Reworks: <orig-id-or-qc-issue-id>` line in at least one commit body.
108
- case "$title" in
109
- impl:rework-*)
110
- if command -v git >/dev/null 2>&1; then
111
- rw_commits="$(printf '%s' "$payload" | jq -r '(.task.metadata.commits // .metadata.commits // [])[]?' 2>/dev/null || true)"
112
- if [ -n "$rw_commits" ]; then
113
- rw_found=0
114
- while IFS= read -r sha; do
115
- [ -z "$sha" ] && continue
116
- body="$(git show --no-color --no-patch --format=%B "$sha" 2>/dev/null || true)"
117
- if printf '%s\n' "$body" | grep -qE '^Reworks:[[:space:]]*[^[:space:]]+'; then
118
- rw_found=1; break
119
- fi
120
- done <<< "$rw_commits"
121
- if [ "$rw_found" -ne 1 ]; then
122
- printf '{"ts":"%s","hook":"task-completed","warn":"MISSING_REWORK_REFERENCE","title":%s,"reason":"no Reworks: line in commit body"}\n' \
123
- "$ts" "$(printf '%s' "$title" | jq -Rs .)" >> "$LOG_FILE"
124
- fi
125
- else
126
- printf '{"ts":"%s","hook":"task-completed","warn":"MISSING_REWORK_REFERENCE","title":%s,"reason":"no commits recorded"}\n' \
127
- "$ts" "$(printf '%s' "$title" | jq -Rs .)" >> "$LOG_FILE"
128
- fi
129
- fi
130
- ;;
131
- esac
132
-
133
- # MAX_ITERATIONS guardrail (preserved from v3/v4).
134
- case "$title" in
135
- impl:*)
136
- iteration_count="$(printf '%s' "$payload" | jq -r '.task.metadata.iteration_count // .metadata.iteration_count // 0' 2>/dev/null || echo 0)"
137
- reflection="$(printf '%s' "$payload" | jq -r '.task.metadata.reflection // .metadata.reflection // ""' 2>/dev/null || echo "")"
138
-
139
- cap=8
140
- if [ -f "$parse_helper" ] && [ -f "${CLAUDE_PROJECT_DIR:-$PWD}/CLAUDE.md" ]; then
141
- configured="$(bash "$parse_helper" get limits.max_iterations_per_task "${CLAUDE_PROJECT_DIR:-$PWD}/CLAUDE.md" 2>/dev/null || true)"
142
- if [ -n "$configured" ] && printf '%s' "$configured" | grep -qE '^[0-9]+$'; then
143
- cap="$configured"
144
- fi
145
- fi
146
-
147
- if [ "${iteration_count:-0}" -gt "$cap" ] && [ -z "$reflection" ]; then
148
- printf '{"ts":"%s","hook":"task-completed","warn":"ITERATION_CAP_EXCEEDED","title":%s,"iteration_count":%d,"cap":%d}\n' \
149
- "$ts" \
150
- "$(printf '%s' "$title" | jq -Rs .)" \
151
- "$iteration_count" \
152
- "$cap" \
153
- >> "$LOG_FILE"
154
- fi
155
- ;;
156
- esac
157
-
158
- # Retrieval budget (preserved from v4).
159
- case "$title" in
160
- impl:*)
161
- retrieval_requests="$(printf '%s' "$payload" | jq -r '.task.metadata.retrieval_requests // .metadata.retrieval_requests // 0' 2>/dev/null || echo 0)"
162
- retrieval_cap=2
163
- if [ -f "$parse_helper" ] && [ -f "${CLAUDE_PROJECT_DIR:-$PWD}/CLAUDE.md" ]; then
164
- configured_r="$(bash "$parse_helper" get limits.retrieval_budget_per_task "${CLAUDE_PROJECT_DIR:-$PWD}/CLAUDE.md" 2>/dev/null || true)"
165
- if [ -n "$configured_r" ] && printf '%s' "$configured_r" | grep -qE '^[0-9]+$'; then
166
- retrieval_cap="$configured_r"
167
- fi
168
- fi
169
-
170
- if [ "${retrieval_requests:-0}" -gt "$retrieval_cap" ]; then
171
- printf '{"ts":"%s","hook":"task-completed","warn":"RETRIEVAL_BUDGET_EXCEEDED","title":%s,"requests":%d,"cap":%d}\n' \
172
- "$ts" "$(printf '%s' "$title" | jq -Rs .)" "$retrieval_requests" "$retrieval_cap" >> "$LOG_FILE"
173
- fi
174
-
175
- if command -v git >/dev/null 2>&1; then
176
- r_commits="$(printf '%s' "$payload" | jq -r '(.task.metadata.commits // .metadata.commits // [])[]?' 2>/dev/null || true)"
177
- if [ -n "$r_commits" ]; then
178
- flagged=0
179
- while IFS= read -r sha; do
180
- [ -z "$sha" ] && continue
181
- body="$(git show --no-color --no-patch --format=%B "$sha" 2>/dev/null || true)"
182
- if printf '%s\n' "$body" | grep -qE '^Flagged-assumptions:'; then
183
- flagged=1; break
184
- fi
185
- done <<< "$r_commits"
186
- if [ "$flagged" -eq 1 ] && [ "${retrieval_requests:-0}" -lt "$retrieval_cap" ]; then
187
- printf '{"ts":"%s","hook":"task-completed","warn":"PREMATURE_ASSUMPTION_FLAG","title":%s,"requests":%d,"cap":%d}\n' \
188
- "$ts" "$(printf '%s' "$title" | jq -Rs .)" "$retrieval_requests" "$retrieval_cap" >> "$LOG_FILE"
189
- fi
190
- fi
191
- fi
192
- ;;
193
- esac
194
-
195
- # AGENTS.md protection (preserved from v4).
196
- if command -v git >/dev/null 2>&1; then
197
- agm_commits="$(printf '%s' "$payload" | jq -r '(.task.metadata.commits // .metadata.commits // [])[]?' 2>/dev/null || true)"
198
- if [ -n "$agm_commits" ]; then
199
- while IFS= read -r sha; do
200
- [ -z "$sha" ] && continue
201
- files="$(git show --no-color --name-only --pretty=format: "$sha" 2>/dev/null || true)"
202
- if printf '%s\n' "$files" | grep -qE '^docs/superpowers/AGENTS\.md$'; then
203
- printf '{"ts":"%s","hook":"task-completed","warn":"AGENT_WROTE_AGENTS_MD","title":%s,"sha":%s}\n' \
204
- "$ts" "$(printf '%s' "$title" | jq -Rs .)" "$(printf '%s' "$sha" | jq -Rs .)" >> "$LOG_FILE"
205
- fi
206
- done <<< "$agm_commits"
207
- fi
208
- fi
209
-
210
- # Migration serialization (preserved). v5 widens the prefix match: any task
211
- # whose title contains the qualifier `-migration-` (e.g. impl:be-migration-*,
212
- # impl:rework-be-migration-*) is migration-class.
213
- case "$title" in
214
- *-migration-*)
215
- other_in_progress="$(printf '%s' "$payload" | jq -r --arg me "$title" '
216
- [ .tasks[]?
217
- | select((.title // "") != $me)
218
- | select(((.title // "") | contains("-migration-")))
219
- | select((.status // "") == "in_progress")
220
- ] | length' 2>/dev/null || echo 0)"
221
- if [ "${other_in_progress:-0}" -gt 0 ]; then
222
- printf '{"ts":"%s","hook":"task-completed","warn":"MIGRATION_RACE","title":%s}\n' "$ts" "$(printf '%s' "$title" | jq -Rs .)" >> "$LOG_FILE"
223
- fi
224
- ;;
225
- esac
226
-
227
- # Contract-publish must touch a contracts file (preserved). v5 widens to any
228
- # task whose title contains the qualifier `-contract-publish-`.
229
- case "$title" in
230
- *-contract-publish-*)
231
- if command -v git >/dev/null 2>&1; then
232
- commits="$(printf '%s' "$payload" | jq -r '(.task.metadata.commits // .metadata.commits // [])[]?' 2>/dev/null || true)"
233
- patterns="$(printf '%s' "$payload" | jq -r '(.task.metadata.contract_files // .metadata.contract_files // ["contracts/"])[]?' 2>/dev/null || echo "contracts/")"
234
- if [ -n "$commits" ]; then
235
- touched=0
236
- while IFS= read -r sha; do
237
- [ -z "$sha" ] && continue
238
- files="$(git show --no-color --name-only --pretty=format: "$sha" 2>/dev/null || true)"
239
- while IFS= read -r pat; do
240
- [ -z "$pat" ] && continue
241
- if printf '%s\n' "$files" | grep -qE "(^|/)${pat//./\\.}"; then
242
- touched=1; break 2
243
- fi
244
- done <<< "$patterns"
245
- done <<< "$commits"
246
- if [ "$touched" -ne 1 ]; then
247
- printf '{"ts":"%s","hook":"task-completed","warn":"EMPTY_CONTRACT_PUBLISH","title":%s}\n' "$ts" "$(printf '%s' "$title" | jq -Rs .)" >> "$LOG_FILE"
248
- fi
249
- fi
250
- fi
251
- ;;
252
- esac
253
-
254
- exit 0