monol-plugin-scout 2.1.3 → 4.1.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.
Files changed (87) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +244 -0
  3. package/monol-plugin-scout-pkg/CLAUDE.md +125 -8
  4. package/monol-plugin-scout-pkg/api/mock/categories.json +81 -0
  5. package/monol-plugin-scout-pkg/api/mock/insights.json +111 -0
  6. package/monol-plugin-scout-pkg/api/mock/marketplace.json +501 -0
  7. package/monol-plugin-scout-pkg/api/mock/trending.json +96 -0
  8. package/monol-plugin-scout-pkg/commands/console.md +79 -0
  9. package/monol-plugin-scout-pkg/commands/frequency.md +32 -0
  10. package/monol-plugin-scout-pkg/commands/install.md +32 -0
  11. package/monol-plugin-scout-pkg/commands/priority.md +30 -0
  12. package/monol-plugin-scout-pkg/commands/quiet.md +32 -0
  13. package/monol-plugin-scout-pkg/commands/schedule.md +32 -0
  14. package/monol-plugin-scout-pkg/commands/scout.md +8 -5
  15. package/monol-plugin-scout-pkg/commands/skills.md +160 -0
  16. package/monol-plugin-scout-pkg/commands/team.md +32 -0
  17. package/monol-plugin-scout-pkg/commands/timing.md +32 -0
  18. package/monol-plugin-scout-pkg/commands/trust.md +85 -0
  19. package/monol-plugin-scout-pkg/commands/trusted-install.md +98 -0
  20. package/monol-plugin-scout-pkg/commands/uninstall.md +31 -0
  21. package/monol-plugin-scout-pkg/config.yaml +57 -0
  22. package/monol-plugin-scout-pkg/data/.cache/676d5ab664292155e5f509c69d4edae1 +10 -0
  23. package/monol-plugin-scout-pkg/data/.session +8 -0
  24. package/monol-plugin-scout-pkg/data/analytics.json +102 -0
  25. package/monol-plugin-scout-pkg/data/history.json +67 -11
  26. package/monol-plugin-scout-pkg/data/logs/scout.log +1 -0
  27. package/monol-plugin-scout-pkg/data/schedules.json +17 -0
  28. package/monol-plugin-scout-pkg/data/team.json +53 -0
  29. package/monol-plugin-scout-pkg/data/usage.json +100 -7
  30. package/monol-plugin-scout-pkg/docs/ARCHITECTURE.md +201 -0
  31. package/monol-plugin-scout-pkg/hooks/generate-insights.sh +102 -0
  32. package/monol-plugin-scout-pkg/hooks/hooks.json +36 -1
  33. package/monol-plugin-scout-pkg/hooks/on-session-end.sh +136 -0
  34. package/monol-plugin-scout-pkg/hooks/on-session-start.sh +43 -0
  35. package/monol-plugin-scout-pkg/hooks/on-stop.md +79 -0
  36. package/monol-plugin-scout-pkg/hooks/open-console.sh +111 -0
  37. package/monol-plugin-scout-pkg/hooks/open-dashboard.sh +61 -0
  38. package/monol-plugin-scout-pkg/hooks/track-usage.sh +59 -0
  39. package/monol-plugin-scout-pkg/lib/ai-recommender.sh +505 -0
  40. package/monol-plugin-scout-pkg/lib/cache.sh +194 -0
  41. package/monol-plugin-scout-pkg/lib/data-validator.sh +360 -0
  42. package/monol-plugin-scout-pkg/lib/error-handler.sh +296 -0
  43. package/monol-plugin-scout-pkg/lib/logger.sh +263 -0
  44. package/monol-plugin-scout-pkg/lib/plugin-manager.sh +239 -0
  45. package/monol-plugin-scout-pkg/lib/priority-scorer.sh +262 -0
  46. package/monol-plugin-scout-pkg/lib/profile-learner.sh +339 -0
  47. package/monol-plugin-scout-pkg/lib/project-analyzer.sh +281 -0
  48. package/monol-plugin-scout-pkg/lib/recommendation-controller.sh +290 -0
  49. package/monol-plugin-scout-pkg/lib/rejection-learner.sh +232 -0
  50. package/monol-plugin-scout-pkg/lib/scheduler.sh +275 -0
  51. package/monol-plugin-scout-pkg/lib/skill-scout.sh +729 -0
  52. package/monol-plugin-scout-pkg/lib/sync.sh +221 -0
  53. package/monol-plugin-scout-pkg/lib/team-learner.sh +450 -0
  54. package/monol-plugin-scout-pkg/lib/team-manager.sh +369 -0
  55. package/monol-plugin-scout-pkg/lib/trend-learner.sh +428 -0
  56. package/monol-plugin-scout-pkg/lib/trust-manager.sh +261 -0
  57. package/monol-plugin-scout-pkg/lib/trusted-installer.sh +738 -0
  58. package/monol-plugin-scout-pkg/plugin.json +3 -2
  59. package/monol-plugin-scout-pkg/skills/audit.md +6 -0
  60. package/monol-plugin-scout-pkg/skills/cleanup.md +6 -0
  61. package/monol-plugin-scout-pkg/skills/compare.md +6 -0
  62. package/monol-plugin-scout-pkg/skills/console.md +315 -0
  63. package/monol-plugin-scout-pkg/skills/explore.md +6 -0
  64. package/monol-plugin-scout-pkg/skills/fork.md +6 -0
  65. package/monol-plugin-scout-pkg/skills/frequency.md +93 -0
  66. package/monol-plugin-scout-pkg/skills/install.md +127 -0
  67. package/monol-plugin-scout-pkg/skills/priority.md +77 -0
  68. package/monol-plugin-scout-pkg/skills/quiet.md +73 -0
  69. package/monol-plugin-scout-pkg/skills/schedule.md +95 -0
  70. package/monol-plugin-scout-pkg/skills/scout.md +27 -17
  71. package/monol-plugin-scout-pkg/skills/skills.md +230 -0
  72. package/monol-plugin-scout-pkg/skills/team.md +117 -0
  73. package/monol-plugin-scout-pkg/skills/timing.md +97 -0
  74. package/monol-plugin-scout-pkg/skills/trust.md +120 -0
  75. package/monol-plugin-scout-pkg/skills/trusted-install.md +264 -0
  76. package/monol-plugin-scout-pkg/skills/uninstall.md +100 -0
  77. package/monol-plugin-scout-pkg/web/components/activity-chart.js +208 -0
  78. package/monol-plugin-scout-pkg/web/components/index.js +27 -0
  79. package/monol-plugin-scout-pkg/web/components/insight-card.js +365 -0
  80. package/monol-plugin-scout-pkg/web/components/overview.js +154 -0
  81. package/monol-plugin-scout-pkg/web/components/plugin-list.js +242 -0
  82. package/monol-plugin-scout-pkg/web/components/stats-card.js +126 -0
  83. package/monol-plugin-scout-pkg/web/components/team-list.js +346 -0
  84. package/monol-plugin-scout-pkg/web/console.html +2098 -0
  85. package/monol-plugin-scout-pkg/web/dashboard.html +2106 -0
  86. package/monol-plugin-scout-pkg/web/manifest.json +29 -0
  87. package/package.json +1 -1
