@arthai/agents 1.0.4 → 1.0.6

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 (131) hide show
  1. package/README.md +55 -3
  2. package/VERSION +1 -1
  3. package/agents/troubleshooter.md +132 -0
  4. package/bin/cli.js +366 -0
  5. package/bundles/canvas.json +1 -1
  6. package/bundles/compass.json +1 -1
  7. package/bundles/counsel.json +1 -0
  8. package/bundles/cruise.json +1 -1
  9. package/bundles/forge.json +12 -1
  10. package/bundles/prism.json +1 -0
  11. package/bundles/scalpel.json +5 -2
  12. package/bundles/sentinel.json +8 -2
  13. package/bundles/shield.json +1 -0
  14. package/bundles/spark.json +1 -0
  15. package/compiler.sh +14 -0
  16. package/dist/plugins/canvas/.claude-plugin/plugin.json +1 -1
  17. package/dist/plugins/canvas/VERSION +1 -0
  18. package/dist/plugins/canvas/commands/planning.md +100 -11
  19. package/dist/plugins/canvas/hooks/hooks.json +16 -0
  20. package/dist/plugins/canvas/hooks/project-setup.sh +109 -0
  21. package/dist/plugins/canvas/templates/CLAUDE.md.managed-block +123 -0
  22. package/dist/plugins/canvas/templates/CLAUDE.md.template +111 -0
  23. package/dist/plugins/compass/.claude-plugin/plugin.json +1 -1
  24. package/dist/plugins/compass/VERSION +1 -0
  25. package/dist/plugins/compass/commands/planning.md +100 -11
  26. package/dist/plugins/compass/hooks/hooks.json +16 -0
  27. package/dist/plugins/compass/hooks/project-setup.sh +109 -0
  28. package/dist/plugins/compass/templates/CLAUDE.md.managed-block +123 -0
  29. package/dist/plugins/compass/templates/CLAUDE.md.template +111 -0
  30. package/dist/plugins/counsel/.claude-plugin/plugin.json +1 -1
  31. package/dist/plugins/counsel/VERSION +1 -0
  32. package/dist/plugins/counsel/hooks/hooks.json +10 -0
  33. package/dist/plugins/counsel/hooks/project-setup.sh +109 -0
  34. package/dist/plugins/counsel/templates/CLAUDE.md.managed-block +123 -0
  35. package/dist/plugins/counsel/templates/CLAUDE.md.template +111 -0
  36. package/dist/plugins/cruise/.claude-plugin/plugin.json +1 -1
  37. package/dist/plugins/cruise/VERSION +1 -0
  38. package/dist/plugins/cruise/hooks/hooks.json +16 -0
  39. package/dist/plugins/cruise/hooks/project-setup.sh +109 -0
  40. package/dist/plugins/cruise/templates/CLAUDE.md.managed-block +123 -0
  41. package/dist/plugins/cruise/templates/CLAUDE.md.template +111 -0
  42. package/dist/plugins/forge/.claude-plugin/plugin.json +1 -1
  43. package/dist/plugins/forge/VERSION +1 -0
  44. package/dist/plugins/forge/agents/troubleshooter.md +132 -0
  45. package/dist/plugins/forge/commands/implement.md +99 -1
  46. package/dist/plugins/forge/commands/planning.md +100 -11
  47. package/dist/plugins/forge/hooks/escalation-guard.sh +177 -0
  48. package/dist/plugins/forge/hooks/hooks.json +22 -0
  49. package/dist/plugins/forge/hooks/project-setup.sh +109 -0
  50. package/dist/plugins/forge/templates/CLAUDE.md.managed-block +123 -0
  51. package/dist/plugins/forge/templates/CLAUDE.md.template +111 -0
  52. package/dist/plugins/prime/.claude-plugin/plugin.json +1 -1
  53. package/dist/plugins/prime/VERSION +1 -0
  54. package/dist/plugins/prime/agents/troubleshooter.md +132 -0
  55. package/dist/plugins/prime/commands/calibrate.md +20 -0
  56. package/dist/plugins/prime/commands/ci-fix.md +36 -0
  57. package/dist/plugins/prime/commands/fix.md +23 -0
  58. package/dist/plugins/prime/commands/implement.md +99 -1
  59. package/dist/plugins/prime/commands/planning.md +100 -11
  60. package/dist/plugins/prime/commands/qa-incident.md +54 -0
  61. package/dist/plugins/prime/commands/restart.md +186 -30
  62. package/dist/plugins/prime/hooks/escalation-guard.sh +177 -0
  63. package/dist/plugins/prime/hooks/hooks.json +60 -0
  64. package/dist/plugins/prime/hooks/post-config-change-restart-reminder.sh +86 -0
  65. package/dist/plugins/prime/hooks/post-server-crash-watch.sh +120 -0
  66. package/dist/plugins/prime/hooks/pre-server-port-guard.sh +110 -0
  67. package/dist/plugins/prime/hooks/project-setup.sh +109 -0
  68. package/dist/plugins/prime/hooks/sync-agents.sh +99 -12
  69. package/dist/plugins/prime/templates/CLAUDE.md.managed-block +123 -0
  70. package/dist/plugins/prime/templates/CLAUDE.md.template +111 -0
  71. package/dist/plugins/prism/.claude-plugin/plugin.json +1 -1
  72. package/dist/plugins/prism/VERSION +1 -0
  73. package/dist/plugins/prism/commands/qa-incident.md +54 -0
  74. package/dist/plugins/prism/hooks/hooks.json +12 -0
  75. package/dist/plugins/prism/hooks/project-setup.sh +109 -0
  76. package/dist/plugins/prism/templates/CLAUDE.md.managed-block +123 -0
  77. package/dist/plugins/prism/templates/CLAUDE.md.template +111 -0
  78. package/dist/plugins/scalpel/.claude-plugin/plugin.json +1 -1
  79. package/dist/plugins/scalpel/VERSION +1 -0
  80. package/dist/plugins/scalpel/agents/troubleshooter.md +132 -0
  81. package/dist/plugins/scalpel/commands/ci-fix.md +36 -0
  82. package/dist/plugins/scalpel/commands/fix.md +23 -0
  83. package/dist/plugins/scalpel/hooks/escalation-guard.sh +177 -0
  84. package/dist/plugins/scalpel/hooks/hooks.json +24 -0
  85. package/dist/plugins/scalpel/hooks/project-setup.sh +109 -0
  86. package/dist/plugins/scalpel/templates/CLAUDE.md.managed-block +123 -0
  87. package/dist/plugins/scalpel/templates/CLAUDE.md.template +111 -0
  88. package/dist/plugins/sentinel/.claude-plugin/plugin.json +1 -1
  89. package/dist/plugins/sentinel/VERSION +1 -0
  90. package/dist/plugins/sentinel/agents/troubleshooter.md +132 -0
  91. package/dist/plugins/sentinel/commands/restart.md +186 -30
  92. package/dist/plugins/sentinel/hooks/escalation-guard.sh +177 -0
  93. package/dist/plugins/sentinel/hooks/hooks.json +64 -0
  94. package/dist/plugins/sentinel/hooks/post-config-change-restart-reminder.sh +86 -0
  95. package/dist/plugins/sentinel/hooks/post-server-crash-watch.sh +120 -0
  96. package/dist/plugins/sentinel/hooks/pre-server-port-guard.sh +110 -0
  97. package/dist/plugins/sentinel/hooks/project-setup.sh +109 -0
  98. package/dist/plugins/sentinel/templates/CLAUDE.md.managed-block +123 -0
  99. package/dist/plugins/sentinel/templates/CLAUDE.md.template +111 -0
  100. package/dist/plugins/shield/.claude-plugin/plugin.json +1 -1
  101. package/dist/plugins/shield/VERSION +1 -0
  102. package/dist/plugins/shield/hooks/hooks.json +22 -12
  103. package/dist/plugins/shield/hooks/project-setup.sh +109 -0
  104. package/dist/plugins/shield/templates/CLAUDE.md.managed-block +123 -0
  105. package/dist/plugins/shield/templates/CLAUDE.md.template +111 -0
  106. package/dist/plugins/spark/.claude-plugin/plugin.json +1 -1
  107. package/dist/plugins/spark/VERSION +1 -0
  108. package/dist/plugins/spark/commands/calibrate.md +20 -0
  109. package/dist/plugins/spark/hooks/hooks.json +10 -0
  110. package/dist/plugins/spark/hooks/project-setup.sh +109 -0
  111. package/dist/plugins/spark/templates/CLAUDE.md.managed-block +123 -0
  112. package/dist/plugins/spark/templates/CLAUDE.md.template +111 -0
  113. package/hook-defs.json +31 -0
  114. package/hooks/escalation-guard.sh +177 -0
  115. package/hooks/post-config-change-restart-reminder.sh +86 -0
  116. package/hooks/post-server-crash-watch.sh +120 -0
  117. package/hooks/pre-server-port-guard.sh +110 -0
  118. package/hooks/project-setup.sh +109 -0
  119. package/hooks/sync-agents.sh +99 -12
  120. package/install.sh +2 -2
  121. package/package.json +1 -1
  122. package/portable.manifest +7 -1
  123. package/skills/calibrate/SKILL.md +20 -0
  124. package/skills/ci-fix/SKILL.md +36 -0
  125. package/skills/fix/SKILL.md +23 -0
  126. package/skills/implement/SKILL.md +99 -1
  127. package/skills/license/SKILL.md +159 -0
  128. package/skills/planning/SKILL.md +100 -11
  129. package/skills/publish/SKILL.md +3 -0
  130. package/skills/qa-incident/SKILL.md +54 -0
  131. package/skills/restart/SKILL.md +187 -31
