solmate-skills 2.0.5 → 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 CHANGED
@@ -56,6 +56,15 @@
56
56
  - **파일 네이밍**: 모든 파일명 앞에는 `01_`과 같은 **순번(Numbering)**을 반드시 붙여 생성 순서와 계층을 명확히 한다. (예: `01_VISION.md`, `02_UI_DESIGN.md`)
57
57
  - **Interactive Process**: 문서를 작성할 때 AI가 독단적으로 내용을 채우지 않는다. 초안 작성 전, **반드시 사용자에게 핵심 질문을 던지고 답변을 바탕으로 문서를 작성(Ask before Write)**한다.
58
58
 
59
+ ### 2.7. SVG 다이어그램 산출물 표준 (User Journey & Data Flow)
60
+ - **사용자 동선 SVG 필수화**: 주요 기능·화면 흐름 문서에는 사용자 동선(User Journey / Screen Flow)을 설명하는 SVG 다이어그램을 포함한다.
61
+ - **저장 위치**: 사용자 동선 SVG는 `docs/02_UI_Screens/assets/`에 저장하고, 관련 UI 스크린 문서에서 상대 경로로 참조한다.
62
+ - **데이터 흐름 SVG 필수화**: 주요 기능의 기술 명세에는 데이터 흐름(Data Flow / API-DB-External Service Flow)을 설명하는 SVG 다이어그램을 포함한다.
63
+ - **저장 위치**: 데이터 흐름 SVG는 `docs/03_Technical_Specs/assets/`에 저장하고, 관련 기술 명세 문서에서 상대 경로로 참조한다.
64
+ - **작업 관리 위치**: SVG 작성·수정 작업은 `docs/04_Logic_Progress/00_BACKLOG.md` 또는 `docs/04_Logic_Progress/02_EXECUTION_PLAN.md`에 태스크로 관리한다.
65
+ - **검증 위치**: SVG가 최신 UI·API·DB 구조와 일치하는지 여부는 `docs/05_QA_Validation/`의 QA 체크리스트 또는 검증 문서에서 확인한다.
66
+ - **파일 네이밍**: SVG 파일명에도 순번과 목적을 포함한다. (예: `01_user_journey.svg`, `02_auth_data_flow.svg`)
67
+
59
68
  ## 3. 개발 표준 및 품질
60
69
  - **UI 중심 개발 전략 (UI-First)**: Concept_Design -> UI_Screens -> Technical_Specs -> Logic_Progress 순서를 따른다.
61
70
  - **git commit 필수**: 중요 작업 전 반드시 git commit을 수행한다.
package/README.md CHANGED
@@ -2,17 +2,19 @@
2
2
 
3
3
  Curated skills for Solmate projects. Easily share and install AI tool skills across your team.
4
4
 
5
- ## What's New in 2.0.4
5
+ ## What's New in 2.0.6
6
6
 
7
- `solmate-skills@2.0.4` keeps **Backlog Context Lock** as the current documentation guardrail, adds **UI-First Gate** expectations, and tightens package hygiene for Codex-local settings.
7
+ `solmate-skills@2.0.6` keeps **Backlog Context Lock** as the current documentation guardrail, adds **UI-First Gate** expectations, formalizes SVG diagram outputs, and fixes package hygiene so installable skill scripts are included in the npm tarball.
8
8
 
9
9
  Key changes:
10
10
 
11
11
  - Every backlog task must link to related Concept, UI, Technical Spec, and QA documents.
12
12
  - UI, user paths, data flow, loading states, empty states, and error states must be confirmed before coding.
13
+ - User journey SVG files belong in `docs/02_UI_Screens/assets/`.
14
+ - Data flow SVG files belong in `docs/03_Technical_Specs/assets/`.
13
15
  - `/rules-workflow` now treats linked backlog documents as implementation inputs before coding starts.
14
16
  - `/verify-docs` fails backlog items that omit required related-document fields.
15
- - Local Codex settings under `.codex/` are excluded from the npm package.
17
+ - Local Codex settings under `.codex/` are excluded from the npm package, while skill-owned shell scripts remain publishable.
16
18
 
17
19
  ## Installation