@@ -0,0 +1,369 @@
1
+ #!/bin/bash
2
+ # Plugin Scout - 팀 매니저
3
+ # 팀원별 플러그인 사용 통계 및 공유 추천
4
+
5
+ PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(dirname "$0")/..}"
6
+ DATA_DIR="$PLUGIN_ROOT/data"
7
+ TEAM_FILE="$DATA_DIR/team.json"
8
+ USAGE_FILE="$DATA_DIR/usage.json"
9
+
10
+ # 팀 데이터 초기화
11
+ init_team() {
12
+ if [ ! -f "$TEAM_FILE" ]; then
13
+ cat > "$TEAM_FILE" << 'EOF'
14
+ {
15
+ "version": "1.0.0",
16
+ "teamName": "",
17
+ "members": {},
18
+ "sharedRecommendations": [],
19
+ "sharedSettings": {
20
+ "defaultPlugins": [],
21
+ "blockedPlugins": [],
22
+ "categories": []
23
+ },
24
+ "stats": {
25
+ "totalMembers": 0,
26
+ "activeMembers": 0,
27
+ "totalPluginsUsed": 0,
28
+ "topPlugins": []
29
+ },
30
+ "createdAt": "",
31
+ "updatedAt": ""
32
+ }
33
+ EOF
34
+ # Set timestamps
35
+ local now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
36
+ jq --arg ts "$now" '.createdAt = $ts | .updatedAt = $ts' "$TEAM_FILE" > "$TEAM_FILE.tmp" && mv "$TEAM_FILE.tmp" "$TEAM_FILE"
37
+ fi
38
+ }
39
+
40
+ # 팀원 등록/업데이트
41
+ register_member() {
42
+ local username="${1:-$USER}"
43
+ local git_name=$(git config user.name 2>/dev/null || echo "$username")
44
+ local git_email=$(git config user.email 2>/dev/null || echo "")
45
+ local now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
46
+
47
+ init_team
48
+
49
+ if ! command -v jq &> /dev/null; then
50
+ echo "Error: jq required"
51
+ return 1
52
+ fi
53
+
54
+ # Check if member exists
55
+ local exists=$(jq -r --arg u "$username" '.members[$u] // null' "$TEAM_FILE")
56
+
57
+ if [ "$exists" = "null" ]; then
58
+ # New member
59
+ jq --arg u "$username" --arg n "$git_name" --arg e "$git_email" --arg ts "$now" '
60
+ .members[$u] = {
61
+ "name": $n,
62
+ "email": $e,
63
+ "joinedAt": $ts,
64
+ "lastActive": $ts,
65
+ "sessions": 1,
66
+ "pluginsUsed": [],
67
+ "topPlugins": []
68
+ } |
69
+ .stats.totalMembers = (.members | length)
70
+ ' "$TEAM_FILE" > "$TEAM_FILE.tmp" && mv "$TEAM_FILE.tmp" "$TEAM_FILE"
71
+ echo "Member registered: $username ($git_name)"
72
+ else
73
+ # Update last active
74
+ jq --arg u "$username" --arg ts "$now" '
75
+ .members[$u].lastActive = $ts |
76
+ .members[$u].sessions = ((.members[$u].sessions // 0) + 1)
77
+ ' "$TEAM_FILE" > "$TEAM_FILE.tmp" && mv "$TEAM_FILE.tmp" "$TEAM_FILE"
78
+ echo "Member updated: $username"
79
+ fi
80
+ }
81
+
82
+ # 팀원 플러그인 사용 기록
83
+ record_plugin_usage() {
84
+ local username="${1:-$USER}"
85
+ local plugin="$2"
86
+ local now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
87
+
88
+ if [ -z "$plugin" ]; then
89
+ echo "Usage: record_plugin_usage <username> <plugin>"
90
+ return 1
91
+ fi
92
+
93
+ init_team
94
+
95
+ jq --arg u "$username" --arg p "$plugin" --arg ts "$now" '
96
+ # Add to member pluginsUsed if not exists
97
+ if .members[$u].pluginsUsed then
98
+ if (.members[$u].pluginsUsed | index($p)) == null then
99
+ .members[$u].pluginsUsed += [$p]
100
+ else .
101
+ end
102
+ else . end |
103
+ # Update last active
104
+ .members[$u].lastActive = $ts
105
+ ' "$TEAM_FILE" > "$TEAM_FILE.tmp" && mv "$TEAM_FILE.tmp" "$TEAM_FILE"
106
+ }
107
+
108
+ # 팀 통계 계산
109
+ calculate_stats() {
110
+ init_team
111
+
112
+ if ! command -v jq &> /dev/null; then
113
+ echo "Error: jq required"
114
+ return 1
115
+ fi
116
+
117
+ local now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
118
+ local week_ago=$(date -v-7d +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -d "7 days ago" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null)
119
+
120
+ # Calculate active members (active in last 7 days) and plugin stats
121
+ jq --arg ts "$now" --arg week "$week_ago" '
122
+ # Count active members
123
+ .stats.activeMembers = ([.members | to_entries[] | select(.value.lastActive > $week)] | length) |
124
+
125
+ # Count total plugins used
126
+ .stats.totalPluginsUsed = ([.members | to_entries[].value.pluginsUsed[]?] | unique | length) |
127
+
128
+ # Get top plugins (most used across team)
129
+ .stats.topPlugins = (
130
+ [.members | to_entries[].value.pluginsUsed[]?] |
131
+ group_by(.) |
132
+ map({plugin: .[0], count: length}) |
133
+ sort_by(-.count) |
134
+ .[:5]
135
+ ) |
136
+
137
+ .updatedAt = $ts
138
+ ' "$TEAM_FILE" > "$TEAM_FILE.tmp" && mv "$TEAM_FILE.tmp" "$TEAM_FILE"
139
+
140
+ echo "Stats updated"
141
+ }
142
+
143
+ # 팀 추천 공유
144
+ share_recommendation() {
145
+ local plugin="$1"
146
+ local reason="${2:-Recommended by team member}"
147
+ local username="${3:-$USER}"
148
+ local now=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
149
+
150
+ if [ -z "$plugin" ]; then
151
+ echo "Usage: share_recommendation <plugin> [reason] [username]"
152
+ return 1
153
+ fi
154
+
155
+ init_team
156
+
157
+ jq --arg p "$plugin" --arg r "$reason" --arg u "$username" --arg ts "$now" '
158
+ .sharedRecommendations += [{
159
+ "plugin": $p,
160
+ "reason": $r,
161
+ "sharedBy": $u,
162
+ "sharedAt": $ts,
163
+ "votes": 1
164
+ }] |
165
+ # Remove duplicates, keep latest
166
+ .sharedRecommendations = (
167
+ .sharedRecommendations |
168
+ group_by(.plugin) |
169
+ map(sort_by(.sharedAt) | last)
170
+ )
171
+ ' "$TEAM_FILE" > "$TEAM_FILE.tmp" && mv "$TEAM_FILE.tmp" "$TEAM_FILE"
172
+
173
+ echo "Shared recommendation: $plugin"
174
+ }
175
+
176
+ # 공유 추천 목록
177
+ list_shared_recommendations() {
178
+ init_team
179
+
180
+ jq -r '.sharedRecommendations | sort_by(-.votes) | .[] | "\(.plugin) - \(.reason) (by \(.sharedBy))"' "$TEAM_FILE"
181
+ }
182
+
183
+ # 팀 설정: 기본 플러그인 추가
184
+ add_default_plugin() {
185
+ local plugin="$1"
186
+
187
+ if [ -z "$plugin" ]; then
188
+ echo "Usage: add_default_plugin <plugin>"
189
+ return 1
190
+ fi
191
+
192
+ init_team
193
+
194
+ jq --arg p "$plugin" '
195
+ if (.sharedSettings.defaultPlugins | index($p)) == null then
196
+ .sharedSettings.defaultPlugins += [$p]
197
+ else . end
198
+ ' "$TEAM_FILE" > "$TEAM_FILE.tmp" && mv "$TEAM_FILE.tmp" "$TEAM_FILE"
199
+
200
+ echo "Default plugin added: $plugin"
201
+ }
202
+
203
+ # 팀 설정: 플러그인 차단
204
+ block_plugin() {
205
+ local plugin="$1"
206
+
207
+ if [ -z "$plugin" ]; then
208
+ echo "Usage: block_plugin <plugin>"
209
+ return 1
210
+ fi
211
+
212
+ init_team
213
+
214
+ jq --arg p "$plugin" '
215
+ if (.sharedSettings.blockedPlugins | index($p)) == null then
216
+ .sharedSettings.blockedPlugins += [$p]
217
+ else . end
218
+ ' "$TEAM_FILE" > "$TEAM_FILE.tmp" && mv "$TEAM_FILE.tmp" "$TEAM_FILE"
219
+
220
+ echo "Plugin blocked: $plugin"
221
+ }
222
+
223
+ # 팀 멤버 목록
224
+ list_members() {
225
+ init_team
226
+
227
+ echo "=== Team Members ==="
228
+ jq -r '.members | to_entries[] | "\(.key): \(.value.name) (sessions: \(.value.sessions), last: \(.value.lastActive | split("T")[0]))"' "$TEAM_FILE"
229
+ }
230
+
231
+ # 팀 요약
232
+ summary() {
233
+ init_team
234
+ calculate_stats >/dev/null
235
+
236
+ echo "=== Team Summary ==="
237
+ echo ""
238
+ jq -r '
239
+ "Team: \(.teamName // "Unnamed")",
240
+ "Members: \(.stats.totalMembers) total, \(.stats.activeMembers) active",
241
+ "Plugins: \(.stats.totalPluginsUsed) used",
242
+ "",
243
+ "Top Plugins:",
244
+ (.stats.topPlugins[:3][] | " - \(.plugin): \(.count) users"),
245
+ "",
246
+ "Shared Recommendations: \(.sharedRecommendations | length)",
247
+ (.sharedRecommendations[:3][] | " - \(.plugin): \(.reason)")
248
+ ' "$TEAM_FILE" 2>/dev/null || echo "No team data yet"
249
+ }
250
+
251
+ # 팀 추천 JSON 출력 (scout 통합용)
252
+ get_team_recommendations_json() {
253
+ init_team
254
+
255
+ jq '{
256
+ sharedRecommendations: .sharedRecommendations,
257
+ defaultPlugins: .sharedSettings.defaultPlugins,
258
+ blockedPlugins: .sharedSettings.blockedPlugins,
259
+ topPlugins: .stats.topPlugins
260
+ }' "$TEAM_FILE"
261
+ }
262
+
263
+ # 플러그인 차단 여부 확인
264
+ is_plugin_blocked() {
265
+ local plugin="$1"
266
+
267
+ if [ -z "$plugin" ]; then
268
+ echo "false"
269
+ return
270
+ fi
271
+
272
+ init_team
273
+
274
+ local blocked=$(jq -r --arg p "$plugin" '
275
+ if (.sharedSettings.blockedPlugins | index($p)) != null then "true" else "false" end
276
+ ' "$TEAM_FILE")
277
+
278
+ echo "$blocked"
279
+ }
280
+
281
+ # 추천 플러그인 필터링 (차단된 것 제외)
282
+ filter_blocked_plugins() {
283
+ local plugins_json="$1"
284
+
285
+ init_team
286
+
287
+ echo "$plugins_json" | jq --slurpfile team "$TEAM_FILE" '
288
+ . - ($team[0].sharedSettings.blockedPlugins // [])
289
+ '
290
+ }
291
+
292
+ # 팀 이름 설정
293
+ set_team_name() {
294
+ local name="$1"
295
+
296
+ if [ -z "$name" ]; then
297
+ echo "Usage: set_team_name <name>"
298
+ return 1
299
+ fi
300
+
301
+ init_team
302
+
303
+ jq --arg n "$name" '.teamName = $n' "$TEAM_FILE" > "$TEAM_FILE.tmp" && mv "$TEAM_FILE.tmp" "$TEAM_FILE"
304
+
305
+ echo "Team name set: $name"
306
+ }
307
+
308
+ # CLI 인터페이스
309
+ case "$1" in
310
+ init)
311
+ init_team
312
+ echo "Team data initialized"
313
+ ;;
314
+ register)
315
+ register_member "$2"
316
+ ;;
317
+ record)
318
+ record_plugin_usage "$2" "$3"
319
+ ;;
320
+ stats)
321
+ calculate_stats
322
+ ;;
323
+ share)
324
+ share_recommendation "$2" "$3" "$4"
325
+ ;;
326
+ shared)
327
+ list_shared_recommendations
328
+ ;;
329
+ default)
330
+ add_default_plugin "$2"
331
+ ;;
332
+ block)
333
+ block_plugin "$2"
334
+ ;;
335
+ members)
336
+ list_members
337
+ ;;
338
+ summary)
339
+ summary
340
+ ;;
341
+ name)
342
+ set_team_name "$2"
343
+ ;;
344
+ recommendations)
345
+ get_team_recommendations_json
346
+ ;;
347
+ is-blocked)
348
+ is_plugin_blocked "$2"
349
+ ;;
350
+ filter)
351
+ filter_blocked_plugins "$2"
352
+ ;;
353
+ *)
354
+ echo "Usage: $0 {init|register|record|stats|share|shared|default|block|members|summary|name|recommendations|is-blocked|filter}"
355
+ echo ""
356
+ echo "Commands:"
357
+ echo " init - Initialize team data"
358
+ echo " register [username] - Register/update team member"
359
+ echo " record <user> <plugin> - Record plugin usage"
360
+ echo " stats - Calculate team statistics"
361
+ echo " share <plugin> [reason] - Share a recommendation"
362
+ echo " shared - List shared recommendations"
363
+ echo " default <plugin> - Add default plugin"
364
+ echo " block <plugin> - Block a plugin"
365
+ echo " members - List team members"
366
+ echo " summary - Show team summary"
367
+ echo " name <name> - Set team name"
368
+ ;;
369
+ esac