@@ -0,0 +1,109 @@
1
+ #!/bin/bash
2
+ # hooks/project-setup.sh — SessionStart hook: first-run project setup for marketplace installs.
3
+ #
4
+ # Runs on every SessionStart. Checks for marker file .claude/.toolkit-setup-done.
5
+ # If missing (or version is stale): creates CLAUDE.md from template, injects managed block,
6
+ # updates .gitignore with toolkit markers.
7
+ #
8
+ # Templates are read from ${CLAUDE_PLUGIN_ROOT}/templates/ (bundled with the plugin).
9
+
10
+ set -euo pipefail
11
+
12
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
13
+ PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-}"
14
+ MARKER_FILE="$PROJECT_DIR/.claude/.toolkit-setup-done"
15
+
16
+ # Exit silently if CLAUDE_PLUGIN_ROOT is not set (not running from a plugin context)
17
+ if [ -z "$PLUGIN_ROOT" ]; then
18
+ exit 0
19
+ fi
20
+
21
+ TEMPLATES_DIR="$PLUGIN_ROOT/templates"
22
+ TEMPLATE_CLAUDE="$TEMPLATES_DIR/CLAUDE.md.template"
23
+ TEMPLATE_BLOCK="$TEMPLATES_DIR/CLAUDE.md.managed-block"
24
+
25
+ # Exit silently if templates are not bundled
26
+ if [ ! -f "$TEMPLATE_CLAUDE" ] || [ ! -f "$TEMPLATE_BLOCK" ]; then
27
+ exit 0
28
+ fi
29
+
30
+ # Read toolkit version from VERSION file (bundled alongside plugin)
31
+ TOOLKIT_VERSION="0.0.0"
32
+ if [ -f "$PLUGIN_ROOT/VERSION" ]; then
33
+ TOOLKIT_VERSION=$(cat "$PLUGIN_ROOT/VERSION" 2>/dev/null | tr -d '[:space:]' || echo "0.0.0")
34
+ fi
35
+
36
+ MANAGED_START="<!-- >>> claude-agents toolkit (DO NOT EDIT THIS BLOCK) >>> -->"
37
+ MANAGED_END="<!-- <<< claude-agents toolkit <<< -->"
38
+ GITIGNORE_START="# >>> claude-agents managed (DO NOT EDIT THIS BLOCK) >>>"
39
+
40
+ # Check marker file — skip if current version is already set up
41
+ if [ -f "$MARKER_FILE" ]; then
42
+ STORED_VERSION=$(cat "$MARKER_FILE" 2>/dev/null | tr -d '[:space:]' || echo "")
43
+ if [ "$STORED_VERSION" = "$TOOLKIT_VERSION" ]; then
44
+ exit 0
45
+ fi
46
+ fi
47
+
48
+ CLAUDE_MD="$PROJECT_DIR/CLAUDE.md"
49
+ GITIGNORE="$PROJECT_DIR/.gitignore"
50
+
51
+ # 1. Create CLAUDE.md from template if it doesn't exist (never overwrite existing)
52
+ if [ ! -f "$CLAUDE_MD" ]; then
53
+ PROJECT_NAME=$(basename "$PROJECT_DIR")
54
+ sed "s/{{PROJECT_NAME}}/$PROJECT_NAME/g" "$TEMPLATE_CLAUDE" > "$CLAUDE_MD"
55
+ fi
56
+
57
+ # 2. Inject managed block into CLAUDE.md if missing, or update if version is stale
58
+ if [ -f "$CLAUDE_MD" ]; then
59
+ BLOCK_CONTENT=$(cat "$TEMPLATE_BLOCK")
60
+ NEW_BLOCK=$(printf '%s\n<!-- version: %s -->\n%s\n%s' \
61
+ "$MANAGED_START" "$TOOLKIT_VERSION" "$BLOCK_CONTENT" "$MANAGED_END")
62
+
63
+ if ! grep -qF "$MANAGED_START" "$CLAUDE_MD"; then
64
+ # Block missing — append it
65
+ printf '\n\n%s\n' "$NEW_BLOCK" >> "$CLAUDE_MD"
66
+ else
67
+ # Block exists — update if version changed
68
+ EXISTING_VERSION=$(grep -o '<!-- version: [^>]* -->' "$CLAUDE_MD" 2>/dev/null | head -1 | sed 's/<!-- version: //;s/ -->//' | tr -d '[:space:]' || echo "")
69
+ if [ "$EXISTING_VERSION" != "$TOOLKIT_VERSION" ]; then
70
+ # Replace block contents between markers
71
+ tmp=$(mktemp)
72
+ in_block=false
73
+ wrote_block=false
74
+ while IFS= read -r line; do
75
+ if echo "$line" | grep -qF "$MANAGED_START"; then
76
+ in_block=true
77
+ printf '%s\n' "$NEW_BLOCK" >> "$tmp"
78
+ wrote_block=true
79
+ continue
80
+ fi
81
+ if echo "$line" | grep -qF "$MANAGED_END"; then
82
+ in_block=false
83
+ continue
84
+ fi
85
+ if ! $in_block; then
86
+ echo "$line" >> "$tmp"
87
+ fi
88
+ done < "$CLAUDE_MD"
89
+ mv "$tmp" "$CLAUDE_MD"
90
+ fi
91
+ fi
92
+ fi
93
+
94
+ # 3. Update .gitignore with toolkit marker block if missing
95
+ if [ ! -f "$GITIGNORE" ] || ! grep -qF "$GITIGNORE_START" "$GITIGNORE" 2>/dev/null; then
96
+ GITIGNORE_BLOCK=$(printf '%s\n.claude/.toolkit-last-seen-sha\n.claude/.toolkit-setup-done\n.claude/.claude-agents.conf\n%s' \
97
+ "$GITIGNORE_START" "# <<< claude-agents managed <<<")
98
+ if [ ! -f "$GITIGNORE" ]; then
99
+ printf '%s\n' "$GITIGNORE_BLOCK" > "$GITIGNORE"
100
+ else
101
+ printf '\n\n%s\n' "$GITIGNORE_BLOCK" >> "$GITIGNORE"
102
+ fi
103
+ fi
104
+
105
+ # 4. Write marker file with current version
106
+ mkdir -p "$PROJECT_DIR/.claude"
107
+ printf '%s\n' "$TOOLKIT_VERSION" > "$MARKER_FILE"
108
+
109
+ exit 0
@@ -22,8 +22,9 @@ if [ ! -d "$AGENTS_DIR/.git" ]; then
22
22
  exit 0
