agileflow 3.3.0 → 3.4.1

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 (210) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +6 -6
  3. package/lib/skill-loader.js +0 -1
  4. package/package.json +1 -1
  5. package/scripts/agileflow-statusline.sh +81 -0
  6. package/scripts/agileflow-welcome.js +79 -0
  7. package/scripts/claude-tmux.sh +90 -23
  8. package/scripts/claude-watchdog.sh +225 -0
  9. package/scripts/generators/agent-registry.js +14 -1
  10. package/scripts/generators/inject-babysit.js +22 -9
  11. package/scripts/generators/inject-help.js +19 -9
  12. package/scripts/lib/ac-test-matcher.js +452 -0
  13. package/scripts/lib/audit-cleanup.js +250 -0
  14. package/scripts/lib/audit-registry.js +304 -0
  15. package/scripts/lib/configure-features.js +35 -0
  16. package/scripts/lib/feature-catalog.js +3 -3
  17. package/scripts/lib/gate-enforcer.js +295 -0
  18. package/scripts/lib/model-profiles.js +118 -0
  19. package/scripts/lib/quality-gates.js +163 -0
  20. package/scripts/lib/signal-detectors.js +44 -1
  21. package/scripts/lib/skill-catalog.js +557 -0
  22. package/scripts/lib/skill-recommender.js +311 -0
  23. package/scripts/lib/status-writer.js +255 -0
  24. package/scripts/lib/story-claiming.js +128 -45
  25. package/scripts/lib/task-sync.js +32 -38
  26. package/scripts/lib/tdd-phase-manager.js +455 -0
  27. package/scripts/lib/team-events.js +34 -3
  28. package/scripts/lib/tmux-audit-monitor.js +611 -0
  29. package/scripts/lib/tmux-group-colors.js +113 -0
  30. package/scripts/lib/tool-registry.yaml +241 -0
  31. package/scripts/lib/tool-shed.js +441 -0
  32. package/scripts/messaging-bridge.js +209 -1
  33. package/scripts/native-team-observer.js +219 -0
  34. package/scripts/obtain-context.js +14 -0
  35. package/scripts/ralph-loop.js +30 -5
  36. package/scripts/smart-detect.js +21 -0
  37. package/scripts/spawn-audit-sessions.js +877 -0
  38. package/scripts/team-manager.js +56 -16
  39. package/scripts/tmux-close-windows.sh +180 -0
  40. package/src/core/agents/a11y-analyzer-aria.md +155 -0
  41. package/src/core/agents/a11y-analyzer-forms.md +162 -0
  42. package/src/core/agents/a11y-analyzer-keyboard.md +175 -0
  43. package/src/core/agents/a11y-analyzer-semantic.md +153 -0
  44. package/src/core/agents/a11y-analyzer-visual.md +158 -0
  45. package/src/core/agents/a11y-consensus.md +248 -0
  46. package/src/core/agents/ads-audit-budget.md +181 -0
  47. package/src/core/agents/ads-audit-compliance.md +169 -0
  48. package/src/core/agents/ads-audit-creative.md +164 -0
  49. package/src/core/agents/ads-audit-google.md +226 -0
  50. package/src/core/agents/ads-audit-meta.md +183 -0
  51. package/src/core/agents/ads-audit-tracking.md +197 -0
  52. package/src/core/agents/ads-consensus.md +396 -0
  53. package/src/core/agents/ads-generate.md +145 -0
  54. package/src/core/agents/ads-performance-tracker.md +197 -0
  55. package/src/core/agents/api-quality-analyzer-conventions.md +148 -0
  56. package/src/core/agents/api-quality-analyzer-docs.md +176 -0
  57. package/src/core/agents/api-quality-analyzer-errors.md +183 -0
  58. package/src/core/agents/api-quality-analyzer-pagination.md +171 -0
  59. package/src/core/agents/api-quality-analyzer-versioning.md +143 -0
  60. package/src/core/agents/api-quality-consensus.md +214 -0
  61. package/src/core/agents/arch-analyzer-circular.md +148 -0
  62. package/src/core/agents/arch-analyzer-complexity.md +171 -0
  63. package/src/core/agents/arch-analyzer-coupling.md +146 -0
  64. package/src/core/agents/arch-analyzer-layering.md +151 -0
  65. package/src/core/agents/arch-analyzer-patterns.md +162 -0
  66. package/src/core/agents/arch-consensus.md +227 -0
  67. package/src/core/agents/brainstorm-analyzer-features.md +169 -0
  68. package/src/core/agents/brainstorm-analyzer-growth.md +161 -0
  69. package/src/core/agents/brainstorm-analyzer-integration.md +172 -0
  70. package/src/core/agents/brainstorm-analyzer-market.md +147 -0
  71. package/src/core/agents/brainstorm-analyzer-ux.md +167 -0
  72. package/src/core/agents/brainstorm-consensus.md +237 -0
  73. package/src/core/agents/completeness-consensus.md +5 -5
  74. package/src/core/agents/perf-consensus.md +2 -2
  75. package/src/core/agents/security-consensus.md +2 -2
  76. package/src/core/agents/seo-analyzer-content.md +167 -0
  77. package/src/core/agents/seo-analyzer-images.md +187 -0
  78. package/src/core/agents/seo-analyzer-performance.md +206 -0
  79. package/src/core/agents/seo-analyzer-schema.md +176 -0
  80. package/src/core/agents/seo-analyzer-sitemap.md +172 -0
  81. package/src/core/agents/seo-analyzer-technical.md +144 -0
  82. package/src/core/agents/seo-consensus.md +289 -0
  83. package/src/core/agents/test-consensus.md +2 -2
  84. package/src/core/commands/adr.md +1 -0
  85. package/src/core/commands/ads/audit.md +375 -0
  86. package/src/core/commands/ads/budget.md +97 -0
  87. package/src/core/commands/ads/competitor.md +112 -0
  88. package/src/core/commands/ads/creative.md +85 -0
  89. package/src/core/commands/ads/generate.md +238 -0
  90. package/src/core/commands/ads/google.md +112 -0
  91. package/src/core/commands/ads/health.md +327 -0
  92. package/src/core/commands/ads/landing.md +119 -0
  93. package/src/core/commands/ads/linkedin.md +112 -0
  94. package/src/core/commands/ads/meta.md +91 -0
  95. package/src/core/commands/ads/microsoft.md +115 -0
  96. package/src/core/commands/ads/plan.md +321 -0
  97. package/src/core/commands/ads/test-plan.md +317 -0
  98. package/src/core/commands/ads/tiktok.md +129 -0
  99. package/src/core/commands/ads/track.md +288 -0
  100. package/src/core/commands/ads/youtube.md +124 -0
  101. package/src/core/commands/ads.md +140 -0
  102. package/src/core/commands/assign.md +1 -0
  103. package/src/core/commands/audit.md +43 -6
  104. package/src/core/commands/babysit.md +315 -1266
  105. package/src/core/commands/baseline.md +1 -0
  106. package/src/core/commands/blockers.md +1 -0
  107. package/src/core/commands/board.md +1 -0
  108. package/src/core/commands/changelog.md +1 -0
  109. package/src/core/commands/choose.md +1 -0
  110. package/src/core/commands/ci.md +1 -0
  111. package/src/core/commands/code/accessibility.md +347 -0
  112. package/src/core/commands/code/api.md +297 -0
  113. package/src/core/commands/code/architecture.md +297 -0
  114. package/src/core/commands/{audit → code}/completeness.md +72 -25
  115. package/src/core/commands/{audit → code}/legal.md +63 -16
  116. package/src/core/commands/{audit → code}/logic.md +64 -16
  117. package/src/core/commands/{audit → code}/performance.md +67 -20
  118. package/src/core/commands/{audit → code}/security.md +69 -19
  119. package/src/core/commands/{audit → code}/test.md +67 -20
  120. package/src/core/commands/configure.md +1 -0
  121. package/src/core/commands/council.md +1 -0
  122. package/src/core/commands/deploy.md +1 -0
  123. package/src/core/commands/diagnose.md +1 -0
  124. package/src/core/commands/docs.md +1 -0
  125. package/src/core/commands/epic/edit.md +213 -0
  126. package/src/core/commands/epic.md +1 -0
  127. package/src/core/commands/export.md +238 -0
  128. package/src/core/commands/help.md +16 -1
  129. package/src/core/commands/{discovery → ideate}/brief.md +12 -12
  130. package/src/core/commands/{discovery/new.md → ideate/discover.md} +20 -16
  131. package/src/core/commands/ideate/features.md +496 -0
  132. package/src/core/commands/ideate/new.md +158 -124
  133. package/src/core/commands/impact.md +1 -0
  134. package/src/core/commands/learn/explain.md +118 -0
  135. package/src/core/commands/learn/glossary.md +135 -0
  136. package/src/core/commands/learn/patterns.md +138 -0
  137. package/src/core/commands/learn/tour.md +126 -0
  138. package/src/core/commands/migrate/codemods.md +151 -0
  139. package/src/core/commands/migrate/plan.md +131 -0
  140. package/src/core/commands/migrate/scan.md +114 -0
  141. package/src/core/commands/migrate/validate.md +119 -0
  142. package/src/core/commands/multi-expert.md +1 -0
  143. package/src/core/commands/pr.md +1 -0
  144. package/src/core/commands/review.md +1 -0
  145. package/src/core/commands/seo/audit.md +373 -0
  146. package/src/core/commands/seo/competitor.md +174 -0
  147. package/src/core/commands/seo/content.md +107 -0
  148. package/src/core/commands/seo/geo.md +229 -0
  149. package/src/core/commands/seo/hreflang.md +140 -0
  150. package/src/core/commands/seo/images.md +96 -0
  151. package/src/core/commands/seo/page.md +198 -0
  152. package/src/core/commands/seo/plan.md +163 -0
  153. package/src/core/commands/seo/programmatic.md +131 -0
  154. package/src/core/commands/seo/references/cwv-thresholds.md +64 -0
  155. package/src/core/commands/seo/references/eeat-framework.md +110 -0
  156. package/src/core/commands/seo/references/quality-gates.md +91 -0
  157. package/src/core/commands/seo/references/schema-types.md +102 -0
  158. package/src/core/commands/seo/schema.md +183 -0
  159. package/src/core/commands/seo/sitemap.md +97 -0
  160. package/src/core/commands/seo/technical.md +100 -0
  161. package/src/core/commands/seo.md +107 -0
  162. package/src/core/commands/skill/list.md +68 -212
  163. package/src/core/commands/skill/recommend.md +216 -0
  164. package/src/core/commands/sprint.md +1 -0
  165. package/src/core/commands/status/undo.md +191 -0
  166. package/src/core/commands/status.md +1 -0
  167. package/src/core/commands/story/edit.md +204 -0
  168. package/src/core/commands/story/view.md +29 -7
  169. package/src/core/commands/story-validate.md +1 -0
  170. package/src/core/commands/story.md +1 -0
  171. package/src/core/commands/tdd-next.md +238 -0
  172. package/src/core/commands/tdd.md +211 -0
  173. package/src/core/commands/team/start.md +10 -6
  174. package/src/core/commands/tests.md +1 -0
  175. package/src/core/commands/verify.md +27 -1
  176. package/src/core/commands/workflow.md +2 -0
  177. package/src/core/experts/_core-expertise.yaml +105 -0
  178. package/src/core/experts/analytics/expertise.yaml +5 -99
  179. package/src/core/experts/codebase-query/expertise.yaml +3 -72
  180. package/src/core/experts/compliance/expertise.yaml +6 -72
  181. package/src/core/experts/database/expertise.yaml +9 -52
  182. package/src/core/experts/documentation/expertise.yaml +7 -140
  183. package/src/core/experts/integrations/expertise.yaml +7 -127
  184. package/src/core/experts/mentor/expertise.yaml +8 -35
  185. package/src/core/experts/monitoring/expertise.yaml +7 -49
  186. package/src/core/experts/performance/expertise.yaml +1 -26
  187. package/src/core/experts/security/expertise.yaml +9 -34
  188. package/src/core/experts/ui/expertise.yaml +6 -36
  189. package/src/core/knowledge/ads/ad-audit-checklist-scoring.md +424 -0
  190. package/src/core/knowledge/ads/ad-optimization-logic.md +590 -0
  191. package/src/core/knowledge/ads/ad-technical-specifications.md +385 -0
  192. package/src/core/knowledge/ads/definitive-advertising-reference-2026.md +506 -0
  193. package/src/core/knowledge/ads/paid-advertising-research-2026.md +445 -0
  194. package/src/core/teams/backend.json +41 -0
  195. package/src/core/teams/frontend.json +41 -0
  196. package/src/core/teams/qa.json +41 -0
  197. package/src/core/teams/solo.json +35 -0
  198. package/src/core/templates/agileflow-metadata.json +20 -1
  199. package/tools/cli/commands/setup.js +85 -3
  200. package/tools/cli/commands/update.js +42 -0
  201. package/tools/cli/installers/ide/_base-ide.js +42 -5
  202. package/tools/cli/installers/ide/claude-code.js +71 -3
  203. package/tools/cli/lib/content-injector.js +160 -12
  204. package/tools/cli/lib/docs-setup.js +1 -1
  205. package/src/core/commands/skill/create.md +0 -698
  206. package/src/core/commands/skill/delete.md +0 -316
  207. package/src/core/commands/skill/edit.md +0 -359
  208. package/src/core/commands/skill/test.md +0 -394
  209. package/src/core/commands/skill/upgrade.md +0 -552
  210. package/src/core/templates/skill-template.md +0 -117