18
20
 
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ secrets_file="${1:-$HOME/.config/k-skill/secrets.env}"
5
+
6
+ missing=0
7
+
8
+ if [[ ! -f "$secrets_file" ]]; then
9
+ echo "missing secrets file: $secrets_file"
10
+ missing=1
11
+ else
12
+ perms=$(stat -f '%Lp' "$secrets_file" 2>/dev/null || stat -c '%a' "$secrets_file" 2>/dev/null)
13
+ if [[ "$perms" != "600" ]]; then
14
+ echo "insecure permissions on $secrets_file: $perms (expected 600)"
15
+ missing=1
16
+ fi
17
+ fi
18
+
19
+ if [[ "$missing" -ne 0 ]]; then
20
+ cat <<EOF
21
+ next steps:
22
+ 1. create ~/.config/k-skill/secrets.env with your credentials
23
+ 2. chmod 0600 ~/.config/k-skill/secrets.env
24
+ 3. run this check again
25
+ EOF
26
+ exit 1
27
+ fi
28
+
29
+ echo "k-skill setup looks usable"
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+ SECRETS_FILE="${KSKILL_SECRETS_FILE:-$HOME/.config/k-skill/secrets.env}"
6
+
7
+ if [[ -f "$SECRETS_FILE" ]]; then
8
+ set -a
9
+ # shellcheck disable=SC1090
10
+ source "$SECRETS_FILE"
11
+ set +a
12
+ fi
13
+
14
+ cd "$ROOT_DIR"
15
+ exec node packages/k-skill-proxy/src/server.js
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5
+ status=0
6
+
7
+ while IFS= read -r -d '' skill_dir; do
8
+ skill_name="$(basename "$skill_dir")"
9
+ skill_file="$skill_dir/SKILL.md"
10
+
11
+ if [[ ! -f "$skill_file" ]]; then
12
+ echo "missing SKILL.md: $skill_name"
13
+ status=1
14
+ continue
15
+ fi
16
+
17
+ if ! head -n 1 "$skill_file" | grep -qx -- "---"; then
18
+ echo "missing frontmatter start: $skill_file"
19
+ status=1
20
+ fi
21
+
22
+ if ! grep -q '^name: ' "$skill_file"; then
23
+ echo "missing name field: $skill_file"
24
+ status=1
25
+ fi
26
+
27
+ if ! grep -q '^description: ' "$skill_file"; then
28
+ echo "missing description field: $skill_file"
29
+ status=1
30
+ fi
31
+
32
+ declared_name="$(sed -n 's/^name: //p' "$skill_file" | head -n 1 | tr -d '"')"
33
+ if [[ "$declared_name" != "$skill_name" ]]; then
34
+ echo "name mismatch: $skill_file declares '$declared_name' but directory is '$skill_name'"
35
+ status=1
36
+ fi
37
+ done < <(
38
+ find "$root" -mindepth 1 -maxdepth 1 -type d \
39
+ ! -name .git \
40
+ ! -name .github \
41
+ ! -name .omx \
42
+ ! -name .changeset \
43
+ ! -name docs \
44
+ ! -name node_modules \
45
+ ! -name packages \
46
+ ! -name python-packages \
47
+ ! -name scripts \
48
+ ! -name examples \
49
+ -print0
50
+ )
51
+
52
+ if [[ "$status" -ne 0 ]]; then
53
+ exit "$status"
54
+ fi
55
+
56
+ echo "skill layout looks valid"
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solmate-skills",
3
- "version": "2.0.5",
3
+ "version": "2.0.6",
4
4
  "description": "Curated skills for Solmate projects",
5
5
  "main": "bin/cli.js",