23
23
  fi
24
24
 
25
- # Exit silently if no license
26
- if [ ! -f "$LICENSE_FILE" ]; then
25
+ # Exit silently if no license found in any path
26
+ ARTHAI_LICENSE_PATH="$REAL_HOME/.arthai/license"
27
+ if [ ! -f "$LICENSE_FILE" ] && [ ! -f "$ARTHAI_LICENSE_PATH" ] && [ -z "${ARTHAI_LICENSE_KEY:-}" ]; then
27
28
  exit 0
28
29
  fi
29
30
 
@@ -108,6 +109,27 @@ fi
108
109
 
109
110
  # --- Step 2: Check license (with revocation enforcement) ---
110
111
  NOW=$(date +%s)
112
+ WORKER_URL="https://license-worker.muddassar-shaikh.workers.dev"
113
+
114
+ # Resolve license key: ~/.claude-agents/.license takes priority (existing clone-install users),
115
+ # fall back to ~/.arthai/license (npm activate users).
116
+ ARTHAI_LICENSE_KEY_VALUE="${ARTHAI_LICENSE_KEY:-}"
117
+ RESOLVED_KEY=""
118
+ if [ -n "$ARTHAI_LICENSE_KEY_VALUE" ]; then
119
+ RESOLVED_KEY="$ARTHAI_LICENSE_KEY_VALUE"
120
+ elif [ -f "$LICENSE_FILE" ]; then
121
+ RESOLVED_KEY=$(cat "$LICENSE_FILE" 2>/dev/null | tr -d '[:space:]' || echo "")
122
+ elif [ -f "$REAL_HOME/.arthai/license" ]; then
123
+ RESOLVED_KEY=$(cat "$REAL_HOME/.arthai/license" 2>/dev/null | tr -d '[:space:]' || echo "")
124
+ fi
125
+
126
+ # Validate key format before using it in any JSON payload — prevents JSON injection
127
+ # via a crafted key value in the env var or license file.
128
+ KEY_FORMAT='^ARTH-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$'
129
+ if [ -n "$RESOLVED_KEY" ] && ! echo "$RESOLVED_KEY" | grep -qE "$KEY_FORMAT"; then
130
+ # Key has invalid format — don't use it for Worker call or local check
131
+ RESOLVED_KEY=""
132
+ fi
111
133
 