@@ -0,0 +1,225 @@
1
+ #!/bin/bash
2
+ # claude-watchdog.sh - Background watchdog that detects and kills frozen Claude processes
3
+ #
4
+ # Usage: claude-watchdog.sh <session-name>
5
+ #
6
+ # Runs in the background, checking every WATCHDOG_INTERVAL seconds for Claude
7
+ # processes that appear frozen. A process is considered frozen when ALL of:
8
+ # 1. Running for > WATCHDOG_MAX_AGE_HOURS hours
9
+ # 2. Using > WATCHDOG_MAX_MEMORY_MB megabytes of RSS
10
+ # 3. No JSONL file modification in > WATCHDOG_MAX_IDLE_MINUTES minutes
11
+ #
12
+ # Recovery sequence: Ctrl+C x2 (5s wait) → SIGTERM (5s wait) → SIGKILL
13
+ # After kill, the pane stays open with a shell prompt (tab is NOT closed).
14
+ #
15
+ # Logs kills to ~/.claude/watchdog.log
16
+ #
17
+ # Environment variable configuration:
18
+ # WATCHDOG_INTERVAL Check interval in seconds (default: 120)
19
+ # WATCHDOG_MAX_AGE_HOURS Minimum process age to consider (default: 6)
20
+ # WATCHDOG_MAX_MEMORY_MB Minimum RSS in MB to consider (default: 400)
21
+ # WATCHDOG_MAX_IDLE_MINUTES Minutes since last JSONL write (default: 60)
22
+ #
23
+ # NOTE: Linux-only (requires /proc filesystem and GNU ps). macOS not supported.
24
+
25
+ set -euo pipefail
26
+
27
+ SESSION_NAME="${1:-}"
28
+ if [ -z "$SESSION_NAME" ]; then
29
+ echo "Usage: claude-watchdog.sh <session-name>" >&2
30
+ exit 1
31
+ fi
32
+
33
+ # Configuration (all overridable via environment)
34
+ INTERVAL="${WATCHDOG_INTERVAL:-120}"
35
+ MAX_AGE_HOURS="${WATCHDOG_MAX_AGE_HOURS:-6}"
36
+ MAX_MEMORY_MB="${WATCHDOG_MAX_MEMORY_MB:-400}"
37
+ MAX_IDLE_MINUTES="${WATCHDOG_MAX_IDLE_MINUTES:-60}"
38
+
39
+ # Validate numeric configuration
40
+ for _var_name in INTERVAL MAX_AGE_HOURS MAX_MEMORY_MB MAX_IDLE_MINUTES; do
41
+ _var_val="${!_var_name}"
42
+ if ! [[ "$_var_val" =~ ^[0-9]+$ ]]; then
43
+ echo "ERROR: $_var_name must be a positive integer, got: '$_var_val'" >&2
44
+ exit 1
45
+ fi
46
+ done
47
+
48
+ LOG_FILE="$HOME/.claude/watchdog.log"
49
+ mkdir -p "$(dirname "$LOG_FILE")"
50
+
51
+ log() {
52
+ local timestamp
53
+ timestamp=$(date '+%Y-%m-%d %H:%M:%S')
54
+ echo "[$timestamp] [watchdog:$SESSION_NAME] $*" >> "$LOG_FILE"
55
+ }
56
+
57
+ log "Started (interval=${INTERVAL}s, max_age=${MAX_AGE_HOURS}h, max_mem=${MAX_MEMORY_MB}MB, max_idle=${MAX_IDLE_MINUTES}m)"
58
+
59
+ # Clean exit when session is destroyed
60
+ cleanup() {
61
+ log "Stopping (session gone or signal received)" || true
62
+ exit 0
63
+ }
64
+ trap cleanup INT TERM
65
+
66
+ # Check if a process's JSONL files have been modified recently
67
+ # Returns 0 if idle (no recent writes), 1 if active
68
+ is_process_idle() {
69
+ local pid="$1"
70
+ local idle_minutes="$2"
71
+
72
+ # Find the working directory of the process to locate .claude/ project dirs
73
+ local cwd
74
+ cwd=$(readlink "/proc/$pid/cwd" 2>/dev/null) || return 1
75
+
76
+ # Build the project path Claude Code uses for JSONL session files
77
+ local proj_dir
78
+ proj_dir=$(echo "$cwd" | sed 's|/|-|g' | sed 's|^-||')
79
+ local sessions_dir="$HOME/.claude/projects/-$proj_dir"
80
+
81
+ if [ ! -d "$sessions_dir" ]; then
82
+ # No session dir means no activity tracking — assume idle
83
+ return 0
84
+ fi
85
+
86
+ # Check if any JSONL file was modified within idle_minutes
87
+ local recent_file
88
+ recent_file=$(find "$sessions_dir" -name '*.jsonl' -mmin "-$idle_minutes" -print -quit 2>/dev/null)
89
+
90
+ if [ -n "$recent_file" ]; then
91
+ # Recently modified — process is active
92
+ return 1
93
+ fi
94
+
95
+ # No recent modifications — process is idle
96
+ return 0
97
+ }
98
+
99
+ # Get process RSS in MB (Linux /proc-based, ps fallback)
100
+ get_rss_mb() {
101
+ local pid="$1"
102
+ local rss_kb
103
+ if [ -f "/proc/$pid/status" ]; then
104
+ rss_kb=$(awk '/^VmRSS:/ { print $2 }' "/proc/$pid/status" 2>/dev/null) || return 1
105
+ [ -z "$rss_kb" ] && return 1 # process died between stat and read
106
+ echo $(( rss_kb / 1024 ))
107
+ else
108
+ rss_kb=$(ps -o rss= -p "$pid" 2>/dev/null | tr -d ' ') || return 1
109
+ [ -z "$rss_kb" ] && return 1
110
+ echo $(( rss_kb / 1024 ))
111
+ fi
112
+ }
113
+
114
+ # Get process age in hours
115
+ get_age_hours() {
116
+ local pid="$1"
117
+ local elapsed_seconds
118
+ elapsed_seconds=$(ps -o etimes= -p "$pid" 2>/dev/null | tr -d ' ') || return 1
119
+ [ -z "$elapsed_seconds" ] && return 1
120
+ echo $(( elapsed_seconds / 3600 ))
121
+ }
122
+
123
+ # Gracefully kill a frozen process with escalating signals
124
+ kill_frozen_process() {
125
+ local pid="$1"
126
+ local pane_id="$2"
127
+ local age_h="$3"
128
+ local mem_mb="$4"
129
+
130
+ log "FROZEN DETECTED: PID=$pid pane=$pane_id age=${age_h}h mem=${mem_mb}MB"
131
+ log "Recovery: sending Ctrl+C x2 to pane $pane_id"
132
+
133
+ # Step 1: Try Ctrl+C twice via tmux (gentlest approach)
134
+ tmux send-keys -t "$pane_id" C-c 2>/dev/null || true
135
+ sleep 1
136
+ tmux send-keys -t "$pane_id" C-c 2>/dev/null || true
137
+ sleep 4
138
+
139
+ # Check if process is still alive
140
+ if ! kill -0 "$pid" 2>/dev/null; then
141
+ log "Process $pid terminated after Ctrl+C"
142
+ return 0
143
+ fi
144
+
145
+ # Step 2: SIGTERM
146
+ log "Recovery: sending SIGTERM to PID $pid"
147
+ kill -TERM "$pid" 2>/dev/null || true
148
+ sleep 5
149
+
150
+ if ! kill -0 "$pid" 2>/dev/null; then
151
+ log "Process $pid terminated after SIGTERM"
152
+ return 0
153
+ fi
154
+
155
+ # Step 3: SIGKILL (last resort)
156
+ log "Recovery: sending SIGKILL to PID $pid"
157
+ kill -KILL "$pid" 2>/dev/null || true
158
+ sleep 1
159
+
160
+ if ! kill -0 "$pid" 2>/dev/null; then
161
+ log "Process $pid terminated after SIGKILL"
162
+ else
163
+ log "WARNING: Process $pid survived SIGKILL — zombie or kernel issue"
164
+ fi
165
+
166
+ return 0
167
+ }
168
+
169
+ # Main check loop
170
+ while true; do
171
+ # Exit if session no longer exists
172
+ if ! tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
173
+ log "Session '$SESSION_NAME' no longer exists"
174
+ break
175
+ fi
176
+
177
+ # Iterate over all panes in the session
178
+ while IFS= read -r pane_info; do
179
+ [ -z "$pane_info" ] && continue
180
+
181
+ pane_id="${pane_info%% *}"
182
+ pane_pid="${pane_info#* }"
183
+
184
+ # Find claude child processes under this pane's shell
185
+ # Look for processes whose command contains "claude" under the pane PID
186
+ while IFS= read -r child_line; do
187
+ [ -z "$child_line" ] && continue
188
+
189
+ child_pid="${child_line%% *}"
190
+ child_cmd="${child_line#* }"
191
+
192
+ # Skip non-claude processes and skip ourselves
193
+ case "$child_cmd" in
194
+ *claude-watchdog*|*watchdog*) continue ;;
195
+ *claude*) ;; # This is a Claude process — check it
196
+ *) continue ;;
197
+ esac
198
+
199
+ # Criterion 1: Age check
200
+ age_h=$(get_age_hours "$child_pid" 2>/dev/null) || continue
201
+ if [ "$age_h" -lt "$MAX_AGE_HOURS" ]; then
202
+ continue
203
+ fi
204
+
205
+ # Criterion 2: Memory check
206
+ mem_mb=$(get_rss_mb "$child_pid" 2>/dev/null) || continue
207
+ if [ "$mem_mb" -lt "$MAX_MEMORY_MB" ]; then
208
+ continue
209
+ fi
210
+
211
+ # Criterion 3: Idle check (most important — prevents killing active work)
212
+ if ! is_process_idle "$child_pid" "$MAX_IDLE_MINUTES"; then
213
+ # Process has recent JSONL activity — NOT frozen, just long-running
214
+ continue
215
+ fi
216
+
217
+ # All three criteria met — this process is frozen
218
+ kill_frozen_process "$child_pid" "$pane_id" "$age_h" "$mem_mb"
219
+
220
+ done < <(ps --ppid "$pane_pid" -o pid=,args= 2>/dev/null || true)
221
+
222
+ done < <(tmux list-panes -t "$SESSION_NAME" -F '#{pane_id} #{pane_pid}' 2>/dev/null || true)
223
+
224
+ sleep "$INTERVAL"
225
+ done
@@ -15,6 +15,19 @@ const path = require('path');
15
15
  const { extractFrontmatter, normalizeTools } = require('../lib/frontmatter-parser');
