cc-workspace 4.7.1 → 5.2.2
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/CHANGELOG.md +307 -0
- package/README.md +123 -41
- package/bin/cli.js +333 -134
- package/global-skills/agents/e2e-validator.md +152 -33
- package/global-skills/agents/implementer.md +77 -71
- package/global-skills/agents/reviewer.md +192 -0
- package/global-skills/agents/security-auditor.md +345 -0
- package/global-skills/agents/team-lead.md +93 -101
- package/global-skills/agents/workspace-init.md +16 -5
- package/global-skills/bootstrap-repo/SKILL.md +1 -0
- package/global-skills/cleanup/SKILL.md +35 -25
- package/global-skills/cross-service-check/SKILL.md +1 -0
- package/global-skills/cycle-retrospective/SKILL.md +6 -4
- package/global-skills/dispatch-feature/SKILL.md +225 -173
- package/global-skills/dispatch-feature/references/anti-patterns.md +52 -35
- package/global-skills/dispatch-feature/references/spawn-templates.md +140 -97
- package/global-skills/doctor/SKILL.md +124 -25
- package/global-skills/e2e-validator/references/container-strategies.md +55 -23
- package/global-skills/hooks/orphan-cleanup.sh +60 -0
- package/global-skills/hooks/permission-auto-approve.sh +61 -4
- package/global-skills/hooks/session-start-context.sh +10 -47
- package/global-skills/hooks/test_hooks.sh +242 -0
- package/global-skills/hooks/user-prompt-guard.sh +6 -6
- package/global-skills/hooks/validate-spawn-prompt.sh +40 -30
- package/global-skills/incident-debug/SKILL.md +1 -0
- package/global-skills/merge-prep/SKILL.md +1 -0
- package/global-skills/metrics/SKILL.md +139 -0
- package/global-skills/plan-review/SKILL.md +2 -1
- package/global-skills/qa-ruthless/SKILL.md +2 -0
- package/global-skills/refresh-profiles/SKILL.md +1 -0
- package/global-skills/rules/context-hygiene.md +4 -19
- package/global-skills/rules/model-routing.md +31 -18
- package/global-skills/session/SKILL.md +41 -20
- package/global-skills/templates/workspace.template.md +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# test_hooks.sh — Unit tests for cc-workspace hooks
|
|
3
|
+
# Run from the hooks directory: cd global-skills/hooks && bash test_hooks.sh
|
|
4
|
+
# Requirements: jq, bash 4+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
HOOKS_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
8
|
+
PASS=0
|
|
9
|
+
FAIL=0
|
|
10
|
+
TOTAL=0
|
|
11
|
+
|
|
12
|
+
# ─── Helpers ────────────────────────────────────────────────
|
|
13
|
+
RED='\033[0;31m'
|
|
14
|
+
GREEN='\033[0;32m'
|
|
15
|
+
DIM='\033[2m'
|
|
16
|
+
RESET='\033[0m'
|
|
17
|
+
|
|
18
|
+
assert_contains() {
|
|
19
|
+
local label="$1" output="$2" expected="$3"
|
|
20
|
+
TOTAL=$((TOTAL + 1))
|
|
21
|
+
if echo "$output" | grep -qF "$expected"; then
|
|
22
|
+
PASS=$((PASS + 1))
|
|
23
|
+
printf " ${GREEN}✓${RESET} %s\n" "$label"
|
|
24
|
+
else
|
|
25
|
+
FAIL=$((FAIL + 1))
|
|
26
|
+
printf " ${RED}✗${RESET} %s\n" "$label"
|
|
27
|
+
printf " ${DIM}expected to contain: %s${RESET}\n" "$expected"
|
|
28
|
+
printf " ${DIM}got: %s${RESET}\n" "$output"
|
|
29
|
+
fi
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
assert_empty() {
|
|
33
|
+
local label="$1" output="$2"
|
|
34
|
+
TOTAL=$((TOTAL + 1))
|
|
35
|
+
if [ -z "$output" ]; then
|
|
36
|
+
PASS=$((PASS + 1))
|
|
37
|
+
printf " ${GREEN}✓${RESET} %s\n" "$label"
|
|
38
|
+
else
|
|
39
|
+
FAIL=$((FAIL + 1))
|
|
40
|
+
printf " ${RED}✗${RESET} %s\n" "$label"
|
|
41
|
+
printf " ${DIM}expected empty, got: %s${RESET}\n" "$output"
|
|
42
|
+
fi
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
assert_exit_code() {
|
|
46
|
+
local label="$1" actual="$2" expected="$3"
|
|
47
|
+
TOTAL=$((TOTAL + 1))
|
|
48
|
+
if [ "$actual" -eq "$expected" ]; then
|
|
49
|
+
PASS=$((PASS + 1))
|
|
50
|
+
printf " ${GREEN}✓${RESET} %s\n" "$label"
|
|
51
|
+
else
|
|
52
|
+
FAIL=$((FAIL + 1))
|
|
53
|
+
printf " ${RED}✗${RESET} %s\n" "$label"
|
|
54
|
+
printf " ${DIM}expected exit %s, got %s${RESET}\n" "$expected" "$actual"
|
|
55
|
+
fi
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
run_hook() {
|
|
59
|
+
local hook="$1" input="$2"
|
|
60
|
+
echo "$input" | bash "$HOOKS_DIR/$hook" 2>/dev/null || true
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
run_hook_exit() {
|
|
64
|
+
local hook="$1" input="$2"
|
|
65
|
+
echo "$input" | bash "$HOOKS_DIR/$hook" 2>/dev/null
|
|
66
|
+
echo $?
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# ─── permission-auto-approve.sh ─────────────────────────────
|
|
70
|
+
echo ""
|
|
71
|
+
echo "▸ permission-auto-approve.sh"
|
|
72
|
+
|
|
73
|
+
# Should auto-approve Read tool
|
|
74
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Read"}')
|
|
75
|
+
assert_contains "approves Read tool" "$OUT" '"behavior":"allow"'
|
|
76
|
+
|
|
77
|
+
# Should auto-approve Glob tool
|
|
78
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Glob"}')
|
|
79
|
+
assert_contains "approves Glob tool" "$OUT" '"behavior":"allow"'
|
|
80
|
+
|
|
81
|
+
# Should auto-approve Grep tool
|
|
82
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Grep"}')
|
|
83
|
+
assert_contains "approves Grep tool" "$OUT" '"behavior":"allow"'
|
|
84
|
+
|
|
85
|
+
# Should NOT auto-approve Write tool
|
|
86
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Write"}')
|
|
87
|
+
assert_empty "does not approve Write tool" "$OUT"
|
|
88
|
+
|
|
89
|
+
# Should approve simple git log
|
|
90
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Bash","tool_input":{"command":"git log --oneline -5"}}')
|
|
91
|
+
assert_contains "approves git log" "$OUT" '"behavior":"allow"'
|
|
92
|
+
|
|
93
|
+
# Should approve git --no-pager log (hardened regex)
|
|
94
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Bash","tool_input":{"command":"git --no-pager log --oneline -5"}}')
|
|
95
|
+
assert_contains "approves git --no-pager log" "$OUT" '"behavior":"allow"'
|
|
96
|
+
|
|
97
|
+
# Should approve git -C path status
|
|
98
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Bash","tool_input":{"command":"git -C ../api status --short"}}')
|
|
99
|
+
assert_contains "approves git -C status" "$OUT" '"behavior":"allow"'
|
|
100
|
+
|
|
101
|
+
# Should approve git branch session/xxx
|
|
102
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Bash","tool_input":{"command":"git branch session/feature-auth preprod"}}')
|
|
103
|
+
assert_contains "approves git branch session/" "$OUT" '"behavior":"allow"'
|
|
104
|
+
|
|
105
|
+
# Should approve git -C ../repo branch session/xxx
|
|
106
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Bash","tool_input":{"command":"git -C ../api branch session/feature-auth preprod"}}')
|
|
107
|
+
assert_contains "approves git -C branch session/" "$OUT" '"behavior":"allow"'
|
|
108
|
+
|
|
109
|
+
# Should approve git worktree add in /tmp/
|
|
110
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Bash","tool_input":{"command":"git worktree add /tmp/api-feature-auth session/feature-auth"}}')
|
|
111
|
+
assert_contains "approves git worktree add /tmp/" "$OUT" '"behavior":"allow"'
|
|
112
|
+
|
|
113
|
+
# Should approve test commands in /tmp/ worktrees
|
|
114
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Bash","tool_input":{"command":"cd /tmp/api-feature-auth && npm run typecheck"}}')
|
|
115
|
+
assert_contains "approves npm typecheck in /tmp/" "$OUT" '"behavior":"allow"'
|
|
116
|
+
|
|
117
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Bash","tool_input":{"command":"cd /tmp/api-feature-auth && php artisan test --filter=UserTest"}}')
|
|
118
|
+
assert_contains "approves php artisan test in /tmp/" "$OUT" '"behavior":"allow"'
|
|
119
|
+
|
|
120
|
+
# Should NOT approve rm -rf
|
|
121
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"}}')
|
|
122
|
+
assert_empty "does not approve rm -rf" "$OUT"
|
|
123
|
+
|
|
124
|
+
# Should NOT approve git checkout (not a safe read op)
|
|
125
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Bash","tool_input":{"command":"git checkout main"}}')
|
|
126
|
+
assert_empty "does not approve git checkout" "$OUT"
|
|
127
|
+
|
|
128
|
+
# Should approve git diff in /tmp/ worktrees
|
|
129
|
+
OUT=$(run_hook "permission-auto-approve.sh" '{"tool_name":"Bash","tool_input":{"command":"git -C /tmp/api-feature-auth diff HEAD~1 HEAD"}}')
|
|
130
|
+
assert_contains "approves git diff in /tmp/" "$OUT" '"behavior":"allow"'
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# ─── validate-spawn-prompt.sh ────────────────────────────────
|
|
134
|
+
echo ""
|
|
135
|
+
echo "▸ validate-spawn-prompt.sh"
|
|
136
|
+
|
|
137
|
+
# Complete prompt should have no warnings
|
|
138
|
+
GOOD_PROMPT='{"tool_input":{"prompt":"## Constitution\n1. **Multi-tenancy** is sacred.\n2. **No hardcoded secrets.**\n\n## Your complete plan — all 3 commit units\n### Commit 1: Data layer\nCreate models\n\n## Your workspace\n- Worktree (ready, go directly here): /tmp/svc-feature-auth\n- Session branch: session/feature-auth\n\n## Signal protocol (MANDATORY)\nAfter EACH commit: SendMessage commit N done. Then WAIT for my green light.\n\nRead the repo CLAUDE.md first.\nIf you hit an architectural decision not in the plan: SendMessage immediately and wait."}}'
|
|
139
|
+
OUT=$(run_hook "validate-spawn-prompt.sh" "$GOOD_PROMPT")
|
|
140
|
+
assert_empty "complete prompt (non-API/non-frontend) — no warnings" "$OUT"
|
|
141
|
+
|
|
142
|
+
# Missing constitution should warn
|
|
143
|
+
NO_CONST='{"tool_input":{"prompt":"## Your plan\n### Commit 1: stuff\nworktree_path: /tmp/api-x\nSendMessage after each commit and wait for green light."}}'
|
|
144
|
+
OUT=$(run_hook "validate-spawn-prompt.sh" "$NO_CONST")
|
|
145
|
+
assert_contains "warns on missing constitution" "$OUT" "project-specific rules"
|
|
146
|
+
|
|
147
|
+
# Missing plan should warn
|
|
148
|
+
NO_PLAN='{"tool_input":{"prompt":"## Constitution\n1. **Rule one.**\nworktree_path: /tmp/api-x\nSendMessage after each commit."}}'
|
|
149
|
+
OUT=$(run_hook "validate-spawn-prompt.sh" "$NO_PLAN")
|
|
150
|
+
assert_contains "warns on missing plan/tasks" "$OUT" "plan/tasks"
|
|
151
|
+
|
|
152
|
+
# Missing worktree path should warn
|
|
153
|
+
NO_WT='{"tool_input":{"prompt":"## Constitution\n1. **Rule one.**\n## Your plan\n### Commit 1: stuff\nSendMessage after each commit."}}'
|
|
154
|
+
OUT=$(run_hook "validate-spawn-prompt.sh" "$NO_WT")
|
|
155
|
+
assert_contains "warns on missing worktree_path" "$OUT" "worktree_path"
|
|
156
|
+
|
|
157
|
+
# Missing signal protocol should warn
|
|
158
|
+
NO_SIGNAL='{"tool_input":{"prompt":"## Constitution\n1. **Rule one.**\n## Your plan\n### Commit 1: stuff\nWorktree ready: /tmp/api-x"}}'
|
|
159
|
+
OUT=$(run_hook "validate-spawn-prompt.sh" "$NO_SIGNAL")
|
|
160
|
+
assert_contains "warns on missing signal protocol" "$OUT" "signal protocol"
|
|
161
|
+
|
|
162
|
+
# Frontend without UX standards should warn
|
|
163
|
+
FRONT_NO_UX='{"tool_input":{"prompt":"## Constitution\n1. **Rule one.**\nfrontend Vue component\n## Your plan\n### Commit 1: UI\n/tmp/front-x\nSendMessage commit N done. WAIT for green light."}}'
|
|
164
|
+
OUT=$(run_hook "validate-spawn-prompt.sh" "$FRONT_NO_UX")
|
|
165
|
+
assert_contains "warns frontend without UX standards" "$OUT" "UX standards"
|
|
166
|
+
|
|
167
|
+
# Empty prompt should produce no output (no crash)
|
|
168
|
+
OUT=$(run_hook "validate-spawn-prompt.sh" '{"tool_input":{"prompt":""}}')
|
|
169
|
+
assert_empty "empty prompt — no crash, no output" "$OUT"
|
|
170
|
+
|
|
171
|
+
# No prompt field should produce no output
|
|
172
|
+
OUT=$(run_hook "validate-spawn-prompt.sh" '{"tool_input":{}}')
|
|
173
|
+
assert_empty "missing prompt field — no crash" "$OUT"
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# ─── session-start-context.sh ────────────────────────────────
|
|
177
|
+
echo ""
|
|
178
|
+
echo "▸ session-start-context.sh"
|
|
179
|
+
|
|
180
|
+
# Note: session-start-context.sh has a glob pattern (for wt in /tmp/*-session-*)
|
|
181
|
+
# that can fail on systems with no matching files unless nullglob is set.
|
|
182
|
+
# We test the parts we can control without needing the orphan cleanup loop.
|
|
183
|
+
|
|
184
|
+
# Setup temp workspace for session-start-context tests
|
|
185
|
+
TEMP_WS=$(mktemp -d)
|
|
186
|
+
mkdir -p "$TEMP_WS/.sessions" "$TEMP_WS/plans"
|
|
187
|
+
|
|
188
|
+
# Create a dummy /tmp/*-session-* dir to prevent glob failure
|
|
189
|
+
DUMMY_WT=$(mktemp -d /tmp/test-session-XXXXXX)
|
|
190
|
+
|
|
191
|
+
# With no workspace.md, should warn
|
|
192
|
+
OUT=$(CLAUDE_PROJECT_DIR="$TEMP_WS" run_hook "session-start-context.sh" '{}')
|
|
193
|
+
assert_contains "warns on missing workspace.md" "$OUT" "No workspace.md"
|
|
194
|
+
|
|
195
|
+
# Create a configured workspace.md
|
|
196
|
+
echo "# Workspace: Test" > "$TEMP_WS/workspace.md"
|
|
197
|
+
OUT=$(CLAUDE_PROJECT_DIR="$TEMP_WS" run_hook "session-start-context.sh" '{}')
|
|
198
|
+
# Should be empty or just orphan cleanup (our dummy dir)
|
|
199
|
+
TOTAL=$((TOTAL + 1))
|
|
200
|
+
if echo "$OUT" | grep -qE "(WARNING|FIRST SESSION|Active plans)"; then
|
|
201
|
+
FAIL=$((FAIL + 1))
|
|
202
|
+
printf " ${RED}✗${RESET} configured workspace — unexpected warnings\n"
|
|
203
|
+
printf " ${DIM}got: %s${RESET}\n" "$OUT"
|
|
204
|
+
else
|
|
205
|
+
PASS=$((PASS + 1))
|
|
206
|
+
printf " ${GREEN}✓${RESET} configured workspace — no unexpected warnings\n"
|
|
207
|
+
fi
|
|
208
|
+
|
|
209
|
+
# Create an unconfigured workspace.md
|
|
210
|
+
echo "[UNCONFIGURED]" > "$TEMP_WS/workspace.md"
|
|
211
|
+
OUT=$(CLAUDE_PROJECT_DIR="$TEMP_WS" run_hook "session-start-context.sh" '{}')
|
|
212
|
+
assert_contains "detects UNCONFIGURED workspace" "$OUT" "FIRST SESSION"
|
|
213
|
+
|
|
214
|
+
# Create an active session and restore configured workspace
|
|
215
|
+
echo "# Workspace: Test" > "$TEMP_WS/workspace.md"
|
|
216
|
+
cat > "$TEMP_WS/.sessions/test.json" << 'SESS'
|
|
217
|
+
{
|
|
218
|
+
"name": "test-session",
|
|
219
|
+
"status": "active",
|
|
220
|
+
"repos": {
|
|
221
|
+
"api": { "worktree_path": "/tmp/nonexistent-test-wt-12345" }
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
SESS
|
|
225
|
+
OUT=$(CLAUDE_PROJECT_DIR="$TEMP_WS" run_hook "session-start-context.sh" '{}')
|
|
226
|
+
assert_contains "shows active sessions" "$OUT" "test-session"
|
|
227
|
+
|
|
228
|
+
# Cleanup
|
|
229
|
+
rm -rf "$TEMP_WS" "$DUMMY_WT"
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
# ─── Summary ────────────────────────────────────────────────
|
|
233
|
+
echo ""
|
|
234
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
235
|
+
if [ "$FAIL" -eq 0 ]; then
|
|
236
|
+
printf "${GREEN}All %d tests passed ✓${RESET}\n" "$TOTAL"
|
|
237
|
+
else
|
|
238
|
+
printf "${RED}%d/%d tests failed${RESET}\n" "$FAIL" "$TOTAL"
|
|
239
|
+
fi
|
|
240
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
241
|
+
|
|
242
|
+
exit "$FAIL"
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# user-prompt-guard.sh
|
|
3
3
|
# UserPromptSubmit hook: conditionally reminds the orchestrator of its role.
|
|
4
|
-
#
|
|
5
|
-
#
|
|
4
|
+
# v5.0: Updated to reflect that Opus can run git/bash on repos for orchestration
|
|
5
|
+
# purposes (branch creation, worktree management, micro-QA), but not code changes.
|
|
6
6
|
# Non-blocking (exit 0 + stdout = context injection).
|
|
7
7
|
set -euo pipefail
|
|
8
8
|
|
|
9
9
|
INPUT=$(cat)
|
|
10
10
|
|
|
11
|
-
# Extract the user prompt text
|
|
11
|
+
# Extract the user prompt text
|
|
12
12
|
PROMPT=$(echo "$INPUT" | jq -r '.prompt // empty' 2>/dev/null) || true
|
|
13
13
|
|
|
14
|
-
# Only inject reminder if user prompt matches code-
|
|
15
|
-
if echo "$PROMPT" | grep -qiE '(
|
|
16
|
-
echo "Role reminder: Writing in sibling repos is for teammates. You can write in orchestrator/ (plans, workspace.md, constitution.md). For repo changes
|
|
14
|
+
# Only inject reminder if user prompt matches direct code-writing patterns
|
|
15
|
+
if echo "$PROMPT" | grep -qiE '(modifie.*fichier|édite.*(api|front|light|spring|scraper|krakend|dashboard)|patch.*service|écris.*dans.*repo|write.*in.*repo|code.*dans.*repo)' 2>/dev/null; then
|
|
16
|
+
echo "Role reminder: Writing application code in sibling repos is for teammates. You can write in orchestrator/ (plans, workspace.md, constitution.md) and run git commands (branch, worktree, log) and test commands in /tmp/ worktrees for micro-QA. For repo application code changes: spawn a teammate."
|
|
17
17
|
fi
|
|
18
18
|
|
|
19
19
|
exit 0
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
# validate-spawn-prompt.sh
|
|
3
3
|
# PreToolUse hook (matcher: Teammate): validates that teammate spawn prompts
|
|
4
4
|
# contain the required context before allowing the spawn.
|
|
5
|
-
#
|
|
5
|
+
# v5.0: Updated for one-teammate-per-repo model with worktree_path and signal protocol.
|
|
6
|
+
# ALL checks are non-blocking warnings (exit 0 + stdout).
|
|
6
7
|
set -euo pipefail
|
|
7
8
|
|
|
8
9
|
INPUT=$(cat)
|
|
@@ -17,65 +18,74 @@ fi
|
|
|
17
18
|
WARNINGS=""
|
|
18
19
|
BLOCKERS=""
|
|
19
20
|
|
|
20
|
-
# Check 1: Project-specific rules
|
|
21
|
-
#
|
|
21
|
+
# Check 1: Project-specific rules / constitution
|
|
22
|
+
# Uses multiple heuristics: section headers, numbered rules (3+), keyword density
|
|
22
23
|
RULES_FOUND=0
|
|
23
|
-
|
|
24
|
+
# Heuristic A: explicit section headers
|
|
25
|
+
if echo "$PROMPT" | grep -qiE '(## (project )?rules|## non-negotiable|## constitution|project-specific rules|rules spécifiques|## engineering principles)' 2>/dev/null; then
|
|
24
26
|
RULES_FOUND=1
|
|
25
27
|
fi
|
|
26
|
-
|
|
28
|
+
# Heuristic B: numbered bold rules (at least 3 = likely a constitution)
|
|
29
|
+
NUMBERED_RULES=$(echo "$PROMPT" | grep -cE '^[0-9]+\.\s+\*\*' 2>/dev/null || echo "0")
|
|
30
|
+
if [ "$NUMBERED_RULES" -ge 3 ]; then
|
|
27
31
|
RULES_FOUND=1
|
|
28
32
|
fi
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
# Heuristic C: constitution keyword + domain-specific terms (2+ matches)
|
|
34
|
+
if echo "$PROMPT" | grep -qiE '(constitution|project rules|non-negotiable)' 2>/dev/null; then
|
|
35
|
+
DOMAIN_HITS=$(echo "$PROMPT" | grep -ciE '(tenant|scoping|precision|rollback|feature flag|naming convention|error handling|code review|test coverage|migration|security|auth|validation)' 2>/dev/null || echo "0")
|
|
36
|
+
if [ "$DOMAIN_HITS" -ge 2 ]; then
|
|
37
|
+
RULES_FOUND=1
|
|
38
|
+
fi
|
|
31
39
|
fi
|
|
32
40
|
if [ "$RULES_FOUND" -eq 0 ]; then
|
|
33
|
-
BLOCKERS+="- Missing project-specific rules in spawn prompt. Include
|
|
41
|
+
BLOCKERS+="- Missing project-specific rules in spawn prompt. Include ALL rules from constitution.md (numbered, in English).\n"
|
|
34
42
|
fi
|
|
35
43
|
|
|
36
|
-
# Check 2: Tasks section must be present
|
|
37
|
-
if ! echo "$PROMPT" | grep -qiE '(your
|
|
38
|
-
BLOCKERS+="- Missing tasks section in spawn prompt. Include the
|
|
44
|
+
# Check 2: Tasks / plan section must be present
|
|
45
|
+
if ! echo "$PROMPT" | grep -qiE '(your (complete )?plan|## (commit|tasks|plan)|commit [0-9]+:|all [0-9]+ commit)' 2>/dev/null; then
|
|
46
|
+
BLOCKERS+="- Missing plan/tasks section in spawn prompt. Include the complete repo plan with all commit units.\n"
|
|
39
47
|
fi
|
|
40
48
|
|
|
41
|
-
# Check 3:
|
|
49
|
+
# Check 3: Worktree path (v5 — teammates receive a ready worktree)
|
|
50
|
+
if ! echo "$PROMPT" | grep -qiE '(worktree.path|worktree.ready|go directly|/tmp/[a-z])' 2>/dev/null; then
|
|
51
|
+
BLOCKERS+="- Missing worktree_path in spawn prompt. Teammate needs the /tmp/ path prepared by Opus.\n"
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# Check 4: Signal protocol instruction
|
|
55
|
+
if ! echo "$PROMPT" | grep -qiE '(SendMessage|signal protocol|commit N done|green light|wait for)' 2>/dev/null; then
|
|
56
|
+
BLOCKERS+="- Missing signal protocol instruction. Teammate must know to SendMessage after each commit and wait for green light.\n"
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
# Check 5: CLAUDE.md instruction
|
|
42
60
|
if ! echo "$PROMPT" | grep -qiE '(CLAUDE\.md|read the repo|repo conventions|read.*conventions)' 2>/dev/null; then
|
|
43
61
|
WARNINGS+="- Missing instruction to read repo CLAUDE.md.\n"
|
|
44
62
|
fi
|
|
45
63
|
|
|
46
|
-
# Check
|
|
47
|
-
if echo "$PROMPT" | grep -qiE '(front|frontend|vue|quasar|nuxt|react|ui
|
|
64
|
+
# Check 6: Frontend teammates need UX standards
|
|
65
|
+
if echo "$PROMPT" | grep -qiE '(front|frontend|vue|quasar|nuxt|react|ui component)' 2>/dev/null; then
|
|
48
66
|
UX_SIGNALS=0
|
|
49
67
|
echo "$PROMPT" | grep -qiE '(4 (mandatory )?states|skeleton|empty state)' 2>/dev/null && UX_SIGNALS=$((UX_SIGNALS + 1))
|
|
50
68
|
echo "$PROMPT" | grep -qiE '(responsive|mobile.first)' 2>/dev/null && UX_SIGNALS=$((UX_SIGNALS + 1))
|
|
51
69
|
echo "$PROMPT" | grep -qiE '(accessib|aria.label|wcag)' 2>/dev/null && UX_SIGNALS=$((UX_SIGNALS + 1))
|
|
52
70
|
echo "$PROMPT" | grep -qiE '(ux standard|error.state|loading.state)' 2>/dev/null && UX_SIGNALS=$((UX_SIGNALS + 1))
|
|
53
71
|
if [ "$UX_SIGNALS" -lt 2 ]; then
|
|
54
|
-
BLOCKERS+="- Frontend teammate detected but UX standards not
|
|
72
|
+
BLOCKERS+="- Frontend teammate detected but UX standards not included (found $UX_SIGNALS/4 signals). Inject frontend-ux-standards.md content.\n"
|
|
55
73
|
fi
|
|
56
74
|
fi
|
|
57
75
|
|
|
58
|
-
# Check
|
|
59
|
-
if echo "$PROMPT" | grep -qiE '(api|backend|endpoint|rest
|
|
60
|
-
if ! echo "$PROMPT" | grep -qiE '(contract|response shape|request shape|interface|payload|
|
|
76
|
+
# Check 7: API teammates need contract shapes
|
|
77
|
+
if echo "$PROMPT" | grep -qiE '(api|backend|endpoint|rest)' 2>/dev/null; then
|
|
78
|
+
if ! echo "$PROMPT" | grep -qiE '(contract|response shape|request shape|interface|payload|GET /|POST /|PUT /|DELETE /)' 2>/dev/null; then
|
|
61
79
|
WARNINGS+="- API teammate detected but no contract/shapes found in prompt. Consider including the API contract.\n"
|
|
62
80
|
fi
|
|
63
81
|
fi
|
|
64
82
|
|
|
65
|
-
# Check
|
|
66
|
-
if ! echo "$PROMPT" | grep -qiE '(escalat|STOP
|
|
67
|
-
WARNINGS+="- Missing escalation instruction. Include: 'If you hit an architectural decision
|
|
68
|
-
fi
|
|
69
|
-
|
|
70
|
-
# Check 7: Session branch instruction (if sessions exist)
|
|
71
|
-
SESSIONS_DIR="${CLAUDE_PROJECT_DIR:-.}/.sessions"
|
|
72
|
-
if [ -d "$SESSIONS_DIR" ] && ls "$SESSIONS_DIR"/*.json >/dev/null 2>&1; then
|
|
73
|
-
if ! echo "$PROMPT" | grep -qiE '(session/|session branch|ALREADY EXISTS.*branch)' 2>/dev/null; then
|
|
74
|
-
WARNINGS+="- Active sessions exist but no session branch found in spawn prompt. Include the session branch instruction.\n"
|
|
75
|
-
fi
|
|
83
|
+
# Check 8: Escalation instruction
|
|
84
|
+
if ! echo "$PROMPT" | grep -qiE '(escalat|STOP|SendMessage.*blocker|architectural decision)' 2>/dev/null; then
|
|
85
|
+
WARNINGS+="- Missing escalation instruction. Include: 'If you hit an architectural decision not in the plan: SendMessage immediately and wait.'\n"
|
|
76
86
|
fi
|
|
77
87
|
|
|
78
|
-
# Report — ALL checks are warnings only (
|
|
88
|
+
# Report — ALL checks are warnings only (v5.0)
|
|
79
89
|
ISSUES=""
|
|
80
90
|
[ -n "$BLOCKERS" ] && ISSUES+="$BLOCKERS"
|
|
81
91
|
[ -n "$WARNINGS" ] && ISSUES+="$WARNINGS"
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: metrics
|
|
3
|
+
prompt_version: 5.2.1
|
|
4
|
+
description: >
|
|
5
|
+
Quantitative analysis of orchestrator performance. Parses session logs,
|
|
6
|
+
completed plans, and QA reports to produce KPIs: re-dispatch rate,
|
|
7
|
+
micro-QA first-pass rate, commits per session, QA findings distribution,
|
|
8
|
+
escalation rate, and phase timing estimates.
|
|
9
|
+
Use: /metrics, /metrics last-5, /metrics session-name.
|
|
10
|
+
Helps justify model routing decisions and prompt improvements.
|
|
11
|
+
argument-hint: "[all | last-N | session-name]"
|
|
12
|
+
context: fork
|
|
13
|
+
allowed-tools: Bash, Read, Glob, Grep
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Metrics — Orchestrator Performance Dashboard
|
|
17
|
+
|
|
18
|
+
You analyze completed sessions and plans to produce quantitative KPIs.
|
|
19
|
+
You do NOT modify any files — read-only analysis.
|
|
20
|
+
|
|
21
|
+
## Data sources
|
|
22
|
+
|
|
23
|
+
1. `./plans/*.md` — completed plans with progress trackers, QA reports, session logs
|
|
24
|
+
2. `./.sessions/*.json` — session metadata with commit tracking
|
|
25
|
+
3. `./plans/retro-*.md` — retrospectives with finding summaries
|
|
26
|
+
|
|
27
|
+
## Scope detection
|
|
28
|
+
|
|
29
|
+
| Argument | Behavior |
|
|
30
|
+
|----------|----------|
|
|
31
|
+
| `all` or no argument | Analyze all completed plans |
|
|
32
|
+
| `last-N` (e.g., last-5) | Analyze the N most recent completed plans |
|
|
33
|
+
| `{session-name}` | Analyze one specific session/plan |
|
|
34
|
+
|
|
35
|
+
## Metrics to extract
|
|
36
|
+
|
|
37
|
+
### Per-session metrics
|
|
38
|
+
|
|
39
|
+
For each completed plan, extract:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
PLAN="./plans/{name}.md"
|
|
43
|
+
|
|
44
|
+
# 1. Commit metrics
|
|
45
|
+
TOTAL_COMMITS=$(grep -c '✅\|❌' "$PLAN" 2>/dev/null || echo 0)
|
|
46
|
+
SUCCESSFUL_COMMITS=$(grep -c '✅' "$PLAN" 2>/dev/null || echo 0)
|
|
47
|
+
FAILED_COMMITS=$(grep -c '❌' "$PLAN" 2>/dev/null || echo 0)
|
|
48
|
+
ESCALATED=$(grep -c 'ESCALATED' "$PLAN" 2>/dev/null || echo 0)
|
|
49
|
+
|
|
50
|
+
# 2. Re-dispatch metrics (from session log entries)
|
|
51
|
+
REDISPATCHES=$(grep -c 're-dispatch\|retry\|fix instruction' "$PLAN" 2>/dev/null || echo 0)
|
|
52
|
+
|
|
53
|
+
# 3. QA findings (from QA Report section)
|
|
54
|
+
BUGS=$(grep -c '🔴' "$PLAN" 2>/dev/null || echo 0)
|
|
55
|
+
SMELLS=$(grep -c '🟡' "$PLAN" 2>/dev/null || echo 0)
|
|
56
|
+
DEAD_CODE=$(grep -c '🟠' "$PLAN" 2>/dev/null || echo 0)
|
|
57
|
+
MISSING_TESTS=$(grep -c '🔵' "$PLAN" 2>/dev/null || echo 0)
|
|
58
|
+
UX_VIOLATIONS=$(grep -c '🟣' "$PLAN" 2>/dev/null || echo 0)
|
|
59
|
+
NITPICKS=$(grep -c '⚪' "$PLAN" 2>/dev/null || echo 0)
|
|
60
|
+
|
|
61
|
+
# 4. Cross-service check results
|
|
62
|
+
CROSS_PASS=$(grep -c '✅' "$PLAN" 2>/dev/null || echo 0) # within cross-service section
|
|
63
|
+
CROSS_FAIL=$(grep -c '❌' "$PLAN" 2>/dev/null || echo 0) # within cross-service section
|
|
64
|
+
|
|
65
|
+
# 5. Services impacted
|
|
66
|
+
REPOS_COUNT=$(jq '.repos | length' "./.sessions/{name}.json" 2>/dev/null || echo "?")
|
|
67
|
+
|
|
68
|
+
# 6. Waves used
|
|
69
|
+
WAVES=$(grep -c 'Wave [0-9]' "$PLAN" 2>/dev/null || echo 1)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Aggregate KPIs (across all analyzed sessions)
|
|
73
|
+
|
|
74
|
+
Calculate and present:
|
|
75
|
+
|
|
76
|
+
| KPI | Formula | Target |
|
|
77
|
+
|-----|---------|--------|
|
|
78
|
+
| **Micro-QA first-pass rate** | successful_commits / total_commits × 100 | > 80% |
|
|
79
|
+
| **Re-dispatch rate** | re-dispatches / total_commits × 100 | < 15% |
|
|
80
|
+
| **Escalation rate** | escalations / total_commits × 100 | < 5% |
|
|
81
|
+
| **QA bug density** | 🔴 findings / total_commits | < 0.3 |
|
|
82
|
+
| **UX violation rate** | 🟣 findings / frontend_commits × 100 | < 10% |
|
|
83
|
+
| **Dead code per session** | avg 🟠 findings per session | trending ↓ |
|
|
84
|
+
| **Cross-service consistency** | cross_pass / (cross_pass + cross_fail) × 100 | > 90% |
|
|
85
|
+
|
|
86
|
+
### Trend analysis (if multiple sessions)
|
|
87
|
+
|
|
88
|
+
If analyzing 3+ sessions, show trends:
|
|
89
|
+
- Are QA findings decreasing over time? (retrospective loop working?)
|
|
90
|
+
- Are re-dispatches decreasing? (plan quality improving?)
|
|
91
|
+
- Are UX violations decreasing? (UX standards being learned?)
|
|
92
|
+
|
|
93
|
+
## Output format
|
|
94
|
+
|
|
95
|
+
```markdown
|
|
96
|
+
## Metrics Report — [DATE]
|
|
97
|
+
|
|
98
|
+
### Scope: [all / last-N / session-name]
|
|
99
|
+
Sessions analyzed: N | Plans: N | Total commits: N
|
|
100
|
+
|
|
101
|
+
### KPI Dashboard
|
|
102
|
+
|
|
103
|
+
| KPI | Value | Target | Status |
|
|
104
|
+
|-----|-------|--------|--------|
|
|
105
|
+
| Micro-QA first-pass | 85% | >80% | ✅ |
|
|
106
|
+
| Re-dispatch rate | 12% | <15% | ✅ |
|
|
107
|
+
| Escalation rate | 3% | <5% | ✅ |
|
|
108
|
+
| QA bug density | 0.4 | <0.3 | ⚠️ |
|
|
109
|
+
| UX violation rate | 8% | <10% | ✅ |
|
|
110
|
+
| Cross-service consistency | 95% | >90% | ✅ |
|
|
111
|
+
|
|
112
|
+
### QA Findings Distribution
|
|
113
|
+
|
|
114
|
+
| Category | Count | % | Trend |
|
|
115
|
+
|----------|-------|---|-------|
|
|
116
|
+
| 🔴 Bugs | N | N% | ↑↓→ |
|
|
117
|
+
| 🟡 Smells | N | N% | ↑↓→ |
|
|
118
|
+
| 🟠 Dead code | N | N% | ↑↓→ |
|
|
119
|
+
| 🔵 Missing tests | N | N% | ↑↓→ |
|
|
120
|
+
| 🟣 UX violations | N | N% | ↑↓→ |
|
|
121
|
+
| ⚪ Nitpicks | N | N% | ↑↓→ |
|
|
122
|
+
|
|
123
|
+
### Per-Session Breakdown
|
|
124
|
+
|
|
125
|
+
| Session | Repos | Commits | Pass | Fail | Re-dispatch | QA 🔴 | QA 🟣 |
|
|
126
|
+
|---------|-------|---------|------|------|-------------|--------|--------|
|
|
127
|
+
| {name} | N | N | N | N | N | N | N |
|
|
128
|
+
|
|
129
|
+
### Insights
|
|
130
|
+
- [Actionable observation based on data]
|
|
131
|
+
- [Suggestion for prompt/process improvement backed by numbers]
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Present the report to the user. Do NOT write it to a file unless asked.
|
|
135
|
+
|
|
136
|
+
## Anti-patterns
|
|
137
|
+
- NEVER fabricate metrics — only report what's extractable from actual files
|
|
138
|
+
- NEVER compare to other teams/projects — only compare to own history
|
|
139
|
+
- If data is insufficient (< 3 sessions), say so instead of producing meaningless trends
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: plan-review
|
|
3
|
+
prompt_version: 5.2.1
|
|
3
4
|
description: >
|
|
4
5
|
Quick sanity check on a plan before the user validates it. Verifies
|
|
5
6
|
structural completeness: all tasks have a service, waves respect
|
|
@@ -9,7 +10,7 @@ argument-hint: "[plan-name.md]"
|
|
|
9
10
|
context: fork
|
|
10
11
|
agent: Explore
|
|
11
12
|
disable-model-invocation: true
|
|
12
|
-
model:
|
|
13
|
+
model: sonnet
|
|
13
14
|
allowed-tools: Read, Glob, Grep
|
|
14
15
|
---
|
|
15
16
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: qa-ruthless
|
|
3
|
+
prompt_version: 5.2.1
|
|
3
4
|
description: >
|
|
4
5
|
Adversarial QA review after feature implementation. MUST find problems —
|
|
5
6
|
a clean report is a failed review. Executes tests, hunts dead code,
|
|
@@ -8,6 +9,7 @@ description: >
|
|
|
8
9
|
"test", "quality", "qa ruthless", "find bugs".
|
|
9
10
|
argument-hint: "[plan-name or 'all']"
|
|
10
11
|
context: fork
|
|
12
|
+
model: opus
|
|
11
13
|
allowed-tools: Read, Write, Glob, Grep, Task, Teammate, SendMessage
|
|
12
14
|
---
|
|
13
15
|
|
|
@@ -16,28 +16,13 @@ globs: ["workspace.md", "plans/**", "constitution.md", "templates/**"]
|
|
|
16
16
|
## Response limits
|
|
17
17
|
- No code in repos — delegate repo code to teammates
|
|
18
18
|
- Writing in orchestrator/ (plans, workspace.md, constitution.md) is allowed and expected
|
|
19
|
-
- Teammate results: summarize to status + files + problems
|
|
19
|
+
- Teammate results: summarize to status + files + problems
|
|
20
20
|
|
|
21
|
-
##
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
(plan → teammates → collect → QA)
|
|
25
|
-
- Also compact when responses visibly slow down
|
|
21
|
+
## Context compaction
|
|
22
|
+
- Claude Code handles compaction automatically — no manual `/compact` needed
|
|
23
|
+
- The SessionStart hook re-injects active plan context after any `/clear`
|
|
26
24
|
|
|
27
25
|
## Triggers for /clear
|
|
28
26
|
- Switching to a completely different feature/epic
|
|
29
27
|
- After merging a completed feature
|
|
30
28
|
- Start of day / new work session
|
|
31
|
-
|
|
32
|
-
## Monitoring
|
|
33
|
-
- The `SessionStart` hook automatically injects active plan context
|
|
34
|
-
at startup or after a `/clear`
|
|
35
|
-
- If a config issue is suspected, use `/hooks` to inspect
|
|
36
|
-
|
|
37
|
-
## Context compaction (Opus 4.6)
|
|
38
|
-
- Opus 4.6 supports native context compaction — the model can summarize
|
|
39
|
-
its own context to continue longer-running tasks without hitting limits
|
|
40
|
-
- The 1M context window (beta) is available but token-intensive.
|
|
41
|
-
Disable with `CLAUDE_CODE_DISABLE_1M_CONTEXT=1` if cost is a concern
|
|
42
|
-
- For orchestration sessions, prefer compact-after-cycle over 1M context:
|
|
43
|
-
smaller context = faster responses = cheaper
|