112
134
  # Detect if authorized-keys.txt changed in the pull — force re-check if so
113
135
  AK_HASH_FILE="$AGENTS_DIR/.ak-hash"
@@ -128,6 +150,49 @@ fi
128
150
  # Store current hash for next comparison
129
151
  [ -n "$AK_CURRENT_HASH" ] && echo "$AK_CURRENT_HASH" > "$AK_HASH_FILE" 2>/dev/null || true
130
152
 
153
+ # validate_with_worker: call Worker /validate with the resolved key.
154
+ # Sets WORKER_RESULT: "valid", "invalid" (definitive), or "network_error".
155
+ validate_with_worker() {
156
+ local key="$1"
157
+ if [ -z "$key" ]; then
158
+ WORKER_RESULT="invalid"
159
+ return
160
+ fi
161
+
162
+ local payload="{\"key\":\"$key\"}"
163
+ local response
164
+ local curl_exit
165
+
166
+ # Pass payload via stdin (--data @-) so the key is not visible in the process list
167
+ response=$(printf '%s' "$payload" | curl \
168
+ --silent \
169
+ --max-time 10 \
170
+ --connect-timeout 5 \
171
+ --request POST \
172
+ --header "Content-Type: application/json" \
173
+ --data "@-" \
174
+ "$WORKER_URL/validate" 2>/dev/null)
175
+ curl_exit=$?
176
+
177
+ if [ $curl_exit -ne 0 ] || [ -z "$response" ]; then
178
+ WORKER_RESULT="network_error"
179
+ return
180
+ fi
181
+
182
+ # Parse "valid" field from JSON — minimal grep-based parse, no jq dependency
183
+ local valid_field
184
+ valid_field=$(echo "$response" | grep -o '"valid"[[:space:]]*:[[:space:]]*[a-z]*' | head -1 | grep -o '[a-z]*$')
185
+
186
+ if [ "$valid_field" = "true" ]; then
187
+ WORKER_RESULT="valid"
188
+ elif [ "$valid_field" = "false" ]; then
189
+ WORKER_RESULT="invalid"
190
+ else
191
+ # Unexpected response format — treat as network error (fail safe)
192
+ WORKER_RESULT="network_error"
193
+ fi
194
+ }
195
+
131
196
  LICENSE_VALID=true
132
197
  if [ -f "$LICENSE_CACHE" ]; then
133
198
  LAST_CHECK=$(cat "$LICENSE_CACHE" 2>/dev/null || echo "0")
@@ -136,19 +201,41 @@ if [ -f "$LICENSE_CACHE" ]; then
136
201
  # Cache is fresh, skip validation
137
202
  :
138
203
  else
139
- # Re-validate
140
- if ! "$AGENTS_DIR/install.sh" --check-license-only 2>/dev/null; then
204
+ # Re-validate: try Worker first, fall back to local only on network error
205
+ validate_with_worker "$RESOLVED_KEY"
206
+ if [ "$WORKER_RESULT" = "valid" ]; then
207
+ echo "$NOW" > "$LICENSE_CACHE"
208
+ elif [ "$WORKER_RESULT" = "invalid" ]; then
209
+ # Worker says definitively invalid — no local fallback, clear cache
210
+ rm -f "$LICENSE_CACHE" 2>/dev/null || true
141
211
  LICENSE_VALID=false
142
212
  else
143
- echo "$NOW" > "$LICENSE_CACHE"
213
+ # Network error — fall back to local authorized-keys.txt check
214
+ echo "License server unavailable. Retrying with local validation..." >&2
215
+ if ! "$AGENTS_DIR/install.sh" --check-license-only 2>/dev/null; then
216
+ LICENSE_VALID=false
217
+ else
218
+ echo "$NOW" > "$LICENSE_CACHE"
219
+ fi
144
220
  fi
145
221
  fi
146
222
  else