16
16
  const { getCached, setCached } = require('../../lib/registry-cache');
17
17
 
18
+ // Lazy-load model-profiles to avoid circular deps and missing-module crashes
19
+ let _resolveModel;
20
+ function getResolveModel() {
21
+ if (_resolveModel === undefined) {
22
+ try {
23
+ _resolveModel = require('../lib/model-profiles').resolveModel;
24
+ } catch (_) {
25
+ _resolveModel = null;
26
+ }
27
+ }
28
+ return _resolveModel;
29
+ }
30
+
18
31
  // Debug mode: set DEBUG_REGISTRY=1 to see why files are skipped
19
32
  const DEBUG = process.env.DEBUG_REGISTRY === '1';
20
33
 
@@ -110,7 +123,7 @@ async function scanAgents(agentsDir) {
110
123
  displayName: frontmatter.name || name,
111
124
  description: frontmatter.description || '',
112
125
  tools,
113
- model: frontmatter.model || 'haiku',
126
+ model: (getResolveModel() || ((_, fm) => fm || 'haiku'))(null, frontmatter.model),
114
127
  color: frontmatter.color || 'blue',
115
128
  category: categorizeAgent(name, frontmatter.description || ''),
116
129
  });
@@ -14,9 +14,11 @@ const { scanAgents } = require('./agent-registry');
14
14
  const { scanCommands } = require('./command-registry');
