oh-my-customcode 0.19.3 → 0.20.0
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/README.md +2 -2
- package/package.json +1 -1
- package/templates/.claude/hooks/hooks.json +24 -0
- package/templates/.claude/hooks/scripts/model-escalation-advisor.sh +103 -0
- package/templates/.claude/hooks/scripts/session-env-check.sh +18 -0
- package/templates/.claude/hooks/scripts/stuck-detector.sh +125 -0
- package/templates/.claude/hooks/scripts/task-outcome-recorder.sh +63 -0
- package/templates/.claude/rules/MUST-agent-design.md +14 -0
- package/templates/.claude/rules/MUST-agent-teams.md +35 -0
- package/templates/.claude/rules/MUST-parallel-execution.md +13 -0
- package/templates/.claude/skills/model-escalation/SKILL.md +60 -0
- package/templates/.claude/skills/stuck-recovery/SKILL.md +54 -0
- package/templates/manifest.json +1 -1
package/README.md
CHANGED
|
@@ -124,7 +124,7 @@ Claude Code selects the appropriate model and parallelizes independent tasks (up
|
|
|
124
124
|
| **QA** | 3 | qa-planner, qa-writer, qa-engineer |
|
|
125
125
|
| **Total** | **41** | |
|
|
126
126
|
|
|
127
|
-
### Skills (
|
|
127
|
+
### Skills (58)
|
|
128
128
|
|
|
129
129
|
| Category | Count | Skills |
|
|
130
130
|
|----------|-------|--------|
|
|
@@ -137,7 +137,7 @@ Claude Code selects the appropriate model and parallelizes independent tasks (up
|
|
|
137
137
|
| **Package Management** | 3 | npm-publish, npm-version, npm-audit |
|
|
138
138
|
| **Operations** | 7 | update-docs, update-external, audit-agents, fix-refs, sauron-watch, monitoring-setup, claude-code-bible |
|
|
139
139
|
| **Utilities** | 5 | lists, help, status, result-aggregation, writing-clearly-and-concisely |
|
|
140
|
-
| **Quality & Workflow** |
|
|
140
|
+
| **Quality & Workflow** | 4 | multi-model-verification, structured-dev-cycle, model-escalation, stuck-recovery |
|
|
141
141
|
| **Deploy** | 2 | vercel-deploy, codex-exec |
|
|
142
142
|
| **External** | 1 | skills-sh-search |
|
|
143
143
|
|
package/package.json
CHANGED
|
@@ -76,6 +76,10 @@
|
|
|
76
76
|
{
|
|
77
77
|
"type": "command",
|
|
78
78
|
"command": "bash .claude/hooks/scripts/agent-teams-advisor.sh"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"type": "command",
|
|
82
|
+
"command": "bash .claude/hooks/scripts/model-escalation-advisor.sh"
|
|
79
83
|
}
|
|
80
84
|
],
|
|
81
85
|
"description": "HUD statusline + R010 git delegation guard + R018 Agent Teams advisor on Task spawn"
|
|
@@ -163,6 +167,26 @@
|
|
|
163
167
|
}
|
|
164
168
|
],
|
|
165
169
|
"description": "Type check Python files with ty after edits"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"matcher": "tool == \"Task\"",
|
|
173
|
+
"hooks": [
|
|
174
|
+
{
|
|
175
|
+
"type": "command",
|
|
176
|
+
"command": "bash .claude/hooks/scripts/task-outcome-recorder.sh"
|
|
177
|
+
}
|
|
178
|
+
],
|
|
179
|
+
"description": "Record task outcomes (success/failure) for model escalation decisions"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"matcher": "tool == \"Edit\" || tool == \"Write\" || tool == \"Bash\" || tool == \"Task\"",
|
|
183
|
+
"hooks": [
|
|
184
|
+
{
|
|
185
|
+
"type": "command",
|
|
186
|
+
"command": "bash .claude/hooks/scripts/stuck-detector.sh"
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
"description": "Detect repetitive failure loops and advise recovery strategies"
|
|
166
190
|
}
|
|
167
191
|
],
|
|
168
192
|
"Stop": [
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Model Escalation Advisor Hook
|
|
5
|
+
# Trigger: PreToolUse, tool == "Task"
|
|
6
|
+
# Purpose: Advise model escalation when failure patterns detected
|
|
7
|
+
# Protocol: stdin JSON -> process -> stdout pass-through, exit 0 always
|
|
8
|
+
|
|
9
|
+
input=$(cat)
|
|
10
|
+
|
|
11
|
+
# Extract current task info
|
|
12
|
+
agent_type=$(echo "$input" | jq -r '.tool_input.subagent_type // "unknown"')
|
|
13
|
+
current_model=$(echo "$input" | jq -r '.tool_input.model // "inherit"')
|
|
14
|
+
|
|
15
|
+
# Session-scoped outcome log
|
|
16
|
+
OUTCOME_FILE="/tmp/.claude-task-outcomes-${PPID}"
|
|
17
|
+
|
|
18
|
+
# Skip if no history
|
|
19
|
+
if [ ! -f "$OUTCOME_FILE" ]; then
|
|
20
|
+
echo "$input"
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Thresholds
|
|
25
|
+
FAILURE_THRESHOLD=2
|
|
26
|
+
CONSECUTIVE_THRESHOLD=3
|
|
27
|
+
COOLDOWN=5
|
|
28
|
+
|
|
29
|
+
# Count failures for this agent type
|
|
30
|
+
agent_failures=0
|
|
31
|
+
if [ -n "$agent_type" ] && [ "$agent_type" != "unknown" ]; then
|
|
32
|
+
agent_failures=$(grep -c "\"agent_type\":\"${agent_type}\".*\"outcome\":\"failure\"" "$OUTCOME_FILE" 2>/dev/null || echo "0")
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# Count consecutive failures (tail entries)
|
|
36
|
+
consecutive_failures=$(tail -${CONSECUTIVE_THRESHOLD} "$OUTCOME_FILE" 2>/dev/null | grep -c '"outcome":"failure"' 2>/dev/null || echo "0")
|
|
37
|
+
|
|
38
|
+
# Escalation path
|
|
39
|
+
next_model=""
|
|
40
|
+
cost_multiplier=""
|
|
41
|
+
case "$current_model" in
|
|
42
|
+
haiku)
|
|
43
|
+
next_model="sonnet"
|
|
44
|
+
cost_multiplier="~3-5x"
|
|
45
|
+
;;
|
|
46
|
+
sonnet)
|
|
47
|
+
next_model="opus"
|
|
48
|
+
cost_multiplier="~5-10x"
|
|
49
|
+
;;
|
|
50
|
+
*)
|
|
51
|
+
next_model=""
|
|
52
|
+
;;
|
|
53
|
+
esac
|
|
54
|
+
|
|
55
|
+
# Advise escalation
|
|
56
|
+
if [ -n "$next_model" ]; then
|
|
57
|
+
should_advise=false
|
|
58
|
+
reason=""
|
|
59
|
+
|
|
60
|
+
if [ "$agent_failures" -ge "$FAILURE_THRESHOLD" ]; then
|
|
61
|
+
should_advise=true
|
|
62
|
+
reason="${agent_type} failed ${agent_failures}x with ${current_model}"
|
|
63
|
+
elif [ "$consecutive_failures" -ge "$CONSECUTIVE_THRESHOLD" ]; then
|
|
64
|
+
should_advise=true
|
|
65
|
+
reason="${consecutive_failures} consecutive failures"
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
if [ "$should_advise" = true ]; then
|
|
69
|
+
echo "" >&2
|
|
70
|
+
echo "--- [Model Escalation Advisory] ---" >&2
|
|
71
|
+
echo " Agent type: ${agent_type}" >&2
|
|
72
|
+
echo " Current model: ${current_model}" >&2
|
|
73
|
+
echo " ⚡ Recommended: Escalate to ${next_model}" >&2
|
|
74
|
+
echo " Cost impact: ${cost_multiplier} per task" >&2
|
|
75
|
+
echo " Reason: ${reason}" >&2
|
|
76
|
+
echo "------------------------------------" >&2
|
|
77
|
+
fi
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# De-escalation check
|
|
81
|
+
if [ "$current_model" != "haiku" ] && [ "$current_model" != "inherit" ] && [ "$current_model" != "" ]; then
|
|
82
|
+
recent_successes=$(tail -${COOLDOWN} "$OUTCOME_FILE" 2>/dev/null | grep -c '"outcome":"success"' 2>/dev/null || echo "0")
|
|
83
|
+
|
|
84
|
+
if [ "$recent_successes" -ge "$COOLDOWN" ]; then
|
|
85
|
+
lower_model=""
|
|
86
|
+
case "$current_model" in
|
|
87
|
+
opus) lower_model="sonnet" ;;
|
|
88
|
+
sonnet) lower_model="haiku" ;;
|
|
89
|
+
esac
|
|
90
|
+
|
|
91
|
+
if [ -n "$lower_model" ]; then
|
|
92
|
+
echo "" >&2
|
|
93
|
+
echo "--- [Model De-escalation Advisory] ---" >&2
|
|
94
|
+
echo " ↓ Consider: ${current_model} → ${lower_model}" >&2
|
|
95
|
+
echo " ${recent_successes} consecutive successes" >&2
|
|
96
|
+
echo "--------------------------------------" >&2
|
|
97
|
+
fi
|
|
98
|
+
fi
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# Pass through
|
|
102
|
+
echo "$input"
|
|
103
|
+
exit 0
|
|
@@ -27,16 +27,34 @@ if [ "${CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS:-0}" = "1" ]; then
|
|
|
27
27
|
AGENT_TEAMS_STATUS="enabled"
|
|
28
28
|
fi
|
|
29
29
|
|
|
30
|
+
# Git workflow reminder
|
|
31
|
+
CURRENT_BRANCH="unknown"
|
|
32
|
+
if command -v git >/dev/null 2>&1 && git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
33
|
+
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
|
|
34
|
+
fi
|
|
35
|
+
|
|
30
36
|
# Write status to file for other hooks to reference
|
|
31
37
|
STATUS_FILE="/tmp/.claude-env-status-${PPID}"
|
|
32
38
|
cat > "$STATUS_FILE" << ENVEOF
|
|
33
39
|
codex=${CODEX_STATUS}
|
|
34
40
|
agent_teams=${AGENT_TEAMS_STATUS}
|
|
41
|
+
git_branch=${CURRENT_BRANCH}
|
|
35
42
|
ENVEOF
|
|
36
43
|
|
|
37
44
|
# Report to stderr (visible in conversation)
|
|
38
45
|
echo " codex CLI: ${CODEX_STATUS}" >&2
|
|
39
46
|
echo " Agent Teams: ${AGENT_TEAMS_STATUS}" >&2
|
|
47
|
+
echo "" >&2
|
|
48
|
+
echo " [Git Workflow Reminder]" >&2
|
|
49
|
+
echo " Current branch: ${CURRENT_BRANCH}" >&2
|
|
50
|
+
if [ "$CURRENT_BRANCH" = "develop" ] || [ "$CURRENT_BRANCH" = "main" ] || [ "$CURRENT_BRANCH" = "master" ]; then
|
|
51
|
+
echo " ⚠ You are on a protected branch!" >&2
|
|
52
|
+
echo " ⚠ Create a feature branch before making changes:" >&2
|
|
53
|
+
echo " git checkout -b feat/your-feature develop" >&2
|
|
54
|
+
else
|
|
55
|
+
echo " ✓ Feature branch detected" >&2
|
|
56
|
+
fi
|
|
57
|
+
echo " Rules: feature branch → commit → push → PR → merge" >&2
|
|
40
58
|
echo "------------------------------------" >&2
|
|
41
59
|
|
|
42
60
|
# Pass through
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Stuck Detector Hook
|
|
5
|
+
# Trigger: PostToolUse, tool matches "Edit|Write|Bash|Task"
|
|
6
|
+
# Purpose: Detect repetitive failure loops and advise recovery
|
|
7
|
+
# Protocol: stdin JSON -> process -> stdout pass-through, exit 0 always
|
|
8
|
+
|
|
9
|
+
input=$(cat)
|
|
10
|
+
|
|
11
|
+
# Extract tool info
|
|
12
|
+
tool_name=$(echo "$input" | jq -r '.tool_name // "unknown"')
|
|
13
|
+
file_path=$(echo "$input" | jq -r '.tool_input.file_path // .tool_input.command // ""' | head -c 120)
|
|
14
|
+
is_error=$(echo "$input" | jq -r '.tool_output.is_error // false')
|
|
15
|
+
output_preview=$(echo "$input" | jq -r '.tool_output.output // ""' | head -c 200)
|
|
16
|
+
|
|
17
|
+
# Session-scoped history
|
|
18
|
+
HISTORY_FILE="/tmp/.claude-tool-history-${PPID}"
|
|
19
|
+
|
|
20
|
+
# Create entry
|
|
21
|
+
timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
22
|
+
|
|
23
|
+
# Generate error hash for deduplication (first 50 chars of error)
|
|
24
|
+
error_hash=""
|
|
25
|
+
if [ "$is_error" = "true" ]; then
|
|
26
|
+
error_hash=$(echo "$output_preview" | head -c 50 | md5sum 2>/dev/null | cut -d' ' -f1 || echo "unknown")
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
entry=$(jq -n \
|
|
30
|
+
--arg ts "$timestamp" \
|
|
31
|
+
--arg tool "$tool_name" \
|
|
32
|
+
--arg path "$file_path" \
|
|
33
|
+
--arg err "$is_error" \
|
|
34
|
+
--arg hash "$error_hash" \
|
|
35
|
+
--arg preview "$output_preview" \
|
|
36
|
+
'{timestamp: $ts, tool: $tool, path: $path, is_error: $err, error_hash: $hash, preview: $preview}')
|
|
37
|
+
|
|
38
|
+
echo "$entry" >> "$HISTORY_FILE"
|
|
39
|
+
|
|
40
|
+
# Ring buffer: keep last 100 entries
|
|
41
|
+
if [ -f "$HISTORY_FILE" ]; then
|
|
42
|
+
line_count=$(wc -l < "$HISTORY_FILE")
|
|
43
|
+
if [ "$line_count" -gt 100 ]; then
|
|
44
|
+
tail -100 "$HISTORY_FILE" > "${HISTORY_FILE}.tmp"
|
|
45
|
+
mv "${HISTORY_FILE}.tmp" "$HISTORY_FILE"
|
|
46
|
+
fi
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# --- Detection Logic ---
|
|
50
|
+
|
|
51
|
+
# Only check for patterns if we have enough history
|
|
52
|
+
if [ ! -f "$HISTORY_FILE" ]; then
|
|
53
|
+
echo "$input"
|
|
54
|
+
exit 0
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
recent_count=$(wc -l < "$HISTORY_FILE")
|
|
58
|
+
if [ "$recent_count" -lt 3 ]; then
|
|
59
|
+
echo "$input"
|
|
60
|
+
exit 0
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
stuck_detected=false
|
|
64
|
+
signal_type=""
|
|
65
|
+
pattern_desc=""
|
|
66
|
+
occurrence_count=0
|
|
67
|
+
threshold=0
|
|
68
|
+
recovery=""
|
|
69
|
+
|
|
70
|
+
# Signal 1: Repeated error (same error_hash 3+ times in last 10 entries)
|
|
71
|
+
if [ "$is_error" = "true" ] && [ -n "$error_hash" ]; then
|
|
72
|
+
error_repeat=$(tail -10 "$HISTORY_FILE" | grep -c "\"error_hash\":\"${error_hash}\"" 2>/dev/null || echo "0")
|
|
73
|
+
if [ "$error_repeat" -ge 3 ]; then
|
|
74
|
+
stuck_detected=true
|
|
75
|
+
signal_type="Repeated error"
|
|
76
|
+
pattern_desc="Same error appeared ${error_repeat} times in last 10 tool calls"
|
|
77
|
+
occurrence_count=$error_repeat
|
|
78
|
+
threshold=3
|
|
79
|
+
recovery="Rephrase the task or try a different approach"
|
|
80
|
+
fi
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# Signal 2: Edit loop (same file edited 3+ times in last 8 entries)
|
|
84
|
+
if [ "$stuck_detected" = false ] && { [ "$tool_name" = "Edit" ] || [ "$tool_name" = "Write" ]; }; then
|
|
85
|
+
if [ -n "$file_path" ]; then
|
|
86
|
+
escaped_path=$(echo "$file_path" | sed 's/[.[\*^$()+?{|]/\\&/g')
|
|
87
|
+
edit_repeat=$(tail -8 "$HISTORY_FILE" | grep -c "\"path\":\"${escaped_path}\"" 2>/dev/null || echo "0")
|
|
88
|
+
if [ "$edit_repeat" -ge 3 ]; then
|
|
89
|
+
stuck_detected=true
|
|
90
|
+
signal_type="Edit loop"
|
|
91
|
+
pattern_desc="$(basename "$file_path") edited ${edit_repeat} times in last 8 calls"
|
|
92
|
+
occurrence_count=$edit_repeat
|
|
93
|
+
threshold=3
|
|
94
|
+
recovery="Try a different file or approach instead of re-editing"
|
|
95
|
+
fi
|
|
96
|
+
fi
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
# Signal 3: Tool spam (same tool 5+ times in last 8 entries)
|
|
100
|
+
if [ "$stuck_detected" = false ]; then
|
|
101
|
+
tool_repeat=$(tail -8 "$HISTORY_FILE" | grep -c "\"tool\":\"${tool_name}\"" 2>/dev/null || echo "0")
|
|
102
|
+
if [ "$tool_repeat" -ge 5 ]; then
|
|
103
|
+
stuck_detected=true
|
|
104
|
+
signal_type="Tool loop"
|
|
105
|
+
pattern_desc="${tool_name} called ${tool_repeat} times in last 8 calls"
|
|
106
|
+
occurrence_count=$tool_repeat
|
|
107
|
+
threshold=5
|
|
108
|
+
recovery="Step back and reconsider the approach"
|
|
109
|
+
fi
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
# Output advisory if stuck detected
|
|
113
|
+
if [ "$stuck_detected" = true ]; then
|
|
114
|
+
echo "" >&2
|
|
115
|
+
echo "--- [Stuck Detection] Loop detected ---" >&2
|
|
116
|
+
echo " Signal: ${signal_type}" >&2
|
|
117
|
+
echo " Pattern: ${pattern_desc}" >&2
|
|
118
|
+
echo " Occurrences: ${occurrence_count}/${threshold}" >&2
|
|
119
|
+
echo " 💡 Recovery: ${recovery}" >&2
|
|
120
|
+
echo "----------------------------------------" >&2
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# Pass through
|
|
124
|
+
echo "$input"
|
|
125
|
+
exit 0
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Task Outcome Recorder Hook
|
|
5
|
+
# Trigger: PostToolUse, tool == "Task"
|
|
6
|
+
# Purpose: Record task outcomes for model escalation decisions
|
|
7
|
+
# Protocol: stdin JSON -> process -> stdout pass-through, exit 0 always
|
|
8
|
+
|
|
9
|
+
input=$(cat)
|
|
10
|
+
|
|
11
|
+
# Extract task info
|
|
12
|
+
agent_type=$(echo "$input" | jq -r '.tool_input.subagent_type // "unknown"')
|
|
13
|
+
model=$(echo "$input" | jq -r '.tool_input.model // "inherit"')
|
|
14
|
+
description=$(echo "$input" | jq -r '.tool_input.description // ""' | head -c 80)
|
|
15
|
+
|
|
16
|
+
# Determine outcome
|
|
17
|
+
is_error=$(echo "$input" | jq -r '.tool_output.is_error // false')
|
|
18
|
+
|
|
19
|
+
if [ "$is_error" = "true" ]; then
|
|
20
|
+
outcome="failure"
|
|
21
|
+
error_summary=$(echo "$input" | jq -r '.tool_output.output // ""' | head -c 200)
|
|
22
|
+
else
|
|
23
|
+
outcome="success"
|
|
24
|
+
error_summary=""
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Session-scoped outcome log
|
|
28
|
+
OUTCOME_FILE="/tmp/.claude-task-outcomes-${PPID}"
|
|
29
|
+
|
|
30
|
+
# Append JSON line entry
|
|
31
|
+
timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
32
|
+
entry=$(jq -n \
|
|
33
|
+
--arg ts "$timestamp" \
|
|
34
|
+
--arg agent "$agent_type" \
|
|
35
|
+
--arg model "$model" \
|
|
36
|
+
--arg outcome "$outcome" \
|
|
37
|
+
--arg desc "$description" \
|
|
38
|
+
--arg err "$error_summary" \
|
|
39
|
+
'{timestamp: $ts, agent_type: $agent, model: $model, outcome: $outcome, description: $desc, error_summary: $err}')
|
|
40
|
+
|
|
41
|
+
echo "$entry" >> "$OUTCOME_FILE"
|
|
42
|
+
|
|
43
|
+
# Ring buffer: keep last 50 entries
|
|
44
|
+
if [ -f "$OUTCOME_FILE" ]; then
|
|
45
|
+
line_count=$(wc -l < "$OUTCOME_FILE")
|
|
46
|
+
if [ "$line_count" -gt 50 ]; then
|
|
47
|
+
tail -50 "$OUTCOME_FILE" > "${OUTCOME_FILE}.tmp"
|
|
48
|
+
mv "${OUTCOME_FILE}.tmp" "$OUTCOME_FILE"
|
|
49
|
+
fi
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# Report failures to stderr
|
|
53
|
+
if [ "$outcome" = "failure" ]; then
|
|
54
|
+
echo "" >&2
|
|
55
|
+
echo "--- [Task Outcome] FAILURE: ${agent_type}:${model} ---" >&2
|
|
56
|
+
echo " ${description}" >&2
|
|
57
|
+
echo " Error: $(echo "$error_summary" | head -c 100)" >&2
|
|
58
|
+
echo "-----------------------------------------------" >&2
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# Pass through
|
|
62
|
+
echo "$input"
|
|
63
|
+
exit 0
|
|
@@ -26,8 +26,22 @@ source: # For external agents
|
|
|
26
26
|
origin: github | npm
|
|
27
27
|
url: https://...
|
|
28
28
|
version: 1.0.0
|
|
29
|
+
escalation: # Model escalation policy (optional)
|
|
30
|
+
enabled: true # Enable auto-escalation advisory
|
|
31
|
+
path: haiku → sonnet → opus # Escalation sequence
|
|
32
|
+
threshold: 2 # Failures before advisory
|
|
29
33
|
```
|
|
30
34
|
|
|
35
|
+
### Escalation Policy
|
|
36
|
+
|
|
37
|
+
When `escalation.enabled: true`, the model-escalation hooks will track outcomes for this agent type and advise escalation when failures exceed the threshold. This is advisory-only — the orchestrator decides whether to accept the recommendation.
|
|
38
|
+
|
|
39
|
+
| Field | Default | Description |
|
|
40
|
+
|-------|---------|-------------|
|
|
41
|
+
| `enabled` | false | Enable escalation tracking for this agent |
|
|
42
|
+
| `path` | haiku → sonnet → opus | Model upgrade sequence |
|
|
43
|
+
| `threshold` | 2 | Failure count before escalation advisory |
|
|
44
|
+
|
|
31
45
|
## Memory Scopes
|
|
32
46
|
|
|
33
47
|
| Scope | Location | Git Tracked |
|
|
@@ -48,6 +48,28 @@ BEFORE using Task tool for 2+ agent tasks, this check is **ENFORCED**:
|
|
|
48
48
|
╚══════════════════════════════════════════════════════════════════╝
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
### Spawn Completeness Check (MANDATORY)
|
|
52
|
+
|
|
53
|
+
When spawning Agent Teams members:
|
|
54
|
+
|
|
55
|
+
**ALL members MUST be spawned in a SINGLE message.** Partial spawning is a VIOLATION of both R018 and R009.
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
╔══════════════════════════════════════════════════════════════════╗
|
|
59
|
+
║ BEFORE SPAWNING TEAM MEMBERS: ║
|
|
60
|
+
║ ║
|
|
61
|
+
║ 1. How many members does this team need? N = ___ ║
|
|
62
|
+
║ 2. Am I spawning ALL N members in THIS message? ║
|
|
63
|
+
║ YES → Good. Continue. ║
|
|
64
|
+
║ NO → STOP. This is a VIOLATION. ║
|
|
65
|
+
║ All N members MUST be in the same message. ║
|
|
66
|
+
║ ║
|
|
67
|
+
║ Partial spawn (e.g., 1/3) = VIOLATION ║
|
|
68
|
+
║ Sequential spawn (one per message) = VIOLATION ║
|
|
69
|
+
║ All at once in single message = CORRECT ║
|
|
70
|
+
╚══════════════════════════════════════════════════════════════════╝
|
|
71
|
+
```
|
|
72
|
+
|
|
51
73
|
## Common Violations
|
|
52
74
|
|
|
53
75
|
```
|
|
@@ -87,6 +109,19 @@ BEFORE using Task tool for 2+ agent tasks, this check is **ENFORCED**:
|
|
|
87
109
|
Task(frontend-dev) + Task(backend-dev) → team members
|
|
88
110
|
Shared TaskList for interface contracts
|
|
89
111
|
SendMessage for API schema coordination
|
|
112
|
+
|
|
113
|
+
❌ WRONG: Spawning team members one at a time
|
|
114
|
+
TeamCreate("research-team")
|
|
115
|
+
Message 1: Task(researcher-1) → Analysis 1 (only 1/3 spawned)
|
|
116
|
+
Message 2: Task(researcher-2) → Analysis 2 (late spawn)
|
|
117
|
+
Message 3: Task(researcher-3) → Analysis 3 (late spawn)
|
|
118
|
+
|
|
119
|
+
✓ CORRECT: All members in a single message
|
|
120
|
+
TeamCreate("research-team")
|
|
121
|
+
Single message:
|
|
122
|
+
Task(researcher-1) → Analysis 1 ┐
|
|
123
|
+
Task(researcher-2) → Analysis 2 ├─ ALL spawned together
|
|
124
|
+
Task(researcher-3) → Analysis 3 ┘
|
|
90
125
|
```
|
|
91
126
|
|
|
92
127
|
## Cost Guidelines
|
|
@@ -39,6 +39,7 @@ Before writing/editing multiple files:
|
|
|
39
39
|
2. Using Write/Edit sequentially for 2+ files? → STOP, parallelize
|
|
40
40
|
3. Specialized agent available? → Use it (not general-purpose)
|
|
41
41
|
4. Agent Teams available + 3+ agents or review cycle? → YES: use Agent Teams instead of Task
|
|
42
|
+
5. Agent Teams members? → ALL members MUST spawn in a single message (no partial spawning)
|
|
42
43
|
|
|
43
44
|
### Common Violations to Avoid
|
|
44
45
|
|
|
@@ -79,6 +80,18 @@ Before writing/editing multiple files:
|
|
|
79
80
|
Task(lang-kotlin-expert → usecase queries) ├─ All spawned together
|
|
80
81
|
Task(be-springboot-expert → persistence) │
|
|
81
82
|
Task(be-springboot-expert → security) ┘
|
|
83
|
+
|
|
84
|
+
❌ WRONG: Agent Teams partial spawn (1 of N members)
|
|
85
|
+
TeamCreate("feature-team")
|
|
86
|
+
Message 1: Task(member-1) ← only 1/3 spawned, VIOLATION
|
|
87
|
+
Message 2: Task(member-2) ← sequential, VIOLATION
|
|
88
|
+
Message 3: Task(member-3) ← sequential, VIOLATION
|
|
89
|
+
|
|
90
|
+
✓ CORRECT: All Agent Teams members in single message
|
|
91
|
+
TeamCreate("feature-team")
|
|
92
|
+
Task(member-1) ┐
|
|
93
|
+
Task(member-2) ├─ Single message, all at once
|
|
94
|
+
Task(member-3) ┘
|
|
82
95
|
```
|
|
83
96
|
|
|
84
97
|
## Execution Rules
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: model-escalation
|
|
3
|
+
description: Advisory model escalation based on task outcome tracking
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Model Escalation Skill
|
|
7
|
+
|
|
8
|
+
Tracks task outcomes and advises model upgrades when failures are detected. **Advisory-only** — the orchestrator makes the final decision (R010).
|
|
9
|
+
|
|
10
|
+
## Escalation Path
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
haiku → sonnet → opus
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Trigger Conditions
|
|
17
|
+
|
|
18
|
+
| Condition | Action |
|
|
19
|
+
|-----------|--------|
|
|
20
|
+
| 2+ failures with same model for same agent type | Advise escalation |
|
|
21
|
+
| 3+ consecutive failures across any agent type | Advise global escalation |
|
|
22
|
+
| Sustained success after escalation | Advise de-escalation |
|
|
23
|
+
|
|
24
|
+
## Thresholds
|
|
25
|
+
|
|
26
|
+
| Parameter | Default | Description |
|
|
27
|
+
|-----------|---------|-------------|
|
|
28
|
+
| `failure_threshold` | 2 | Failures before escalation advisory |
|
|
29
|
+
| `consecutive_threshold` | 3 | Consecutive failures for global advisory |
|
|
30
|
+
| `cooldown_tasks` | 5 | Successes before de-escalation advisory |
|
|
31
|
+
|
|
32
|
+
## Cost Guard
|
|
33
|
+
|
|
34
|
+
- Advisory includes estimated cost multiplier
|
|
35
|
+
- De-escalation suggested after sustained success at higher tier
|
|
36
|
+
- Cost tracked per session via PPID-scoped temp file
|
|
37
|
+
|
|
38
|
+
## Architecture
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
PostToolUse (Task) → task-outcome-recorder.sh
|
|
42
|
+
Records: agent_type, model, success/failure, error_summary
|
|
43
|
+
Storage: /tmp/.claude-task-outcomes-$PPID (JSON lines, max 50)
|
|
44
|
+
|
|
45
|
+
PreToolUse (Task) → model-escalation-advisor.sh
|
|
46
|
+
Reads outcomes → counts failures → advises escalation via stderr
|
|
47
|
+
Advisory only — never blocks, never modifies tool input
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Advisory Format
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
--- [Model Escalation Advisory] ---
|
|
54
|
+
Agent type: {agent_type}
|
|
55
|
+
Current model: {current_model}
|
|
56
|
+
Recent failures: {count}/{threshold}
|
|
57
|
+
⚡ Recommended: Escalate to {next_model}
|
|
58
|
+
Cost impact: {multiplier} per task
|
|
59
|
+
---
|
|
60
|
+
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stuck-recovery
|
|
3
|
+
description: Detect stuck loops and advise recovery strategies
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Stuck Recovery Skill
|
|
7
|
+
|
|
8
|
+
Detects when tasks are stuck in repetitive failure loops and advises recovery strategies. **Advisory-only** — the orchestrator decides the action (R010).
|
|
9
|
+
|
|
10
|
+
## Detection Signals
|
|
11
|
+
|
|
12
|
+
| Signal | Pattern | Threshold |
|
|
13
|
+
|--------|---------|-----------|
|
|
14
|
+
| Repeated error | Same error message appears 3+ times | 3 occurrences |
|
|
15
|
+
| Edit loop | Same file edited 3+ times in sequence | 3 edits |
|
|
16
|
+
| Agent retry | Same agent_type fails 3+ times consecutively | 3 failures |
|
|
17
|
+
| Tool loop | Same tool called 5+ times with similar input | 5 calls |
|
|
18
|
+
|
|
19
|
+
## Recovery Strategies
|
|
20
|
+
|
|
21
|
+
| Strategy | When | Action |
|
|
22
|
+
|----------|------|--------|
|
|
23
|
+
| Fresh context | Repeated same error | Suggest rephrasing the task |
|
|
24
|
+
| Model escalation | Agent retry loop | Trigger model-escalation advisory |
|
|
25
|
+
| Alternative approach | Edit loop detected | Suggest different file/method |
|
|
26
|
+
| Human intervention | All automated strategies exhausted | Ask user for guidance |
|
|
27
|
+
|
|
28
|
+
## Architecture
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
PostToolUse (Edit, Write, Bash, Task) → stuck-detector.sh
|
|
32
|
+
Tracks: tool_name, file_path, error_hash, agent_type
|
|
33
|
+
Storage: /tmp/.claude-tool-history-$PPID (JSON lines, max 100)
|
|
34
|
+
Detection: sliding window pattern matching
|
|
35
|
+
Output: stderr advisory when loop detected
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Advisory Format
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
--- [Stuck Detection] Loop detected ---
|
|
42
|
+
Signal: {signal_type}
|
|
43
|
+
Pattern: {description}
|
|
44
|
+
Occurrences: {count}/{threshold}
|
|
45
|
+
💡 Recovery: {suggested_strategy}
|
|
46
|
+
---
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Integration
|
|
50
|
+
|
|
51
|
+
- Complements model-escalation skill (escalation is one recovery strategy)
|
|
52
|
+
- Respects R010 (advisory only, orchestrator decides)
|
|
53
|
+
- Uses same PPID-scoped temp file pattern as other hooks
|
|
54
|
+
- Works with task-outcome-recorder.sh data when available
|