147
- # First check (or cache was invalidated by AK change)
148
- if ! "$AGENTS_DIR/install.sh" --check-license-only 2>/dev/null; then
223
+ # First check (or cache was invalidated by AK change): try Worker first
224
+ validate_with_worker "$RESOLVED_KEY"
225
+ if [ "$WORKER_RESULT" = "valid" ]; then
226
+ echo "$NOW" > "$LICENSE_CACHE"
227
+ elif [ "$WORKER_RESULT" = "invalid" ]; then
228
+ # Worker says definitively invalid — no local fallback, ensure cache stays clear
229
+ rm -f "$LICENSE_CACHE" 2>/dev/null || true
149
230
  LICENSE_VALID=false
150
231
  else
151
- echo "$NOW" > "$LICENSE_CACHE"
232
+ # Network error — fall back to local authorized-keys.txt check
233
+ echo "License server unavailable. Retrying with local validation..." >&2
234
+ if ! "$AGENTS_DIR/install.sh" --check-license-only 2>/dev/null; then
235
+ LICENSE_VALID=false
236
+ else
237
+ echo "$NOW" > "$LICENSE_CACHE"
238
+ fi
152
239
  fi
153
240
  fi
154
241
 
@@ -182,12 +269,12 @@ if ! $LICENSE_VALID; then
182
269
 
183
270
  # Remove CLAUDE.md managed block
184
271
  CLAUDEMD="$PROJECT_DIR/CLAUDE.md"
185
- if [ -f "$CLAUDEMD" ] && grep -qF "<!-- >>> claude-agents toolkit -->" "$CLAUDEMD" 2>/dev/null; then
272
+ if [ -f "$CLAUDEMD" ] && grep -qF "<!-- >>> claude-agents toolkit (DO NOT EDIT THIS BLOCK) >>> -->" "$CLAUDEMD" 2>/dev/null; then
186
273
  tmp=$(mktemp)
187
274
  in_block=false
188
275
  skip_next_blank=false
189
276
  while IFS= read -r line; do
190
- if echo "$line" | grep -qF "<!-- >>> claude-agents toolkit -->"; then
277
+ if echo "$line" | grep -qF "<!-- >>> claude-agents toolkit (DO NOT EDIT THIS BLOCK) >>> -->"; then
191
278
  in_block=true
192
279
  continue
193
280
  fi
@@ -218,8 +305,8 @@ if ! $LICENSE_VALID; then
218
305
  rm -f "$LICENSE_CACHE" 2>/dev/null || true
219
306
  fi
220
307
 
221
- echo " License revoked. Toolkit has been disabled for this project."
222
- echo " Contact support to renew your license."
308
+ echo "Invalid license key. Toolkit has been disabled for this project."
309
+ echo " Check your key or get one at arthai.dev/pricing"
223
310
  exit 0
224
311
  fi
225
312
 
package/install.sh CHANGED
@@ -114,7 +114,7 @@ get_category_items() {
114
114
  echo "agents/architect.md agents/code-reviewer.md agents/design-studio-create.md agents/design-studio-critique.md agents/design-studio-think.md agents/gtm-expert.md agents/product-manager.md agents/stakeholder-reporter.md agents/meeting-prep.md agents/content-strategist.md agents/user-researcher.md agents/competitive-analyst.md"
115
115
  ;;
116
116
  development)
117
- echo "agents/frontend.md agents/python-backend.md agents/ops.md skills/planning skills/implement skills/fix skills/pr skills/precheck skills/review-pr skills/issue"
117
+ echo "agents/frontend.md agents/python-backend.md agents/ops.md agents/troubleshooter.md skills/planning skills/implement skills/fix skills/pr skills/precheck skills/review-pr skills/issue"
118
118
  ;;
119
119
  quality)
120
120
  echo "agents/qa.md agents/qa-e2e.md agents/qa-challenger.md agents/qa-test-promoter.md agents/qa-baseline-updater.md agents/qa-domain.md skills/qa skills/ci-fix skills/qa-incident skills/qa-learn"
@@ -126,7 +126,7 @@ get_category_items() {
126
126
  echo "hooks/triage-router.sh hooks/session-end.sh"
127
127
  ;;
128
128
  guardrails)
129
- echo "hooks/session-bootstrap.sh hooks/pre-bash-guard.sh hooks/pre-task-context.sh hooks/pre-edit-guard.sh hooks/post-test-summary.sh hooks/post-edit-lint.sh hooks/post-deploy-health.sh hooks/post-diff-test-compare.sh hooks/post-git-state.sh hooks/post-merge-cleanup.sh skills/onboard skills/welcome skills/share skills/templates skills/wizard skills/autopilot skills/continue"
129
+ echo "hooks/session-bootstrap.sh hooks/pre-bash-guard.sh hooks/pre-task-context.sh hooks/pre-edit-guard.sh hooks/post-test-summary.sh hooks/post-edit-lint.sh hooks/post-deploy-health.sh hooks/post-diff-test-compare.sh hooks/post-git-state.sh hooks/post-merge-cleanup.sh hooks/escalation-guard.sh hooks/project-setup.sh hooks/pre-server-port-guard.sh hooks/post-config-change-restart-reminder.sh hooks/post-server-crash-watch.sh skills/onboard skills/welcome skills/share skills/templates skills/wizard skills/autopilot skills/continue"
130
130
  ;;
131
131
  railway)
132
132
  echo "skills/railway/central-station skills/railway/database skills/railway/deploy skills/railway/deployment skills/railway/domain skills/railway/environment skills/railway/metrics skills/railway/new skills/railway/projects skills/railway/railway-docs skills/railway/service skills/railway/status skills/railway/templates"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arthai/agents",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "AI-powered development toolkit for Claude Code — agents, skills, and hooks",