15
15
 
16
16
  /**
17
- * Generate agent list content with details
17
+ * Generate agent list content as category summary with counts.
18
+ * Uses compact format with discovery pointer instead of listing every agent name.
19
+ * Research (arXiv:2602.11988): Full lists increase context cost without improving performance.
18
20
  * @param {Array} agents - Array of agent metadata
19
- * @returns {string} Formatted agent list
21
+ * @returns {string} Formatted agent category summary
20
22
  */
21
23
  function generateAgentList(agents) {
22
24
  const lines = [];
@@ -24,16 +26,27 @@ function generateAgentList(agents) {
24
26
  lines.push(`**AVAILABLE AGENTS** (${agents.length} total):`);
25
27
  lines.push('');
26
28
 
27
- let count = 1;
29
+ // Group agents by category for compact output (counts only, not full names)
30
+ const categories = {};
28
31
  for (const agent of agents) {
29
- lines.push(`${count}. **${agent.name}** (model: ${agent.model})`);
30
- lines.push(` - **Purpose**: ${agent.description}`);
31
- lines.push(` - **Tools**: ${agent.tools.join(', ')}`);
32
- lines.push(` - **Category**: ${agent.category}`);
33
- lines.push('');
34
- count++;
32
+ const cat = agent.category || 'Other';
33
+ if (!categories[cat]) categories[cat] = { count: 0, examples: [] };
34
+ categories[cat].count++;
35
+ // Keep first 3 names as examples
36
+ if (categories[cat].examples.length < 3) {
37
+ categories[cat].examples.push(agent.name);
38
+ }
39
+ }
40
+
41
+ for (const [category, data] of Object.entries(categories)) {
42
+ const examples = data.examples.join(', ');
43
+ const more = data.count > 3 ? `, +${data.count - 3} more` : '';
44
+ lines.push(`**${category}** (${data.count}): ${examples}${more}`);
35
45
  }
36
46
 
47
+ lines.push('');
48
+ lines.push('Browse all: `ls .agileflow/agents/` or run `/agileflow:help agents`');
49
+
37
50
  return lines.join('\n');
38
51
  }
39
52
 
@@ -13,9 +13,11 @@ const path = require('path');
13
13
  const { scanCommands } = require('./command-registry');
14
14
 
15
15
  /**
16
- * Generate command list content grouped by category
16
+ * Generate command list content as category summary with counts and examples.
17
+ * Uses compact format with discovery pointer instead of listing every command.
18
+ * Research (arXiv:2602.11988): Full lists increase context cost without improving performance.
17
19
  * @param {Array} commands - Array of command metadata
18
- * @returns {string} Formatted command list
20
+ * @returns {string} Formatted command category summary
19
21
  */
20
22
  function generateCommandList(commands) {
21
23
  const lines = [];
@@ -29,16 +31,24 @@ function generateCommandList(commands) {
29
31
  categories[cmd.category].push(cmd);
30
32
  }
31
33
 
32
- // Generate markdown for each category
34
+ lines.push(
35
+ `**${commands.length} commands** across ${Object.keys(categories).length} categories:`
36
+ );
37
+ lines.push('');
38
+
39
+ // Generate compact category summary with examples
33
40
  for (const [category, cmds] of Object.entries(categories)) {
34
- lines.push(`**${category}:**`);
35
- for (const cmd of cmds) {
36
- const hint = cmd.argumentHint ? ` ${cmd.argumentHint}` : '';
37
- lines.push(`- \`/agileflow:${cmd.name}${hint}\` - ${cmd.description}`);
38
- }
39
- lines.push(''); // Blank line between categories
41
+ const examples = cmds
42
+ .slice(0, 3)
43
+ .map(c => c.name)
44
+ .join(', ');
45
+ const more = cmds.length > 3 ? `, +${cmds.length - 3} more` : '';
46
+ lines.push(`- **${category}** (${cmds.length}): ${examples}${more}`);
40
47
  }
41
48
 
49
+ lines.push('');
50
+ lines.push('Browse all: `ls .agileflow/commands/` or run `/agileflow:help`');
51
+
42
52
  return lines.join('\n');
43
53
  }
44
54