solmate-skills 2.0.4 → 2.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.
- package/AGENTS.md +19 -6
- package/README.md +71 -8
- package/bin/cli.js +42 -2
- package/docs-business/agents/openai.yaml +4 -0
- package/docs-dev/SKILL.md +17 -0
- package/docs-dev/agents/openai.yaml +4 -0
- package/docs-pitch/agents/openai.yaml +4 -0
- package/docs-plan/SKILL.md +34 -5
- package/docs-plan/agents/openai.yaml +4 -0
- package/ext-k-skill/scripts/check-setup.sh +29 -0
- package/ext-k-skill/scripts/run-k-skill-proxy.sh +15 -0
- package/ext-k-skill/scripts/validate-skills.sh +56 -0
- package/hooks/install.sh +157 -0
- package/hooks/suggest-skills.sh +109 -0
- package/hooks/verify-suggest.sh +42 -0
- package/hooks/watch-files.sh +96 -0
- package/manage-collaboration/agents/openai.yaml +4 -0
- package/manage-decisions/agents/openai.yaml +4 -0
- package/manage-skills/SKILL.md +8 -1
- package/manage-skills/agents/openai.yaml +4 -0
- package/package.json +1 -1
- package/role-team-lead/agents/openai.yaml +4 -0
- package/role-team-member/agents/openai.yaml +4 -0
- package/rules-dev/agents/openai.yaml +4 -0
- package/rules-docs/agents/openai.yaml +4 -0
- package/rules-product/SKILL.md +105 -6
- package/rules-product/agents/openai.yaml +4 -0
- package/rules-react/SKILL.md +10 -7
- package/rules-react/agents/openai.yaml +4 -0
- package/rules-react/scripts/fetch-stitch.sh +30 -0
- package/rules-workflow/SKILL.md +17 -2
- package/rules-workflow/agents/openai.yaml +4 -0
- package/tools-obsidian/agents/openai.yaml +4 -0
- package/tools-shadcn/agents/openai.yaml +4 -0
- package/tools-shadcn/scripts/verify-setup.sh +134 -0
- package/verify-code/SKILL.md +17 -1
- package/verify-code/agents/openai.yaml +4 -0
- package/verify-docs/SKILL.md +38 -5
- package/verify-docs/agents/openai.yaml +4 -0
- package/verify-drizzle-schema/agents/openai.yaml +4 -0
- package/verify-implementation/SKILL.md +66 -12
- package/verify-implementation/agents/openai.yaml +4 -0
- package/verify-performance/SKILL.md +16 -0
- package/verify-performance/agents/openai.yaml +4 -0
- package/verify-security/agents/openai.yaml +4 -0
- package/verify-skills/SKILL.md +179 -0
- package/verify-skills/agents/openai.yaml +4 -0
- package/verify-ui/SKILL.md +128 -0
- package/verify-ui/agents/openai.yaml +4 -0
package/hooks/install.sh
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# solmate-skills: install.sh
|
|
3
|
+
# Purpose: Install Solmate hook scripts into the current project's .claude/ directory
|
|
4
|
+
# and merge hook configuration into .claude/settings.json.
|
|
5
|
+
# Usage: bash .agent/skills/hooks/install.sh
|
|
6
|
+
# (or run from any location: bash <path-to-hooks>/install.sh)
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
|
+
PROJECT_ROOT="$(pwd)"
|
|
12
|
+
CLAUDE_DIR="$PROJECT_ROOT/.claude"
|
|
13
|
+
HOOKS_DIR="$CLAUDE_DIR/hooks"
|
|
14
|
+
SETTINGS_FILE="$CLAUDE_DIR/settings.json"
|
|
15
|
+
|
|
16
|
+
echo "Solmate Skills — Hook Installer"
|
|
17
|
+
echo "Project: $PROJECT_ROOT"
|
|
18
|
+
echo ""
|
|
19
|
+
|
|
20
|
+
# --- Step 1: Create .claude/hooks/ ---
|
|
21
|
+
mkdir -p "$HOOKS_DIR"
|
|
22
|
+
echo "[1/4] Created $HOOKS_DIR"
|
|
23
|
+
|
|
24
|
+
# --- Step 2: Copy hook scripts ---
|
|
25
|
+
cp "$SCRIPT_DIR/suggest-skills.sh" "$HOOKS_DIR/solmate-suggest.sh"
|
|
26
|
+
cp "$SCRIPT_DIR/watch-files.sh" "$HOOKS_DIR/solmate-watch.sh"
|
|
27
|
+
cp "$SCRIPT_DIR/verify-suggest.sh" "$HOOKS_DIR/solmate-verify-suggest.sh"
|
|
28
|
+
chmod +x "$HOOKS_DIR/solmate-suggest.sh"
|
|
29
|
+
chmod +x "$HOOKS_DIR/solmate-watch.sh"
|
|
30
|
+
chmod +x "$HOOKS_DIR/solmate-verify-suggest.sh"
|
|
31
|
+
echo "[2/4] Copied hook scripts:"
|
|
32
|
+
echo " .claude/hooks/solmate-suggest.sh (UserPromptSubmit)"
|
|
33
|
+
echo " .claude/hooks/solmate-watch.sh (PreToolUse)"
|
|
34
|
+
echo " .claude/hooks/solmate-verify-suggest.sh (Stop)"
|
|
35
|
+
|
|
36
|
+
# --- Step 3: Merge hook config into settings.json ---
|
|
37
|
+
echo "[3/4] Merging hook config into $SETTINGS_FILE"
|
|
38
|
+
|
|
39
|
+
python3 - "$SETTINGS_FILE" <<'PYEOF'
|
|
40
|
+
import sys, json, os
|
|
41
|
+
|
|
42
|
+
settings_path = sys.argv[1]
|
|
43
|
+
|
|
44
|
+
# Load existing settings or start fresh
|
|
45
|
+
if os.path.exists(settings_path):
|
|
46
|
+
with open(settings_path, 'r') as f:
|
|
47
|
+
try:
|
|
48
|
+
settings = json.load(f)
|
|
49
|
+
except json.JSONDecodeError:
|
|
50
|
+
print(f" WARNING: {settings_path} has invalid JSON. Backing up and starting fresh.")
|
|
51
|
+
os.rename(settings_path, settings_path + '.bak')
|
|
52
|
+
settings = {}
|
|
53
|
+
else:
|
|
54
|
+
settings = {}
|
|
55
|
+
|
|
56
|
+
hooks = settings.setdefault('hooks', {})
|
|
57
|
+
|
|
58
|
+
# --- UserPromptSubmit hook ---
|
|
59
|
+
suggest_cmd = "bash .claude/hooks/solmate-suggest.sh"
|
|
60
|
+
submit_hooks = hooks.setdefault('UserPromptSubmit', [])
|
|
61
|
+
|
|
62
|
+
# Check for duplicate
|
|
63
|
+
already_has_suggest = any(
|
|
64
|
+
h.get('command') == suggest_cmd
|
|
65
|
+
for entry in submit_hooks
|
|
66
|
+
for h in entry.get('hooks', [])
|
|
67
|
+
)
|
|
68
|
+
if not already_has_suggest:
|
|
69
|
+
submit_hooks.append({
|
|
70
|
+
"hooks": [{
|
|
71
|
+
"type": "command",
|
|
72
|
+
"command": suggest_cmd,
|
|
73
|
+
"timeout": 5
|
|
74
|
+
}]
|
|
75
|
+
})
|
|
76
|
+
print(" Added: UserPromptSubmit → solmate-suggest.sh")
|
|
77
|
+
else:
|
|
78
|
+
print(" Skipped (already exists): UserPromptSubmit → solmate-suggest.sh")
|
|
79
|
+
|
|
80
|
+
# --- PreToolUse hook ---
|
|
81
|
+
watch_cmd = "bash .claude/hooks/solmate-watch.sh"
|
|
82
|
+
pre_hooks = hooks.setdefault('PreToolUse', [])
|
|
83
|
+
|
|
84
|
+
already_has_watch = any(
|
|
85
|
+
h.get('command') == watch_cmd
|
|
86
|
+
for entry in pre_hooks
|
|
87
|
+
for h in entry.get('hooks', [])
|
|
88
|
+
)
|
|
89
|
+
if not already_has_watch:
|
|
90
|
+
pre_hooks.append({
|
|
91
|
+
"matcher": "Read|Write|Edit|Bash",
|
|
92
|
+
"hooks": [{
|
|
93
|
+
"type": "command",
|
|
94
|
+
"command": watch_cmd,
|
|
95
|
+
"timeout": 5
|
|
96
|
+
}]
|
|
97
|
+
})
|
|
98
|
+
print(" Added: PreToolUse (Read|Write|Edit|Bash) → solmate-watch.sh")
|
|
99
|
+
else:
|
|
100
|
+
print(" Skipped (already exists): PreToolUse → solmate-watch.sh")
|
|
101
|
+
|
|
102
|
+
# --- Stop hook ---
|
|
103
|
+
verify_cmd = "bash .claude/hooks/solmate-verify-suggest.sh"
|
|
104
|
+
stop_hooks = hooks.setdefault('Stop', [])
|
|
105
|
+
|
|
106
|
+
already_has_verify = any(
|
|
107
|
+
h.get('command') == verify_cmd
|
|
108
|
+
for entry in stop_hooks
|
|
109
|
+
for h in entry.get('hooks', [])
|
|
110
|
+
)
|
|
111
|
+
if not already_has_verify:
|
|
112
|
+
stop_hooks.append({
|
|
113
|
+
"hooks": [{
|
|
114
|
+
"type": "command",
|
|
115
|
+
"command": verify_cmd,
|
|
116
|
+
"timeout": 10,
|
|
117
|
+
"statusMessage": "변경 파일 분석 중..."
|
|
118
|
+
}]
|
|
119
|
+
})
|
|
120
|
+
print(" Added: Stop → solmate-verify-suggest.sh")
|
|
121
|
+
else:
|
|
122
|
+
print(" Skipped (already exists): Stop → solmate-verify-suggest.sh")
|
|
123
|
+
|
|
124
|
+
# Write back
|
|
125
|
+
os.makedirs(os.path.dirname(settings_path), exist_ok=True)
|
|
126
|
+
with open(settings_path, 'w') as f:
|
|
127
|
+
json.dump(settings, f, indent=2, ensure_ascii=False)
|
|
128
|
+
f.write('\n')
|
|
129
|
+
|
|
130
|
+
print(f" Saved: {settings_path}")
|
|
131
|
+
PYEOF
|
|
132
|
+
|
|
133
|
+
# --- Step 4: Add .claude/hooks/ to .gitignore if not already there ---
|
|
134
|
+
GITIGNORE="$PROJECT_ROOT/.gitignore"
|
|
135
|
+
if [ -f "$GITIGNORE" ]; then
|
|
136
|
+
if ! grep -q "\.claude/hooks/" "$GITIGNORE" 2>/dev/null; then
|
|
137
|
+
echo "" >> "$GITIGNORE"
|
|
138
|
+
echo "# Solmate hook scripts (project-local)" >> "$GITIGNORE"
|
|
139
|
+
echo ".claude/hooks/" >> "$GITIGNORE"
|
|
140
|
+
echo "[4/4] Added .claude/hooks/ to .gitignore"
|
|
141
|
+
else
|
|
142
|
+
echo "[4/4] .gitignore already excludes .claude/hooks/"
|
|
143
|
+
fi
|
|
144
|
+
else
|
|
145
|
+
echo "[4/4] No .gitignore found — skipping"
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
echo ""
|
|
149
|
+
echo "Done. Hooks are active in this project."
|
|
150
|
+
echo ""
|
|
151
|
+
echo "What was installed:"
|
|
152
|
+
echo " UserPromptSubmit → 프롬프트 키워드 감지 → 관련 스킬 제안"
|
|
153
|
+
echo " PreToolUse → 편집 중인 파일 패턴 감지 → 관련 스킬 제안"
|
|
154
|
+
echo " Stop → 작업 완료 후 변경 파일 분석 → verify-* 스킬 실행 시점 알림"
|
|
155
|
+
echo ""
|
|
156
|
+
echo "To review or disable hooks, open /hooks in Claude Code."
|
|
157
|
+
echo "To uninstall, remove .claude/hooks/ and the 'hooks' section from .claude/settings.json."
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# solmate-skills: suggest-skills.sh
|
|
3
|
+
# Event: UserPromptSubmit
|
|
4
|
+
# Purpose: Detect keywords in user prompt and inject skill suggestions as context.
|
|
5
|
+
# Output: JSON with hookSpecificOutput.additionalContext (non-blocking)
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
# Read stdin JSON
|
|
10
|
+
INPUT=$(cat)
|
|
11
|
+
|
|
12
|
+
# Extract the user prompt text
|
|
13
|
+
PROMPT=$(echo "$INPUT" | python3 -c "
|
|
14
|
+
import sys, json
|
|
15
|
+
data = json.load(sys.stdin)
|
|
16
|
+
# UserPromptSubmit provides 'prompt' field
|
|
17
|
+
print(data.get('prompt', ''))
|
|
18
|
+
" 2>/dev/null || echo "")
|
|
19
|
+
|
|
20
|
+
if [ -z "$PROMPT" ]; then
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
SUGGESTIONS=""
|
|
25
|
+
|
|
26
|
+
# --- Keyword matching (Korean + English) ---
|
|
27
|
+
|
|
28
|
+
# Decision / Design → manage-decisions
|
|
29
|
+
if echo "$PROMPT" | grep -qiE '결정|설계|어떻게 할|어떤 방식|DB 스키마|테이블|API 구조|아키텍처|폴더 구조|기능 범위|MVP|스택|라이브러리|어떤 거|어떤게'; then
|
|
30
|
+
SUGGESTIONS="$SUGGESTIONS\n- 결정이 필요한 상황입니다. \`/manage-decisions\`를 실행하면 유형별 질문 템플릿으로 대화를 통해 결정을 이끌어냅니다."
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Security → verify-security
|
|
34
|
+
if echo "$PROMPT" | grep -qiE '보안|security|취약|OWASP|인증|인가|token|jwt|secret|API ?key|sql|injection|xss|csrf'; then
|
|
35
|
+
SUGGESTIONS="$SUGGESTIONS\n- 보안 관련 작업입니다. \`/verify-security\`로 OWASP Top 10 기준 점검을 실행하세요."
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# Performance → verify-performance
|
|
39
|
+
if echo "$PROMPT" | grep -qiE '성능|performance|lighthouse|느리|느림|최적화|LCP|CLS|FID|번들|bundle|이미지 최적|lazy|loading'; then
|
|
40
|
+
SUGGESTIONS="$SUGGESTIONS\n- 성능 관련 작업입니다. \`/verify-performance\`로 Lighthouse 및 Core Web Vitals 점검을 실행하세요."
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# PR / Commit / Code review → verify-code
|
|
44
|
+
if echo "$PROMPT" | grep -qiE 'PR|pull ?request|코드 ?리뷰|review|commit|머지|merge|배포 전|pre-deploy'; then
|
|
45
|
+
SUGGESTIONS="$SUGGESTIONS\n- PR 또는 배포 전 점검입니다. \`/verify-code\`로 코드 품질을 종합 리뷰하고, \`/verify-implementation\`으로 전체 verify-* 스킬을 통합 실행하세요."
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Documentation → verify-docs / docs-plan / docs-dev
|
|
49
|
+
if echo "$PROMPT" | grep -qiE '문서|docs?|README|VISION|LEAN_CANVAS|PRODUCT_SPECS|API_SPECS|DB_SCHEMA|ROADMAP|백로그|backlog'; then
|
|
50
|
+
SUGGESTIONS="$SUGGESTIONS\n- 문서 작업입니다. 기획·UI 문서는 \`/docs-plan\`, 기술·진행·QA 문서는 \`/docs-dev\`, 문서 구조 검증은 \`/verify-docs\`를 사용하세요."
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# Feature implementation / workflow → rules-workflow
|
|
54
|
+
if echo "$PROMPT" | grep -qiE '기능 ?구현|구현|implement|feature|작업 ?시작|어디서 ?시작|어떻게 ?시작|개발 ?시작|시작할게'; then
|
|
55
|
+
SUGGESTIONS="$SUGGESTIONS\n- 기능 구현을 시작하려 합니다. 먼저 \`/rules-product\`로 현재 Phase를 진단하고 Flow Status Block을 확인한 뒤, \`/rules-workflow\`로 18단계 구현 워크플로우를 진행하세요."
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# Flow position question → rules-product
|
|
59
|
+
if echo "$PROMPT" | grep -qiE '지금.*어디|현재.*단계|현재.*위치|다음.*뭐|어느.*Phase|flow status|플로우.*상태|단계.*확인'; then
|
|
60
|
+
SUGGESTIONS="$SUGGESTIONS\n- 현재 위치 확인 요청입니다. \`/rules-product\` 기준 Flow Status Block으로 현재 Phase, Gate, 다음 액션을 먼저 보고하세요."
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# React / UI component → rules-react
|
|
64
|
+
if echo "$PROMPT" | grep -qiE 'React|컴포넌트|component|페이지|page|UI|화면|shadcn|tailwind'; then
|
|
65
|
+
SUGGESTIONS="$SUGGESTIONS\n- React/UI 작업입니다. \`/rules-react\`로 컴포넌트 설계 기준을 확인하고, 구현 후 \`/verify-ui\`로 화면 문서와 사용자 동선 정합성을 검증하세요."
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# UI verification explicit request → verify-ui
|
|
69
|
+
if echo "$PROMPT" | grep -qiE 'UI ?검증|UX ?검증|화면 ?검증|화면.*맞|동선.*검증|상태별 UI|empty state|loading state|error state'; then
|
|
70
|
+
SUGGESTIONS="$SUGGESTIONS\n- UI 검증 요청입니다. \`/verify-ui\`로 화면 구조, 사용자 동선, 데이터 흐름, 상태별 UI를 점검하세요."
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
# Skill package changes → verify-skills
|
|
74
|
+
if echo "$PROMPT" | grep -qiE '스킬.*검증|skill.*verify|SKILL\.md|openai\.yaml|solmate-skills|npm pack|패키지.*검증'; then
|
|
75
|
+
SUGGESTIONS="$SUGGESTIONS\n- 스킬 패키지 작업입니다. \`/verify-skills\`로 SKILL.md, agents/openai.yaml, CLI 목록, README/AGENTS, npm pack을 검증하세요."
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# Drizzle / DB schema → verify-drizzle-schema
|
|
79
|
+
if echo "$PROMPT" | grep -qiE 'drizzle|schema\.ts|마이그레이션|migration|pgTable|sqliteTable'; then
|
|
80
|
+
SUGGESTIONS="$SUGGESTIONS\n- Drizzle 스키마 작업입니다. \`/verify-drizzle-schema\`로 스키마 정합성을 검증하세요."
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# New project / product pipeline → rules-product
|
|
84
|
+
if echo "$PROMPT" | grep -qiE '새 프로젝트|신규 프로젝트|프로젝트 시작|어디서 시작|뭐부터|처음부터|from scratch'; then
|
|
85
|
+
SUGGESTIONS="$SUGGESTIONS\n- 새 프로젝트입니다. \`/rules-product\`를 실행하면 현재 단계를 자동 진단하고 올바른 스킬로 안내합니다."
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
# Pitch deck / business plan → docs-pitch / docs-business
|
|
89
|
+
if echo "$PROMPT" | grep -qiE '피치|pitch|투자|investor|사업 ?계획|business ?plan|데모데이|해커톤'; then
|
|
90
|
+
SUGGESTIONS="$SUGGESTIONS\n- 발표·투자 자료 작업입니다. 피치덱은 \`/docs-pitch\`, 사업계획서는 \`/docs-business\`를 사용하세요."
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# If no suggestions, exit silently
|
|
94
|
+
if [ -z "$SUGGESTIONS" ]; then
|
|
95
|
+
exit 0
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
# Output JSON with additionalContext (non-blocking)
|
|
99
|
+
python3 -c "
|
|
100
|
+
import json, sys
|
|
101
|
+
suggestions = sys.argv[1]
|
|
102
|
+
output = {
|
|
103
|
+
'hookSpecificOutput': {
|
|
104
|
+
'hookEventName': 'UserPromptSubmit',
|
|
105
|
+
'additionalContext': '[Solmate Skills 제안]\n' + suggestions.strip()
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
print(json.dumps(output))
|
|
109
|
+
" "$SUGGESTIONS"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Claude Stop 훅: git 변경 파일을 분석하여 적절한 verify-* 스킬을 제안합니다
|
|
3
|
+
|
|
4
|
+
python3 - <<'PYEOF'
|
|
5
|
+
import subprocess, json
|
|
6
|
+
|
|
7
|
+
r = subprocess.run(['git', 'diff', '--name-only', 'HEAD'], capture_output=True, text=True)
|
|
8
|
+
files = [f for f in r.stdout.strip().split('\n') if f]
|
|
9
|
+
|
|
10
|
+
if not files:
|
|
11
|
+
exit()
|
|
12
|
+
|
|
13
|
+
s = []
|
|
14
|
+
|
|
15
|
+
if any('schema' in f and (f.endswith('.ts') or f.endswith('.sql')) for f in files):
|
|
16
|
+
s.append(' DB 스키마 변경 감지 → /verify-drizzle-schema')
|
|
17
|
+
|
|
18
|
+
if any(f.endswith(('.tsx', '.jsx')) or f.startswith('docs/02_UI_Screens/') for f in files):
|
|
19
|
+
s.append(' UI/화면 변경 감지 → /verify-ui')
|
|
20
|
+
|
|
21
|
+
if any(any(k in f.lower() for k in ('auth', 'middleware', 'api', 'route', 'token', 'session'))
|
|
22
|
+
and (f.endswith('.ts') or f.endswith('.tsx')) for f in files):
|
|
23
|
+
s.append(' 인증/API 파일 변경 감지 → /verify-security')
|
|
24
|
+
|
|
25
|
+
if any(f.endswith('.ts') or f.endswith('.tsx') for f in files):
|
|
26
|
+
s.append(' 코드 파일 변경 감지 → /verify-code')
|
|
27
|
+
|
|
28
|
+
if any(f.endswith('.md') for f in files):
|
|
29
|
+
s.append(' 문서 파일 변경 감지 → /verify-docs')
|
|
30
|
+
|
|
31
|
+
if any(
|
|
32
|
+
f.endswith('/SKILL.md')
|
|
33
|
+
or f.endswith('/agents/openai.yaml')
|
|
34
|
+
or f in ('bin/cli.js', 'package.json', 'README.md', 'AGENTS.md')
|
|
35
|
+
for f in files
|
|
36
|
+
):
|
|
37
|
+
s.append(' 스킬 패키지 변경 감지 → /verify-skills')
|
|
38
|
+
|
|
39
|
+
if s:
|
|
40
|
+
msg = '[ 검증 시점 알림 ]\n' + '\n'.join(s)
|
|
41
|
+
print(json.dumps({'systemMessage': msg}))
|
|
42
|
+
PYEOF
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# solmate-skills: watch-files.sh
|
|
3
|
+
# Event: PreToolUse (matcher: Read|Write|Edit|Bash)
|
|
4
|
+
# Purpose: Detect file patterns being modified and inject relevant skill suggestions.
|
|
5
|
+
# Output: JSON with hookSpecificOutput.additionalContext (non-blocking)
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
INPUT=$(cat)
|
|
10
|
+
|
|
11
|
+
# Extract file path and tool name
|
|
12
|
+
FILE_PATH=$(echo "$INPUT" | python3 -c "
|
|
13
|
+
import sys, json
|
|
14
|
+
data = json.load(sys.stdin)
|
|
15
|
+
inp = data.get('tool_input', {})
|
|
16
|
+
# Write/Edit use file_path; Bash use command
|
|
17
|
+
print(inp.get('file_path', inp.get('command', '')))" 2>/dev/null || echo "")
|
|
18
|
+
|
|
19
|
+
TOOL_NAME=$(echo "$INPUT" | python3 -c "
|
|
20
|
+
import sys, json
|
|
21
|
+
data = json.load(sys.stdin)
|
|
22
|
+
print(data.get('tool_name', ''))" 2>/dev/null || echo "")
|
|
23
|
+
|
|
24
|
+
if [ -z "$FILE_PATH" ]; then
|
|
25
|
+
exit 0
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
SUGGESTIONS=""
|
|
29
|
+
|
|
30
|
+
# --- File pattern matching ---
|
|
31
|
+
|
|
32
|
+
# Drizzle schema file → verify-drizzle-schema
|
|
33
|
+
if echo "$FILE_PATH" | grep -qiE 'schema\.(ts|js)|drizzle'; then
|
|
34
|
+
SUGGESTIONS="$SUGGESTIONS\n- Drizzle 스키마 파일을 수정 중입니다. 작업 후 \`/verify-drizzle-schema\`로 스키마 정합성을 검증하세요."
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# .env files → verify-security
|
|
38
|
+
if echo "$FILE_PATH" | grep -qiE '\.env|\.env\.local|\.env\.production|\.env\.example'; then
|
|
39
|
+
SUGGESTIONS="$SUGGESTIONS\n- 환경변수 파일을 수정 중입니다. \`/verify-security\` Check 1(시크릿 노출)을 실행하여 민감 정보 노출 여부를 확인하세요."
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# SKILL.md files → manage-skills
|
|
43
|
+
if echo "$FILE_PATH" | grep -qiE 'SKILL\.md'; then
|
|
44
|
+
SUGGESTIONS="$SUGGESTIONS\n- 스킬 파일을 수정 중입니다. \`/manage-skills\`로 verify 스킬과의 정합성 드리프트를 점검하고, 작업 후 \`/verify-skills\`로 패키지 메타데이터를 검증하세요."
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# Skill metadata / package files → verify-skills
|
|
48
|
+
if echo "$FILE_PATH" | grep -qiE 'agents/openai\.yaml|bin/cli\.js|package\.json|README\.md|AGENTS\.md'; then
|
|
49
|
+
SUGGESTIONS="$SUGGESTIONS\n- 스킬 패키지 메타데이터 또는 배포 파일을 수정 중입니다. 작업 후 \`/verify-skills\`를 실행하세요."
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# UI implementation files → verify-ui
|
|
53
|
+
if echo "$FILE_PATH" | grep -qiE '\.(tsx|jsx)$|docs/02_UI_Screens/.*\.md'; then
|
|
54
|
+
SUGGESTIONS="$SUGGESTIONS\n- UI 구현 또는 화면 문서를 수정 중입니다. 작업 후 \`/verify-ui\`로 화면 구조·동선·상태별 UI 정합성을 검증하세요."
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Page/route files → verify-performance
|
|
58
|
+
if echo "$FILE_PATH" | grep -qiE 'page\.(tsx|jsx|ts|js)|route\.(tsx|jsx|ts|js)|layout\.(tsx|jsx)'; then
|
|
59
|
+
SUGGESTIONS="$SUGGESTIONS\n- 페이지·라우트 파일을 수정 중입니다. 작업 후 \`/verify-performance\`로 Core Web Vitals 및 렌더링 전략을 점검하세요."
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# API route files → verify-security
|
|
63
|
+
if echo "$FILE_PATH" | grep -qiE 'api/.*route\.(ts|js)|api/.*index\.(ts|js)|\bapi\b.*\.(ts|js)'; then
|
|
64
|
+
SUGGESTIONS="$SUGGESTIONS\n- API 라우트 파일을 수정 중입니다. 작업 후 \`/verify-security\` Check 2(인증·인가) 및 Check 5(CSRF)를 점검하세요."
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Auth-related files → verify-security
|
|
68
|
+
if echo "$FILE_PATH" | grep -qiE 'auth\.(ts|js|tsx)|middleware\.(ts|js)|session\.(ts|js)'; then
|
|
69
|
+
SUGGESTIONS="$SUGGESTIONS\n- 인증·미들웨어 파일을 수정 중입니다. \`/verify-security\`로 인증·인가 취약점을 점검하세요."
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# Documentation files → verify-docs
|
|
73
|
+
if echo "$FILE_PATH" | grep -qiE 'docs/(01|02|03|04|05)_.*\.md'; then
|
|
74
|
+
SUGGESTIONS="$SUGGESTIONS\n- 문서 레이어 파일을 수정 중입니다. 작업 후 \`/verify-docs\`로 메타데이터 및 구조 정합성을 검증하세요."
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# AGENTS.md → remind about skill count
|
|
78
|
+
if echo "$FILE_PATH" | grep -qiE 'AGENTS\.md'; then
|
|
79
|
+
SUGGESTIONS="$SUGGESTIONS\n- AGENTS.md를 수정 중입니다. 스킬 목록·개수가 변경된 경우 Section 4의 테이블과 개수를 함께 업데이트하세요."
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
if [ -z "$SUGGESTIONS" ]; then
|
|
83
|
+
exit 0
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
python3 -c "
|
|
87
|
+
import json, sys
|
|
88
|
+
suggestions = sys.argv[1]
|
|
89
|
+
output = {
|
|
90
|
+
'hookSpecificOutput': {
|
|
91
|
+
'hookEventName': 'PreToolUse',
|
|
92
|
+
'additionalContext': '[Solmate Skills 파일 감지]\n' + suggestions.strip()
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
print(json.dumps(output))
|
|
96
|
+
" "$SUGGESTIONS"
|
package/manage-skills/SKILL.md
CHANGED
|
@@ -28,7 +28,14 @@ argument-hint: "[선택사항: 특정 스킬 이름 또는 집중할 영역]"
|
|
|
28
28
|
|
|
29
29
|
| 스킬 | 설명 | 커버 파일 패턴 |
|
|
30
30
|
|------|------|---------------|
|
|
31
|
-
| `verify
|
|
31
|
+
| `verify-docs` | 문서 구조, Backlog Context Lock, UI-First Gate | `docs/**/*.md`, `README.md`, `AGENTS.md` |
|
|
32
|
+
| `verify-ui` | 화면 구현과 UI 문서, 사용자 동선, 상태별 UI 정합성 | `src/**/*.tsx`, `src/**/*.jsx`, `docs/02_UI_Screens/**/*.md` |
|
|
33
|
+
| `verify-code` | 코드 품질, 타입, 로직, 사이드 이펙트 | `src/**/*.{ts,tsx,js,jsx}` |
|
|
34
|
+
| `verify-security` | 인증·인가·입력·시크릿·OWASP 보안 | `auth`, `api`, `route`, `middleware`, `.env`, `db` 관련 파일 |
|
|
35
|
+
| `verify-performance` | Lighthouse, Core Web Vitals, 렌더링·번들 | page/layout/image/font/bundle 관련 파일 |
|
|
36
|
+
| `verify-drizzle-schema` | Drizzle 스키마와 기술 명세 정합성 | `schema.ts`, `schema/*.ts`, migration 파일 |
|
|
37
|
+
| `verify-skills` | 스킬 패키지 메타데이터, CLI, README/AGENTS, npm pack | `*/SKILL.md`, `*/agents/openai.yaml`, `bin/cli.js`, `package.json` |
|
|
38
|
+
| `verify-implementation` | 전체 verify 스킬 통합 실행 | 모든 변경 |
|
|
32
39
|
|
|
33
40
|
## 워크플로우
|
|
34
41
|
|
package/package.json
CHANGED