5
5
  "bin": {
6
6
  "arthai": "bin/cli.js"
package/portable.manifest CHANGED
@@ -38,6 +38,7 @@ agent agents/content-strategist.md
38
38
  agent agents/user-researcher.md
39
39
  agent agents/competitive-analyst.md
40
40
  agent agents/ai-consultant.md
41
+ agent agents/troubleshooter.md
41
42
 
42
43
  # Portable skills (30)
43
44
  skill skills/explore.md
@@ -78,7 +79,8 @@ skill-dir skills/solution-architect
78
79
  skill-dir skills/deliverable-builder
79
80
  skill-dir skills/engagement-tracker
80
81
 
81
- # Portable hooks (13)
82
+ # Portable hooks (14)
83
+ hook hooks/project-setup.sh
82
84
  hook hooks/ensure-client-dir.sh
83
85
  hook hooks/check-deliverable.sh
84
86
  hook hooks/session-summary.sh
@@ -109,4 +111,8 @@ railway-skill-dir skills/railway/railway-docs
109
111
  railway-skill-dir skills/railway/service
110
112
  railway-skill-dir skills/railway/status
111
113
  railway-skill-dir skills/railway/templates
114
+ hook hooks/escalation-guard.sh
115
+ hook hooks/pre-server-port-guard.sh
116
+ hook hooks/post-config-change-restart-reminder.sh
117
+ hook hooks/post-server-crash-watch.sh
112
118
  hook hooks/session-end.sh
@@ -74,6 +74,26 @@ This goes far deeper than `/scan`. Read **actual source code** to understand HOW
74
74
 
75
75
  #### Step 1.1: Foundation Scan
76
76
 
77
+ **Managed block check (belt-and-suspenders — runs before anything else):**
78
+
79
+ Check if CLAUDE.md has the toolkit managed block. If missing, inject it before proceeding:
80
+
81
+ ```bash
82
+ MANAGED_START="<!-- >>> claude-agents toolkit (DO NOT EDIT THIS BLOCK) >>> -->"
83
+ if [ -f "$CLAUDE_PROJECT_DIR/CLAUDE.md" ]; then
84
+ grep -qF "$MANAGED_START" "$CLAUDE_PROJECT_DIR/CLAUDE.md" || echo "MISSING_BLOCK"
85
+ fi
86
+ ```
87
+
88
+ If the managed block is missing:
89
+ 1. Read `~/.claude-agents/templates/CLAUDE.md.managed-block` (or `$CLAUDE_PROJECT_DIR/.claude/hooks/../templates/CLAUDE.md.managed-block` if installed via plugin)
90
+ 2. Inject it at the end of CLAUDE.md using the markers:
91
+ - Start: `<!-- >>> claude-agents toolkit (DO NOT EDIT THIS BLOCK) >>> -->`
92
+ - End: `<!-- <<< claude-agents toolkit <<< -->`
93
+ 3. Report: "Injected toolkit managed block into CLAUDE.md (was missing)"
94
+
95
+ This catches any install path that missed the injection — clone installs, manual setups, or projects that predate the managed block feature.
96
+
77
97
  Run `/scan` first if CLAUDE.md has `<!-- TODO -->` placeholders or doesn't exist. This populates
78
98
  the basics (tech stack, services, test commands, infrastructure). Then proceed to deep scan.
79
99
 
@@ -162,6 +162,42 @@ gh run view <FAILED_RUN_ID> --log-failed 2>&1 | tail -200
162
162
  | **Build failures** | build errors | Read error, fix import/export/config |
163
163
  | **Migration** | Alembic/Django errors | Fix migration file |
164
164
  | **Dependency** | pip/npm install failures | Fix requirements/package.json |
165
+ | **Toolkit tests** | 15/20-skill-runtime-safety, manifest-coverage | See Toolkit Test Fixes below |
166
+
167
+ #### Toolkit-Specific Test Fixes (claude-agents repo)
168
+
169
+ When CI fails on the mechanical test suite (`tests/run.sh`), these are the common failures and auto-fixes:
170
+
171
+ | Test | Failure message | Root cause | Auto-fix |
172
+ |------|----------------|-----------|----------|
173
+ | `20-skill-runtime-safety` | "regex-unsafe [brackets] in descriptions" | SKILL.md `description:` or `arguments:` field contains `[text]` | Replace `[text]` with `<text>` in the frontmatter field. Brackets break regex matching in Claude Code. |
174
+ | `20-skill-runtime-safety` | "Skills missing required frontmatter fields" | SKILL.md missing `user-invocable: true` or `arguments:` | Add missing field to the YAML frontmatter between `---` markers. Check `git show HEAD~1:path/to/SKILL.md` for the original. |
175
+ | `15-manifest-coverage` | "entries mapped to categories" | New file in `portable.manifest` not listed in any `get_category_items()` category in `install.sh` | Add the manifest entry to the appropriate category in `install.sh:get_category_items()`. |
176
+ | `15-manifest-coverage` | "Install creates all expected symlinks" | New file in `portable.manifest` but install didn't create the symlink | Usually follows from the category mapping fix above. |
177
+ | `15-manifest-coverage` | "Entry counts are consistent" | Mismatch between manifest entries and installed files | Check that new manifest entries have matching source files. |
178
+ | `19-brownfield-assessment` | "classify_file returns IDENTICAL" | Agent fixture is stale after editing an agent `.md` file | Update fixture: `cp agents/{name}.md tests/fixtures/claude-setups/poweruser/.claude/agents/` |
179
+
180
+ **Auto-fix sequence for toolkit tests:**
181
+
182
+ ```bash
183
+ # 1. Get the exact failure
184
+ gh run view <ID> --log-failed 2>&1 | grep -E "FAIL|✗" | head -5
185
+
186
+ # 2. For bracket issues — find and fix ALL bracket descriptions
187
+ grep -rn 'description:.*\[' skills/*/SKILL.md
188
+ # Replace [text] with <text> in each match
189
+
190
+ # 3. For missing frontmatter — compare against last known good
191
+ git show HEAD~1:path/to/SKILL.md | head -6
192
+ # Restore missing fields
193
+
194
+ # 4. For manifest coverage — add to install.sh categories
195
+ grep "get_category_items" install.sh
196
+ # Add new entries to the right category
197
+
198
+ # 5. Verify locally before pushing
199
+ bash tests/run.sh --suite 15,20 --scenario a
200
+ ```
165
201
 
166
202
  **Attempt escalation:**
167
203
  - Attempt 1: Apply the obvious fix (auto-fix tools, direct code fix)
@@ -478,6 +478,29 @@ Select the right agent based on which layer the bug is in:
478
478
  If `.claude/project-profile.md` exists, read it to determine the platform and pick the right agent.
479
479
  If `/calibrate` generated custom agents (e.g., `ios-developer.md`), use those for platform-specific bugs.
480
480
 
481
+ **4.2b: Escalation protocol for fix agents**
482
+
483
+ Include this in the implementation agent's prompt:
484
+
485
+ ```
486
+ ## When Your Fix Doesn't Work (MANDATORY)
487
+
488
+ 1. After first failed attempt: re-read the root cause analysis from Step 1.
489
+ Is the root cause correct? If not, go back to Step 1.
490
+ 2. After second failed attempt: consult knowledge base:
491
+ - .claude/knowledge/qa-knowledge/ (error keywords)
492
+ - .claude/knowledge/shared/conventions.md (project gotchas)
493
+ - git log --all --grep="<error keyword>" --oneline -10
494
+ 3. After third failed attempt: STOP. Do not try another fix.
495
+ Generate a STUCK REPORT and send to team-lead:
496
+ - Error: [exact message]
497
+ - Root cause hypothesis: [from Step 1]
498
+ - Fix attempts: [1, 2, 3 with results]
499
+ - KB consultation results: [what you found]
500
+ - Recommendation: [re-investigate root cause / ask user for X / try different approach]
501
+ 4. If a troubleshooter agent is available, team-lead may spawn one.
502
+ ```
503
+
481
504
  **Agent prompt includes:**
482
505
  ```
483
506
  1. Root cause analysis from Step 1
@@ -29,9 +29,15 @@ If no feature name is provided, use AskUserQuestion to get it.
29
29
  If the plan file exists:
30
30
  - Read it with the Read tool.
31
31
  - Parse the YAML frontmatter to extract the `layers` array (`frontend`, `backend`, or both).
32
+ - Parse the `spec` field from frontmatter (e.g., `spec: specs/feature-name.md`).
32
33
  - Use `layers` to determine which agents to spawn (see Agent Selection below).
33
34
  - Use the full file content as `PLAN`.
34
35
 
36
+ **Also check for a spec file** at `.claude/specs/{feature-name}.md` (written by `/planning` Phase 0):
37
+ - If it exists, read it and store as `FEATURE_SPEC`.
38
+ - Extract `USER_STORIES` (the ## User Stories section) and `EDGE_CASES` (the ## Edge Cases section).
39
+ - These are passed to implementation agents and QA for better coverage.
40
+
35
41
  If the plan file does NOT exist:
36
42
  - Check conversation history for a recent `/planning` output. If found, use it as `PLAN` and infer layers from task breakdown.
37
43
  - If neither exists, ask the user with AskUserQuestion:
@@ -136,6 +142,43 @@ Include the results in the shared context block below so agents match existing
136
142
  patterns instead of inventing new ones. This is 60x cheaper than having each
137
143
  Sonnet agent independently explore the codebase.
138
144
 
145
+ ### 3c. Consult Knowledge Base (before agents start)
146
+
147
+ Before spawning implementation agents, check the knowledge base for relevant context:
148
+
149
+ ```
150
+ 1. .claude/knowledge/shared/conventions.md — coding rules and project gotchas
151
+ 2. .claude/knowledge/shared/patterns.md — architecture patterns to follow
152
+ 3. .claude/knowledge/qa-knowledge/ — past incidents in the same area
153
+ 4. git log --all --grep="fix:" --oneline -10 — recent bug fixes that may be relevant
154
+ ```
155
+
156
+ Include any relevant findings in the shared context block as `KNOWLEDGE_CONTEXT`.
157
+ This prevents agents from repeating past mistakes or contradicting established patterns.
158
+
159
+ ### 3d. Escalation Protocol for Implementation Agents
160
+
161
+ Add this to every implementation agent's prompt:
162
+
163
+ ```
164
+ ## When You Get Stuck (MANDATORY PROTOCOL)
165
+
166
+ If a command fails or a fix doesn't work:
167
+ 1. DO NOT retry the same approach more than twice
168
+ 2. After 2 failures with same error: STOP and consult knowledge base
169
+ - .claude/knowledge/shared/conventions.md
170
+ - .claude/knowledge/qa-knowledge/ (search for error keywords)
171
+ - git log --all --grep="<error keyword>" --oneline -10
172
+ 3. After 3 failures: escalate with a STUCK REPORT:
173
+ - Error: [exact message]
174
+ - Attempts: [what you tried, why each failed]
175
+ - Evidence: [logs, state, KB results]
176
+ - What you need: [access/data/decision]
177
+ - Recommendation: [your best option]
178
+ 4. Send the stuck report to team-lead via SendMessage
179
+ 5. If a troubleshooter agent is available, team-lead may spawn one to help
180
+ ```
181
+
139
182
  ### 4. Build Shared Context Block
140
183
 
141
184
  ```
@@ -148,6 +191,16 @@ Auth: {AUTH_APPROACH}
148
191
  ## Implementation Plan
149
192
  {PLAN}
150
193
 
194
+ ## User Stories (from spec — trace your work to these)
195
+ {USER_STORIES}
196
+
197
+ (If no spec exists, this section is omitted.)
198
+
199
+ ## Edge Cases (from spec — handle these in your implementation)
200
+ {EDGE_CASES}
201
+
202
+ (If no spec exists, this section is omitted.)
203
+
151
204
  ## API Contract
152
205
  {API_CONTRACT}
153
206
 
@@ -206,7 +259,7 @@ Check `.claude/project-profile.md` first (if /calibrate has run). Otherwise the
206
259
 
207
260
  **Always spawn:**
208
261
  - **qa** (subagent_type="qa", model="sonnet", name="qa")
209
- - Prompt: "{SHARED_CONTEXT}\n\nYou are QA. Your job: (1) Review backend and frontend implementations as they complete. (2) Ask teammates 'why did you do X?' when something looks wrong. (3) Run validation checks (linters, type checkers, build commands). (4) Report issues back to the responsible teammate. (5) Mark your tasks done when all checks pass. Do NOT write code — only review and validate."
262
+ - Prompt: "{SHARED_CONTEXT}\n\nYou are QA. Your job: (1) Review backend and frontend implementations as they complete. (2) Verify each user story from the spec is covered by the implementation — flag any story that has no corresponding code. (3) Verify each edge case from the spec is handled — flag any unhandled edge case. (4) Ask teammates 'why did you do X?' when something looks wrong. (5) Run validation checks (linters, type checkers, build commands). (6) Report issues back to the responsible teammate. (7) Mark your tasks done when all checks pass. Do NOT write code — only review and validate.\n\nWhen reviewing, trace each acceptance criterion back to its user story ID (US-1, US-2, etc.) and confirm the implementation satisfies it. Check edge cases (EC-1, EC-2, etc.) have explicit handling in the code."
210
263
 
211
264
  ### 5b. Red Team Phase
212
265
 
@@ -341,6 +394,7 @@ After PASS (or user override of BLOCK):
341
394
 
342
395
  ### 6. Monitor + Coordinate
343
396
 
397
+ **Standard coordination:**
344
398
  - Watch TaskList for progress.
345
399
  - If backend finishes API endpoints, nudge frontend to unblock.
346
400
  - If a teammate is stuck, relay context from the other teammate.
@@ -349,6 +403,50 @@ After PASS (or user override of BLOCK):
349
403
  - If `REDTEAM_MODE=once`, defer Step 5b until all implementation steps are complete.
350
404
  - Track `REDTEAM_CYCLE`. If a BLOCK verdict is returned from Step 5b.4, pause all progress and escalate to the user before continuing.
351
405
 
406
+ **Escalation handling (when an agent sends a STUCK REPORT):**
407
+
408
+ When an agent reports they're stuck (via SendMessage with stuck report format):
409
+
410
+ 1. **Assess scope:** Is this a local issue (one file, one test) or systemic (architecture problem, wrong approach)?
411
+
412
+ 2. **If local issue (single file/test failure):**
413
+ - Check if another teammate can help (e.g., backend stuck on a frontend integration → ask frontend agent)
414
+ - Spawn a troubleshooter agent with the stuck report + error context
415
+ - Relay the troubleshooter's diagnosis back to the stuck agent
416
+ - If troubleshooter confidence is LOW → escalate to user with structured options
417
+
418
+ 3. **If systemic issue (architecture problem, multiple agents affected):**
419
+ - PAUSE all agents (don't let them keep building on a broken foundation)
420
+ - Escalate to user immediately:
421
+ ```
422
+ IMPLEMENTATION BLOCKED
423
+
424
+ What happened: [agent] hit [error] after [N] attempts
425
+ Scope: [local/systemic] — [why you think so]
426
+ Impact: [which tasks are blocked]
427
+ Troubleshooter says: [diagnosis if spawned]
428
+
429
+ Options:
430
+ [1] Fix the root cause (I'll explain what needs to change)
431
+ [2] Adjust the plan (scope down to avoid this area)
432
+ [3] Abort implementation (save work done so far)
433
+ ```
434
+
435
+ 4. **If two agents are stuck simultaneously:**
436
+ - This is almost always a systemic issue → treat as systemic
437
+ - Do NOT spawn two troubleshooters — diagnose once, fix at the root
438
+
439
+ 5. **If a task shows no progress for 3+ consecutive idle cycles:**
440
+ - Check in with the agent: "What's your status on Task #N?"
441
+ - If no meaningful progress → treat as stuck (even without explicit stuck report)
442
+
443
+ **Red team finding escalation:**
444
+
445
+ When red team finds issues that the developer can't fix:
446
+ - If the fix requires changes outside their file ownership → orchestrator makes the cross-cutting change
447
+ - If the fix requires a plan change → escalate to user: "Red team found [issue] that requires changing the plan. Original plan said [X], but we need [Y]. Approve?"
448
+ - If the fix is beyond the team's capability → acknowledge, log it, and add to the PR description as a known limitation
449
+
352
450
  ### 7. Cleanup Implementation Team
353
451
 
354
452
  - Send shutdown_request to all teammates.