6
6
  "bin": {
@@ -0,0 +1,30 @@
1
+ #!/bin/bash
2
+ # Copyright 2026 Google LLC
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ URL=$1
17
+ OUTPUT=$2
18
+ if [ -z "$URL" ] || [ -z "$OUTPUT" ]; then
19
+ echo "Usage: $0 <url> <output_path>"
20
+ exit 1
21
+ fi
22
+ echo "Initiating high-reliability fetch for Stitch HTML..."
23
+ curl -L -f -sS --connect-timeout 10 --compressed "$URL" -o "$OUTPUT"
24
+ if [ $? -eq 0 ]; then
25
+ echo "✅ Successfully retrieved HTML at: $OUTPUT"
26
+ exit 0
27
+ else
28
+ echo "❌ Error: Failed to retrieve content. Check TLS/SNI or URL expiration."
29
+ exit 1
30
+ fi
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env bash
2
+ # shadcn/ui Setup Verification Script
3
+ # Validates that a project is correctly configured for shadcn/ui
4
+
5
+ set -e
6
+
7
+ GREEN='\033[0;32m'
8
+ RED='\033[0;31m'
9
+ YELLOW='\033[1;33m'
10
+ NC='\033[0m' # No Color
11
+
12
+ echo "🔍 Verifying shadcn/ui setup..."
13
+ echo ""
14
+
15
+ # Check if components.json exists
16
+ if [ -f "components.json" ]; then
17
+ echo -e "${GREEN}✓${NC} components.json found"
18
+ else
19
+ echo -e "${RED}✗${NC} components.json not found"
20
+ echo -e " ${YELLOW}Run:${NC} npx shadcn@latest init"
21
+ exit 1
22
+ fi
23
+
24
+ # Check if tailwind.config exists
25
+ if [ -f "tailwind.config.js" ] || [ -f "tailwind.config.ts" ]; then
26
+ echo -e "${GREEN}✓${NC} Tailwind config found"
27
+ else
28
+ echo -e "${RED}✗${NC} tailwind.config.js not found"
29
+ echo -e " ${YELLOW}Install Tailwind:${NC} npm install -D tailwindcss postcss autoprefixer"
30
+ exit 1
31
+ fi
32
+
33
+ # Check if tsconfig.json has path aliases
34
+ if [ -f "tsconfig.json" ]; then
35
+ if grep -q '"@/\*"' tsconfig.json; then
36
+ echo -e "${GREEN}✓${NC} Path aliases configured in tsconfig.json"
37
+ else
38
+ echo -e "${YELLOW}⚠${NC} Path aliases not found in tsconfig.json"
39
+ echo " Add to compilerOptions.paths:"
40
+ echo ' "@/*": ["./src/*"]'
41
+ fi
42
+ else
43
+ echo -e "${YELLOW}⚠${NC} tsconfig.json not found (TypeScript not configured)"
44
+ fi
45
+
46
+ # Check if globals.css or equivalent exists
47
+ if [ -f "src/index.css" ] || [ -f "src/globals.css" ] || [ -f "app/globals.css" ]; then
48
+ echo -e "${GREEN}✓${NC} Global CSS file found"
49
+
50
+ # Check for Tailwind directives
51
+ CSS_FILE=$(find . -name "globals.css" -o -name "index.css" | head -n 1)
52
+ if grep -q "@tailwind base" "$CSS_FILE"; then
53
+ echo -e "${GREEN}✓${NC} Tailwind directives present"
54
+ else
55
+ echo -e "${RED}✗${NC} Tailwind directives missing"
56
+ echo " Add to your CSS file:"
57
+ echo " @tailwind base;"
58
+ echo " @tailwind components;"
59
+ echo " @tailwind utilities;"
60
+ fi
61
+
62
+ # Check for CSS variables
63
+ if grep -q "^:root" "$CSS_FILE" || grep -q "@layer base" "$CSS_FILE"; then
64
+ echo -e "${GREEN}✓${NC} CSS variables defined"
65
+ else
66
+ echo -e "${YELLOW}⚠${NC} CSS variables not found"
67
+ echo " shadcn/ui requires CSS variables for theming"
68
+ fi
69
+ else
70
+ echo -e "${RED}✗${NC} Global CSS file not found"
71
+ fi
72
+
73
+ # Check if components/ui directory exists
74
+ if [ -d "src/components/ui" ] || [ -d "components/ui" ]; then
75
+ echo -e "${GREEN}✓${NC} components/ui directory exists"
76
+
77
+ # Count components
78
+ COMPONENT_COUNT=$(find . -path "*/components/ui/*.tsx" -o -path "*/components/ui/*.jsx" | wc -l)
79
+ echo -e " ${COMPONENT_COUNT} components installed"
80
+ else
81
+ echo -e "${YELLOW}⚠${NC} components/ui directory not found"
82
+ echo " Add your first component: npx shadcn@latest add button"
83
+ fi
84
+
85
+ # Check if lib/utils exists
86
+ if [ -f "src/lib/utils.ts" ] || [ -f "lib/utils.ts" ]; then
87
+ echo -e "${GREEN}✓${NC} lib/utils.ts exists"
88
+
89
+ # Check for cn function
90
+ UTILS_FILE=$(find . -name "utils.ts" | grep "lib" | head -n 1)
91
+ if grep -q "export function cn" "$UTILS_FILE"; then
92
+ echo -e "${GREEN}✓${NC} cn() utility function present"
93
+ else
94
+ echo -e "${RED}✗${NC} cn() utility function missing"
95
+ fi
96
+ else
97
+ echo -e "${RED}✗${NC} lib/utils.ts not found"
98
+ fi
99
+
100
+ # Check package.json dependencies
101
+ if [ -f "package.json" ]; then
102
+ echo ""
103
+ echo "📦 Checking dependencies..."
104
+
105
+ # Required dependencies
106
+ REQUIRED_DEPS=("react" "tailwindcss")
107
+ RECOMMENDED_DEPS=("class-variance-authority" "clsx" "tailwind-merge" "tailwindcss-animate")
108
+
109
+ for dep in "${REQUIRED_DEPS[@]}"; do
110
+ if grep -q "\"$dep\"" package.json; then
111
+ echo -e "${GREEN}✓${NC} $dep installed"
112
+ else
113
+ echo -e "${RED}✗${NC} $dep not installed"
114
+ fi
115
+ done
116
+
117
+ echo ""
118
+ echo "Recommended dependencies:"
119
+ for dep in "${RECOMMENDED_DEPS[@]}"; do
120
+ if grep -q "\"$dep\"" package.json; then
121
+ echo -e "${GREEN}✓${NC} $dep installed"
122
+ else
123
+ echo -e "${YELLOW}⚠${NC} $dep not installed (recommended)"
124
+ fi
125
+ done
126
+ fi
127
+
128
+ echo ""
129
+ echo -e "${GREEN}✓${NC} Setup verification complete!"
130
+ echo ""
131
+ echo "Next steps:"
132
+ echo " 1. Add components: npx shadcn@latest add [component]"
133
+ echo " 2. View catalog: npx shadcn@latest add --help"
134
+ echo " 3. Browse docs: https://ui.shadcn.com"