@simplysm/sd-claude 13.0.78 → 13.0.81
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/claude/rules/sd-claude-rules.md +4 -63
- package/claude/rules/sd-simplysm-usage.md +7 -0
- package/claude/sd-session-start.sh +10 -0
- package/claude/sd-statusline.py +249 -0
- package/claude/skills/sd-api-review/SKILL.md +89 -0
- package/claude/skills/sd-check/SKILL.md +55 -57
- package/claude/skills/sd-commit/SKILL.md +37 -42
- package/claude/skills/sd-debug/SKILL.md +75 -265
- package/claude/skills/sd-document/SKILL.md +63 -53
- package/claude/skills/sd-document/_common.py +94 -0
- package/claude/skills/sd-document/extract_docx.py +19 -48
- package/claude/skills/sd-document/extract_pdf.py +22 -50
- package/claude/skills/sd-document/extract_pptx.py +17 -40
- package/claude/skills/sd-document/extract_xlsx.py +19 -40
- package/claude/skills/sd-email-analyze/SKILL.md +23 -31
- package/claude/skills/sd-email-analyze/email-analyzer.py +79 -65
- package/claude/skills/sd-init/SKILL.md +133 -0
- package/claude/skills/sd-plan/SKILL.md +69 -120
- package/claude/skills/sd-readme/SKILL.md +106 -131
- package/claude/skills/sd-review/SKILL.md +38 -155
- package/claude/skills/sd-simplify/SKILL.md +59 -0
- package/dist/commands/install.js +20 -6
- package/dist/commands/install.js.map +1 -1
- package/package.json +3 -2
- package/src/commands/install.ts +29 -7
- package/README.md +0 -297
- package/claude/refs/sd-angular.md +0 -127
- package/claude/refs/sd-code-conventions.md +0 -155
- package/claude/refs/sd-directories.md +0 -7
- package/claude/refs/sd-library-issue.md +0 -7
- package/claude/refs/sd-migration.md +0 -7
- package/claude/refs/sd-orm-v12.md +0 -81
- package/claude/refs/sd-orm.md +0 -23
- package/claude/refs/sd-service.md +0 -5
- package/claude/refs/sd-simplysm-docs.md +0 -52
- package/claude/refs/sd-solid.md +0 -68
- package/claude/refs/sd-workflow.md +0 -25
- package/claude/rules/sd-refs-linker.md +0 -52
- package/claude/sd-statusline.js +0 -296
- package/claude/skills/sd-api-name-review/SKILL.md +0 -154
- package/claude/skills/sd-brainstorm/SKILL.md +0 -215
- package/claude/skills/sd-debug/condition-based-waiting-example.ts +0 -158
- package/claude/skills/sd-debug/condition-based-waiting.md +0 -114
- package/claude/skills/sd-debug/defense-in-depth.md +0 -128
- package/claude/skills/sd-debug/find-polluter.sh +0 -64
- package/claude/skills/sd-debug/root-cause-tracing.md +0 -168
- package/claude/skills/sd-discuss/SKILL.md +0 -91
- package/claude/skills/sd-explore/SKILL.md +0 -118
- package/claude/skills/sd-plan-dev/SKILL.md +0 -294
- package/claude/skills/sd-plan-dev/code-quality-reviewer-prompt.md +0 -49
- package/claude/skills/sd-plan-dev/final-review-prompt.md +0 -50
- package/claude/skills/sd-plan-dev/implementer-prompt.md +0 -60
- package/claude/skills/sd-plan-dev/spec-reviewer-prompt.md +0 -45
- package/claude/skills/sd-review/api-reviewer-prompt.md +0 -75
- package/claude/skills/sd-review/code-reviewer-prompt.md +0 -82
- package/claude/skills/sd-review/convention-checker-prompt.md +0 -61
- package/claude/skills/sd-review/refactoring-analyzer-prompt.md +0 -92
- package/claude/skills/sd-skill/SKILL.md +0 -417
- package/claude/skills/sd-skill/anthropic-best-practices.md +0 -156
- package/claude/skills/sd-skill/cso-guide.md +0 -161
- package/claude/skills/sd-skill/examples/CLAUDE_MD_TESTING.md +0 -200
- package/claude/skills/sd-skill/persuasion-principles.md +0 -220
- package/claude/skills/sd-skill/testing-skills-with-subagents.md +0 -408
- package/claude/skills/sd-skill/writing-guide.md +0 -159
- package/claude/skills/sd-tdd/SKILL.md +0 -385
- package/claude/skills/sd-tdd/testing-anti-patterns.md +0 -317
- package/claude/skills/sd-use/SKILL.md +0 -67
- package/claude/skills/sd-worktree/SKILL.md +0 -78
|
@@ -1,66 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
## 요청 수행 규칙
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
- 사용자가 명시적으로 수정을 요청하지 않은 경우, 코드를 절대 수정하지 않는다. (질문등에 대해 자의적 판단 금지)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 코드 작성 규칙
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
- Show English error messages and logs in their original form, but provide explanations in the system language
|
|
9
|
-
|
|
10
|
-
## Missing References
|
|
11
|
-
|
|
12
|
-
If a referenced file or document cannot be found, **stop immediately and ask the user for the correct path.**
|
|
13
|
-
|
|
14
|
-
- Do NOT skip or proceed on your own judgment.
|
|
15
|
-
- Responses like "I couldn't find the file, so I'll skip it" are strictly prohibited.
|
|
16
|
-
- Always confirm with the user before proceeding.
|
|
17
|
-
|
|
18
|
-
## Scope of Work
|
|
19
|
-
|
|
20
|
-
**Do only what is explicitly asked.** Never perform work that was not requested.
|
|
21
|
-
|
|
22
|
-
### Questions vs. Code Requests — CRITICAL
|
|
23
|
-
|
|
24
|
-
- **If the user asks a question** (e.g., "Why is this like this?", "What is this?", "How does this work?") → **answer with text only**. Do NOT edit, write, or create any files.
|
|
25
|
-
- **If the user discusses, explains, or shares opinions** → **respond with text only**. Do NOT touch any files.
|
|
26
|
-
- **Only edit/write/create files when the user explicitly requests code changes** (e.g., "Fix this", "Create this", "Change this", "Add this").
|
|
27
|
-
- Reading files to answer a question is fine. **Modifying files to answer a question is prohibited.**
|
|
28
|
-
|
|
29
|
-
### General Rules
|
|
30
|
-
|
|
31
|
-
- When the user says "ask", "request", or "confirm" → **ask the user**. Do NOT decide or create it yourself.
|
|
32
|
-
- Do NOT add features, refactoring, improvements, or documentation beyond the requested scope.
|
|
33
|
-
- When in doubt, **ask first** before proceeding.
|
|
34
|
-
- Responses like "I'll create it myself" or "I'll add that as well" are strictly prohibited.
|
|
35
|
-
- **Do NOT comment on code outside the requested change.** This includes:
|
|
36
|
-
- Listing issues you noticed but did not fix
|
|
37
|
-
- Describing what you "left alone" or "did not change"
|
|
38
|
-
- "reference", "suggestions", "by the way", "note", "what I left alone"
|
|
39
|
-
- Any unsolicited observations about surrounding code quality
|
|
40
|
-
- Only describe **what you changed** — nothing else
|
|
41
|
-
|
|
42
|
-
### Analysis & Comparison
|
|
43
|
-
|
|
44
|
-
- When analyzing, comparing, diffing, or auditing: **enumerate all items exhaustively**. Never provide a shallow summary — list every difference, even minor ones.
|
|
45
|
-
- Example: v12 vs v13 migration gap → list ALL API, type, pattern differences item by item
|
|
46
|
-
|
|
47
|
-
### Direct Action Requests
|
|
48
|
-
|
|
49
|
-
- When the user provides a specific action (e.g., "rename X to Y", "delete this file"), **execute it directly**. Do not route through skill agents or sub-agent workflows for trivial operations.
|
|
50
|
-
|
|
51
|
-
## Worktree Rules
|
|
52
|
-
|
|
53
|
-
All git worktrees MUST be created under the **`.worktrees/`** directory (project root). Never use `.claude/worktrees/` or any other location.
|
|
54
|
-
|
|
55
|
-
- When using `isolation: "worktree"` on Agent tool calls, the worktree is created in `.worktrees/`.
|
|
56
|
-
- **After work is complete, you MUST delete the worktree and its branch** before finishing. No worktree may be left behind.
|
|
57
|
-
- Prefer using the **`/sd-worktree`** skill for worktree creation/deletion. It includes fixes for Claude Code's built-in worktree bugs.
|
|
58
|
-
|
|
59
|
-
## Asking Clarifying Questions
|
|
60
|
-
|
|
61
|
-
When you need to ask the user a question, you MUST use the `AskUserQuestion` tool. Do NOT ask questions in plain text.
|
|
62
|
-
|
|
63
|
-
- **Wrong:** Writing questions as text in your response
|
|
64
|
-
- **Right:** Calling the `AskUserQuestion` tool
|
|
65
|
-
|
|
66
|
-
**Before EVERY `AskUserQuestion` call, output `---` as the last line.** The widget clips text above it. No exceptions.
|
|
7
|
+
- YAGNI 원칙 준수
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
echo "Read the following rule files before proceeding:"
|
|
3
|
+
files=$(ls -1 .claude/rules/*.md 2>/dev/null)
|
|
4
|
+
if [ -n "$files" ]; then
|
|
5
|
+
echo "$files" | while read f; do echo "- $f"; done
|
|
6
|
+
fi
|
|
7
|
+
echo
|
|
8
|
+
if [ -f "CLAUDE.md" ]; then
|
|
9
|
+
echo "- CLAUDE.md"
|
|
10
|
+
fi
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Claude Code statusline: folder | model | context% | 5h%(time) | 7d%(time)"""
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import re
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
import tempfile
|
|
10
|
+
import time
|
|
11
|
+
from contextlib import contextmanager
|
|
12
|
+
|
|
13
|
+
_IS_WINDOWS = os.name == "nt"
|
|
14
|
+
if _IS_WINDOWS:
|
|
15
|
+
import msvcrt
|
|
16
|
+
else:
|
|
17
|
+
import fcntl
|
|
18
|
+
|
|
19
|
+
CACHE_FILE = os.path.expanduser("~/.claude/statusline-cache.json")
|
|
20
|
+
CACHE_DIR = os.path.dirname(CACHE_FILE)
|
|
21
|
+
LOCK_FILE = os.path.expanduser("~/.claude/statusline-cache.lock")
|
|
22
|
+
CREDS_FILE = os.path.expanduser("~/.claude/.credentials.json")
|
|
23
|
+
FETCH_INTERVAL = 180 # 3 minutes
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def format_model(model_id: str) -> str:
|
|
27
|
+
m = re.match(r"claude-(\w+)-(\d+)-(\d+)", model_id)
|
|
28
|
+
if m:
|
|
29
|
+
name = m.group(1).capitalize()
|
|
30
|
+
ver = f"{m.group(2)}.{m.group(3)}"
|
|
31
|
+
return f"{name} {ver}"
|
|
32
|
+
return model_id
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def format_remaining(reset_epoch: int) -> str:
|
|
36
|
+
delta = reset_epoch - time.time()
|
|
37
|
+
if delta <= 0:
|
|
38
|
+
return "0m"
|
|
39
|
+
total_min = int(delta / 60)
|
|
40
|
+
days = total_min // (24 * 60)
|
|
41
|
+
hours = (total_min % (24 * 60)) // 60
|
|
42
|
+
minutes = total_min % 60
|
|
43
|
+
if days > 0:
|
|
44
|
+
return f"{days}d{hours}h"
|
|
45
|
+
elif hours > 0:
|
|
46
|
+
return f"{hours}h{minutes}m"
|
|
47
|
+
else:
|
|
48
|
+
return f"{minutes}m"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def read_cache():
|
|
52
|
+
try:
|
|
53
|
+
with open(CACHE_FILE) as f:
|
|
54
|
+
return json.load(f)
|
|
55
|
+
except (json.JSONDecodeError, OSError):
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def should_fetch(cache):
|
|
60
|
+
if cache is None:
|
|
61
|
+
return True
|
|
62
|
+
last_ts = cache.get("last_fetch_ts", 0)
|
|
63
|
+
return (time.time() - last_ts) > FETCH_INTERVAL
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@contextmanager
|
|
67
|
+
def _exclusive_lock():
|
|
68
|
+
fd = os.open(LOCK_FILE, os.O_CREAT | os.O_WRONLY, 0o600)
|
|
69
|
+
try:
|
|
70
|
+
if _IS_WINDOWS:
|
|
71
|
+
msvcrt.locking(fd, msvcrt.LK_NBLCK, 1)
|
|
72
|
+
else:
|
|
73
|
+
fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
74
|
+
yield True
|
|
75
|
+
except (BlockingIOError, OSError):
|
|
76
|
+
yield False
|
|
77
|
+
finally:
|
|
78
|
+
if _IS_WINDOWS:
|
|
79
|
+
try:
|
|
80
|
+
msvcrt.locking(fd, msvcrt.LK_UNLCK, 1)
|
|
81
|
+
except OSError:
|
|
82
|
+
pass
|
|
83
|
+
os.close(fd)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _make_bucket(util, reset):
|
|
87
|
+
return {
|
|
88
|
+
"used_pct": round(float(util) * 100) if util is not None else None,
|
|
89
|
+
"reset_epoch": int(reset) if reset is not None else None,
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def try_spawn_fetch():
|
|
94
|
+
try:
|
|
95
|
+
with _exclusive_lock() as locked:
|
|
96
|
+
if locked:
|
|
97
|
+
subprocess.Popen(
|
|
98
|
+
[sys.executable, os.path.abspath(__file__), "--fetch"],
|
|
99
|
+
stdin=subprocess.DEVNULL,
|
|
100
|
+
stdout=subprocess.DEVNULL,
|
|
101
|
+
stderr=subprocess.DEVNULL,
|
|
102
|
+
start_new_session=True,
|
|
103
|
+
)
|
|
104
|
+
except OSError:
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def do_fetch():
|
|
109
|
+
try:
|
|
110
|
+
with _exclusive_lock() as locked:
|
|
111
|
+
if not locked:
|
|
112
|
+
return
|
|
113
|
+
_do_fetch_locked()
|
|
114
|
+
except OSError:
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _do_fetch_locked():
|
|
119
|
+
cache = read_cache()
|
|
120
|
+
if cache and not should_fetch(cache):
|
|
121
|
+
return
|
|
122
|
+
|
|
123
|
+
import urllib.request
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
with open(CREDS_FILE) as f:
|
|
127
|
+
creds = json.load(f)
|
|
128
|
+
oauth = creds["claudeAiOauth"]
|
|
129
|
+
token = oauth["accessToken"]
|
|
130
|
+
expires_at = oauth.get("expiresAt", 0)
|
|
131
|
+
|
|
132
|
+
if expires_at < time.time() * 1000:
|
|
133
|
+
write_cache(cache, error="token_expired")
|
|
134
|
+
return
|
|
135
|
+
|
|
136
|
+
req = urllib.request.Request(
|
|
137
|
+
"https://api.anthropic.com/v1/messages",
|
|
138
|
+
data=json.dumps({
|
|
139
|
+
"model": "claude-haiku-4-5-20251001",
|
|
140
|
+
"max_tokens": 1,
|
|
141
|
+
"messages": [{"role": "user", "content": "quota"}],
|
|
142
|
+
}).encode(),
|
|
143
|
+
headers={
|
|
144
|
+
"Authorization": f"Bearer {token}",
|
|
145
|
+
"Content-Type": "application/json",
|
|
146
|
+
"anthropic-version": "2023-06-01",
|
|
147
|
+
"anthropic-beta": "oauth-2025-04-20",
|
|
148
|
+
"x-app": "cli",
|
|
149
|
+
"User-Agent": "claude-code/2.1.72",
|
|
150
|
+
},
|
|
151
|
+
method="POST",
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
resp = urllib.request.urlopen(req, timeout=15)
|
|
155
|
+
headers = resp.headers
|
|
156
|
+
resp.read()
|
|
157
|
+
|
|
158
|
+
buckets = {}
|
|
159
|
+
for key, prefix in (("five_hour", "5h"), ("seven_day", "7d")):
|
|
160
|
+
util = headers.get(f"anthropic-ratelimit-unified-{prefix}-utilization")
|
|
161
|
+
reset = headers.get(f"anthropic-ratelimit-unified-{prefix}-reset")
|
|
162
|
+
buckets[key] = _make_bucket(util, reset)
|
|
163
|
+
|
|
164
|
+
new_cache = {
|
|
165
|
+
"last_fetch_ts": time.time(),
|
|
166
|
+
**buckets,
|
|
167
|
+
"error": None,
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
write_cache_atomic(new_cache)
|
|
171
|
+
except Exception as e:
|
|
172
|
+
write_cache(cache, error=str(e))
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def write_cache(old_cache, error=None):
|
|
176
|
+
data = dict(old_cache) if old_cache else {}
|
|
177
|
+
data["last_fetch_ts"] = time.time()
|
|
178
|
+
data["error"] = error
|
|
179
|
+
write_cache_atomic(data)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def write_cache_atomic(data):
|
|
183
|
+
fd, tmp_path = tempfile.mkstemp(dir=CACHE_DIR, suffix=".tmp")
|
|
184
|
+
try:
|
|
185
|
+
with os.fdopen(fd, "w") as f:
|
|
186
|
+
json.dump(data, f)
|
|
187
|
+
os.replace(tmp_path, CACHE_FILE)
|
|
188
|
+
except Exception:
|
|
189
|
+
try:
|
|
190
|
+
os.unlink(tmp_path)
|
|
191
|
+
except OSError:
|
|
192
|
+
pass
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def format_usage(bucket: dict) -> str:
|
|
196
|
+
pct = bucket.get("used_pct")
|
|
197
|
+
reset = bucket.get("reset_epoch")
|
|
198
|
+
if pct is not None and reset is not None:
|
|
199
|
+
return f"{pct}%({format_remaining(reset)})"
|
|
200
|
+
elif pct is not None:
|
|
201
|
+
return f"{pct}%"
|
|
202
|
+
return "?"
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def main():
|
|
206
|
+
# Read stdin JSON
|
|
207
|
+
try:
|
|
208
|
+
stdin_data = json.load(sys.stdin)
|
|
209
|
+
except Exception:
|
|
210
|
+
stdin_data = {}
|
|
211
|
+
|
|
212
|
+
# Extract folder
|
|
213
|
+
cwd = stdin_data.get("workspace", {}).get("current_dir") or stdin_data.get("cwd", "")
|
|
214
|
+
folder = os.path.basename(cwd) if cwd else "?"
|
|
215
|
+
|
|
216
|
+
# Extract model
|
|
217
|
+
model_id = stdin_data.get("model", {}).get("id", "")
|
|
218
|
+
model = format_model(model_id) if model_id else "?"
|
|
219
|
+
|
|
220
|
+
# Extract context %
|
|
221
|
+
ctx_pct = stdin_data.get("context_window", {}).get("used_percentage")
|
|
222
|
+
ctx_str = f"{ctx_pct}%" if ctx_pct is not None else "?"
|
|
223
|
+
|
|
224
|
+
# Read cached usage data
|
|
225
|
+
cache = read_cache()
|
|
226
|
+
|
|
227
|
+
if cache and not cache.get("error"):
|
|
228
|
+
h5_str = format_usage(cache.get("five_hour", {}))
|
|
229
|
+
d7_str = format_usage(cache.get("seven_day", {}))
|
|
230
|
+
else:
|
|
231
|
+
h5_str = "?"
|
|
232
|
+
d7_str = "?"
|
|
233
|
+
|
|
234
|
+
# Spawn background fetch if needed
|
|
235
|
+
if should_fetch(cache):
|
|
236
|
+
try_spawn_fetch()
|
|
237
|
+
|
|
238
|
+
# Output
|
|
239
|
+
print(f"{folder} | {model} | {ctx_str} | {h5_str} | {d7_str}")
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
if __name__ == "__main__":
|
|
243
|
+
try:
|
|
244
|
+
if "--fetch" in sys.argv:
|
|
245
|
+
do_fetch()
|
|
246
|
+
else:
|
|
247
|
+
main()
|
|
248
|
+
except Exception:
|
|
249
|
+
pass # statusline should never crash Claude Code
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sd-api-review
|
|
3
|
+
description: "API 리뷰", "api-review", "sd-api-review", "API 개선", "공개 API 검토", "API 직관성" 등을 요청할 때 사용.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# SD API Review — Public API 직관성 리뷰 및 개선
|
|
7
|
+
|
|
8
|
+
지정한 경로(패키지/폴더/파일)의 public API를 추출하고, 관련 표준 및 유사 라이브러리와 비교하여 직관성 개선안을 도출한 뒤, `/sd-plan` 프로세스로 계획을 수립하여 구현한다. Breaking change를 허용하며 사용자 직관성을 최우선으로 한다.
|
|
9
|
+
|
|
10
|
+
ARGUMENTS: 대상 경로 (필수). 예: `/sd-api-review packages/my-pkg`
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Step 1: 인자 확인
|
|
15
|
+
|
|
16
|
+
1. ARGUMENTS에서 **대상 경로**를 추출하라. 경로가 없으면 "대상 경로를 지정해 주세요. 예: `/sd-api-review packages/my-pkg`"라고 안내하고 종료하라.
|
|
17
|
+
|
|
18
|
+
## Step 2: Public API 추출
|
|
19
|
+
|
|
20
|
+
대상의 public API를 수집하라.
|
|
21
|
+
- **폴더/파일 대상**: 해당 경로의 export를 직접 분석
|
|
22
|
+
- **깊이**: export된 심볼(클래스, 함수, 인터페이스, 타입, 상수) + export된 클래스의 public 메서드/프로퍼티
|
|
23
|
+
|
|
24
|
+
export가 없으면 "대상에 export된 API가 없습니다."라고 안내하고 종료하라.
|
|
25
|
+
|
|
26
|
+
## Step 3: 비교 분석 및 개선안 도출
|
|
27
|
+
|
|
28
|
+
### 3-1. 비교 대상 결정
|
|
29
|
+
|
|
30
|
+
- 패키지 메타데이터와 코드 내용을 분석하여 도메인을 추론하고, 해당 도메인에서 가장 널리 사용되는 다수의 라이브러리 자동 선정하라.
|
|
31
|
+
- 관련 표준(HTML, WAI-ARIA, Web API, TC39, Javascript, CSS 등)도 도메인에 따라 자동으로 포함하라.
|
|
32
|
+
|
|
33
|
+
### 3-2. 외부 API 조사
|
|
34
|
+
|
|
35
|
+
WebSearch와 WebFetch를 사용하여 아래 두 축을 **동등한 비중**으로 조사하라.
|
|
36
|
+
**카테고리/패턴 단위**로 비교하라 (개별 심볼마다 검색하지 않음).
|
|
37
|
+
|
|
38
|
+
1. **표준**: 도메인 관련 표준의 공식 사양에서 네이밍, 속성, 패턴을 조사하라.
|
|
39
|
+
2. **라이브러리**: 선정된 라이브러리들의 공식 문서에서 API를 조사하라.
|
|
40
|
+
|
|
41
|
+
### 3-3. 개선안 도출
|
|
42
|
+
|
|
43
|
+
Step 2의 API 카탈로그와 외부 API를 비교하여 개선점을 도출하라. 네이밍, 구조, 일관성, 패턴, 사용 편의성, 타입 품질 관점에서 검토하라.
|
|
44
|
+
|
|
45
|
+
주의사항:
|
|
46
|
+
- Breaking change는 고려대상이 아니다. 완전히 허용된다.
|
|
47
|
+
- input/output/목적이 다를경우 동작이 다른경우, 제안이 잘못될 수 있음을 반드시 인지해야함. (자주하는 실수)
|
|
48
|
+
|
|
49
|
+
각 개선안은 아래를 포함하라:
|
|
50
|
+
- **현재**: 현재 API 상태 (코드 예시)
|
|
51
|
+
- **제안**: 개선된 API (코드 예시)
|
|
52
|
+
- **전환이유**: 변경해야 하는 근거 (표준/라이브러리 비교 포함)
|
|
53
|
+
- **비전환이유**: 현재 상태를 유지해도 되는 근거
|
|
54
|
+
|
|
55
|
+
## Step 4: sd-plan으로 구현 계획 수립
|
|
56
|
+
|
|
57
|
+
Step 3에서 도출된 개선안을 작업 설명으로 하여, Skill 도구로 `sd-plan`을 호출하라. args에 아래를 전달하라:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
아래는 **LLM이 분석하여 제안한** API 개선안이다.
|
|
61
|
+
개선안은 사용자가 명시적으로 요청한 수정이 아니므로, 불명확한 것으로 취급하라.
|
|
62
|
+
|
|
63
|
+
## 대상
|
|
64
|
+
<대상 경로>
|
|
65
|
+
|
|
66
|
+
## LLM 제안 개선안 — 비교 분석 표
|
|
67
|
+
불명확한 개선안을 사용자에게 질문할 때, 아래 내용을 **반드시 먼저** 제시하여 사용자가 맥락을 파악할 수 있도록 하라.
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
개선안:
|
|
71
|
+
- 현재:
|
|
72
|
+
- 제안:
|
|
73
|
+
- 전환이유:
|
|
74
|
+
- 비전환이유:
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## 구현 시 필수 고려사항
|
|
78
|
+
1. Breaking change는 고려 대상이 아니다. 완전히 허용된다.
|
|
79
|
+
2. 모노레포 전체에서 변경된 API의 사용처를 Grep으로 검색하여 함께 수정하라.
|
|
80
|
+
3. deprecated 래퍼를 남기지 않는다 (clean break).
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Step 5: 계획 실행
|
|
84
|
+
|
|
85
|
+
sd-plan이 완료되어 확정된 계획서가 나오면, 그 계획서에 따라 코드를 수정하라.
|
|
86
|
+
|
|
87
|
+
## Step 6: README 업데이트 추천
|
|
88
|
+
|
|
89
|
+
코드 수정이 발생한 경우, 사용자에게 `/sd-readme` 수행을 추천하라.
|
|
@@ -1,71 +1,69 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sd-check
|
|
3
|
-
description: "
|
|
3
|
+
description: "체크", "check", "sd-check", "타입체크+린트+테스트", "전체 검사" 등을 요청할 때 사용.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# SD Check — 자동 검사 및 오류 수정 루프
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
패키지 매니저를 감지하고 check 스크립트를 실행하여 결과를 확인한 뒤, 코드 오류가 있으면 sd-debug로 근본 원인을 분석·수정하고 재검사하는 과정을 오류가 없을 때까지 반복한다.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
ARGUMENTS: 타겟 경로 (선택, 복수 가능). 미지정 시 대화 컨텍스트에서 파악하며, 특정 타겟이 없거나 "전체/all"이면 타겟 없이 실행.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
- If `pnpm-lock.yaml` exists in project root → use `pnpm`
|
|
14
|
-
- If `yarn.lock` exists in project root → use `yarn`
|
|
15
|
-
- Otherwise → use `npm`
|
|
12
|
+
---
|
|
16
13
|
|
|
17
|
-
|
|
14
|
+
## Step 1: 준비 (PM 감지 + 스크립트 확인 + 타겟 결정)
|
|
18
15
|
|
|
19
|
-
|
|
16
|
+
1. **PM 감지**: 프로젝트 루트의 락 파일로 판별하라.
|
|
17
|
+
- `pnpm-lock.yaml` 존재 → `pnpm`
|
|
18
|
+
- `yarn.lock` 존재 → `yarn`
|
|
19
|
+
- `package-lock.json` 존재 → `npm`
|
|
20
|
+
- 모두 없으면 → `npm` (기본값)
|
|
21
|
+
2. **스크립트 확인**: `package.json`의 `scripts.check` 존재 여부를 확인하라. 없으면 `"check 스크립트가 package.json에 정의되어 있지 않습니다."` 안내 후 **종료**.
|
|
22
|
+
3. **타겟 결정**: 아래 우선순위로 결정하라.
|
|
23
|
+
1. ARGUMENTS에 명시된 타겟
|
|
24
|
+
2. 현재 대화 컨텍스트에서 파악 (사용자가 특정 패키지 작업 중인 경우)
|
|
25
|
+
3. 위 둘 모두 해당 없거나 "전체/all" → 타겟 없이 실행 (전체)
|
|
26
|
+
|
|
27
|
+
## Step 2: 검사 실행
|
|
28
|
+
|
|
29
|
+
1. `mkdir -p .tmp/check` (Bash)
|
|
30
|
+
2. Bash로 아래 명령을 실행하라:
|
|
31
|
+
```
|
|
32
|
+
$PM check [targets...] > .tmp/check/{yyMMddHHmmss}.txt 2>&1; echo "EXIT_CODE:$?" >> .tmp/check/{yyMMddHHmmss}.txt
|
|
33
|
+
```
|
|
34
|
+
- `$PM` = Step 1에서 감지한 패키지 매니저
|
|
35
|
+
- `{yyMMddHHmmss}` = 연월일시분초
|
|
36
|
+
- 타겟이 있으면 명령에 포함, 없으면 생략
|
|
37
|
+
3. Read 도구로 결과 파일(`.tmp/check/{yyMMddHHmmss}.txt`)을 읽어라.
|
|
38
|
+
|
|
39
|
+
## Step 3: 결과 분석
|
|
40
|
+
|
|
41
|
+
결과 파일 내용을 읽고 아래 세 가지 중 하나로 분류하라:
|
|
42
|
+
|
|
43
|
+
- **성공**: 오류 없이 모든 검사를 통과한 경우 → **Step 5(완료)**로 이동
|
|
44
|
+
- **환경 오류**: 코드 문제가 아닌 환경/인프라 문제로 판단되는 경우 (예: 의존성 미설치, 메모리 부족, 명령어 없음, 네트워크 문제 등) → 사용자에게 해당 오류 내용을 보여주고 **즉시 종료**. 코드 수정을 시도하지 않는다.
|
|
45
|
+
- **코드 오류**: 소스 코드의 타입 에러, 린트 위반, 테스트 실패 등으로 판단되는 경우 → **Step 4**로 이동
|
|
46
|
+
|
|
47
|
+
> 위 분류는 하드코딩된 패턴 매칭이 아닌, 결과 내용을 읽고 자유롭게 판단한다.
|
|
48
|
+
|
|
49
|
+
**반복 제한**: 현재 반복 횟수가 5회를 초과하면, 잔여 오류를 사용자에게 보고하고 `"5회 반복 후에도 오류가 남아 있습니다. 남은 오류를 확인해 주세요."` 안내 후 **종료**.
|
|
50
|
+
|
|
51
|
+
## Step 4: 오류 분석 및 수정 (sd-debug 활용)
|
|
52
|
+
|
|
53
|
+
Skill 도구로 `sd-debug`를 호출하라. args에 아래 내용을 전달하라:
|
|
20
54
|
|
|
21
55
|
```
|
|
22
|
-
|
|
23
|
-
|
|
56
|
+
아래 check 결과의 코드 오류를 분석하라.
|
|
57
|
+
**중요: Step 2(코드베이스 심층 분석) 완료 후 Step 3~5를 건너뛰고, 분석 결과를 바탕으로 바로 코드를 수정하라. 진단 보고서 출력, 사용자 확인, sd-plan 호출 없이 즉시 수정한다.**
|
|
24
58
|
|
|
25
|
-
|
|
26
|
-
| ------------------------------------- | ------------------------- |
|
|
27
|
-
| `/sd-check` | Full project, all checks |
|
|
28
|
-
| `/sd-check packages/core-common` | Specific path, all checks |
|
|
29
|
-
| `/sd-check test` | Tests only, full project |
|
|
30
|
-
| `/sd-check packages/core-common lint` | Specific path + type |
|
|
31
|
-
|
|
32
|
-
Multiple types: `--type typecheck,lint`. No path = full project. No type = all checks.
|
|
33
|
-
|
|
34
|
-
## Workflow
|
|
35
|
-
|
|
36
|
-
```mermaid
|
|
37
|
-
flowchart TD
|
|
38
|
-
A[Run check] --> B{All passed?}
|
|
39
|
-
B -->|yes| C[Report results → done]
|
|
40
|
-
B -->|no| D["Fix errors (typecheck → lint → test)"]
|
|
41
|
-
D --> E{Stuck after 2-3 tries?}
|
|
42
|
-
E -->|no| A
|
|
43
|
-
E -->|yes| F[Recommend /sd-debug]
|
|
59
|
+
<.tmp/check/{yyMMddHHmmss}.txt 의 오류 내용을 여기에 포함>
|
|
44
60
|
```
|
|
45
61
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
**Fixing errors:**
|
|
55
|
-
- **Before fixing any code**: Read `.claude/refs/sd-code-conventions.md` and check `.claude/rules/sd-refs-linker.md` for additional refs relevant to the affected code area (e.g., `sd-solid.md` for SolidJS, `sd-orm.md` for ORM). Fixing errors does NOT exempt you from following project conventions.
|
|
56
|
-
- Test failures: **MUST** run `git log` to decide — update test or fix source
|
|
57
|
-
- **E2E test failures**: use Playwright MCP to investigate before fixing
|
|
58
|
-
1. `browser_navigate` to the target URL
|
|
59
|
-
2. `browser_snapshot` / `browser_take_screenshot` (save to `.tmp/playwright/`) to see page state
|
|
60
|
-
3. `browser_console_messages` for JS errors
|
|
61
|
-
4. `browser_network_requests` for failed API calls
|
|
62
|
-
5. Interact with the page following the test steps to reproduce the failure
|
|
63
|
-
6. Fix based on observed evidence, not guesswork
|
|
64
|
-
|
|
65
|
-
## Rules
|
|
66
|
-
|
|
67
|
-
- **Always re-run ALL checks** after any fix — never assume other checks still pass
|
|
68
|
-
- **Report with evidence** — cite actual numbers (e.g., "0 errors, 47 tests passed"), not "should work"
|
|
69
|
-
- **No build, no dev server** — typecheck + lint + test only
|
|
70
|
-
- **Run Bash directly** — no Task/agent/team overhead
|
|
71
|
-
- **Never run in background** — always run Bash in foreground (do NOT set `run_in_background: true`), wait for result before proceeding
|
|
62
|
+
sd-debug 완료 후 → **Step 2**로 복귀 (새로운 txt로 재검사)
|
|
63
|
+
|
|
64
|
+
## Step 5: 완료 보고
|
|
65
|
+
|
|
66
|
+
모든 검사 통과 시 아래를 출력하라:
|
|
67
|
+
- 총 반복 횟수
|
|
68
|
+
- 각 반복에서 수정한 내용 요약
|
|
69
|
+
- 형식: `"✔ 체크 완료: {N}회 만에 모든 검사를 통과했습니다."` + 수정 내역 bullet list
|
|
@@ -1,68 +1,63 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sd-commit
|
|
3
|
-
description: "
|
|
4
|
-
argument-hint: "[all]"
|
|
5
|
-
model: haiku
|
|
3
|
+
description: "커밋", "commit", "sd-commit" 등을 요청할 때 사용.
|
|
6
4
|
---
|
|
7
5
|
|
|
8
|
-
#
|
|
6
|
+
# SD Commit — 변경사항 분석 후 커밋
|
|
9
7
|
|
|
10
|
-
|
|
8
|
+
변경사항을 스테이징하고, 변경 내용을 분석하여 커밋 메시지를 생성한 뒤 커밋한다.
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
ARGUMENTS: `all` (선택). 지정하면 모든 변경사항 대상, 미지정 시 대화 내 수정 파일만 대상.
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- **Default mode** (no arguments): Stage files relevant to the current conversation context. Always a **single commit**.
|
|
17
|
-
- **"all" mode** (`$ARGUMENTS` is "all"): Target **all** changed/untracked files. Always a **single commit**.
|
|
12
|
+
---
|
|
18
13
|
|
|
19
|
-
##
|
|
14
|
+
## Step 1: 인자 파싱 및 스테이징
|
|
20
15
|
|
|
21
|
-
|
|
16
|
+
ARGUMENTS에서 `all` 여부를 확인하라.
|
|
22
17
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
18
|
+
- **`all`**: 워킹 트리의 모든 변경사항(수정, 삭제, 신규)을 스테이징하라.
|
|
19
|
+
- **`all`이 아니거나 인자 없음**: 현재 대화에서 Edit 또는 Write 도구로 수정하거나 생성한 파일들만 스테이징하라. 대화 컨텍스트를 되돌아보며 해당 파일 목록을 추출하라.
|
|
25
20
|
|
|
26
|
-
|
|
21
|
+
## Step 2: 변경사항 확인
|
|
27
22
|
|
|
28
|
-
|
|
29
|
-
- Folder name or path (e.g., `node_modules` is handled by `.gitignore`)
|
|
30
|
-
- Personal judgment about importance or "cleanliness"
|
|
31
|
-
- Assumption that generated/config/style files are unimportant
|
|
23
|
+
스테이징된 변경사항이 없으면 "커밋할 변경사항이 없습니다."라고 안내하고 **종료**하라.
|
|
32
24
|
|
|
33
|
-
|
|
25
|
+
## Step 3: 커밋 메시지 생성 및 커밋
|
|
34
26
|
|
|
35
|
-
|
|
27
|
+
스테이징된 diff를 분석하여 아래 규칙에 따라 커밋 메시지를 생성하고 커밋하라.
|
|
36
28
|
|
|
37
|
-
|
|
38
|
-
- Current diff: !`git diff HEAD`
|
|
39
|
-
- Current branch: !`git branch --show-current`
|
|
40
|
-
- Recent commits: !`git log --oneline -10`
|
|
29
|
+
### 커밋 메시지 규칙
|
|
41
30
|
|
|
42
|
-
|
|
31
|
+
- **Conventional Commits** 형식: prefix + 설명
|
|
32
|
+
- prefix 예: `feat`, `fix`, `refactor`, `chore`, `docs`, `style`, `test`, `perf`, `ci`, `build`
|
|
33
|
+
- **subject** (첫 줄): 변경 요약. 70자 이내.
|
|
34
|
+
- **body**: 빈 줄 후 주요 변경 내용을 나열. 여러 주제의 변경이 섞여 있으면 주제별로 `[prefix]` 태그를 붙여 그룹화하라.
|
|
35
|
+
- 마지막에 `Co-Authored-By: Claude <noreply@anthropic.com>` 포함.
|
|
43
36
|
|
|
37
|
+
단일 주제 예시:
|
|
44
38
|
```
|
|
45
|
-
|
|
46
|
-
```
|
|
39
|
+
feat: 사용자 인증 로직 추가
|
|
47
40
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
| `type` | `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `build`, `style`, `perf` |
|
|
51
|
-
| `scope` | package name or area (e.g., `solid`, `core-common`, `orm-node`) |
|
|
52
|
-
| `description` | English, imperative, lowercase, no period at end |
|
|
41
|
+
- AuthService에 JWT 토큰 검증 로직 구현
|
|
42
|
+
- 로그인 페이지에 폼 유효성 검사 추가
|
|
53
43
|
|
|
54
|
-
|
|
44
|
+
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
45
|
+
```
|
|
55
46
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
47
|
+
여러 주제 예시:
|
|
48
|
+
```
|
|
49
|
+
chore: 인증 기능 추가 및 결제 오류 수정
|
|
59
50
|
|
|
60
|
-
|
|
51
|
+
[feat] 사용자 인증
|
|
52
|
+
- AuthService에 JWT 토큰 검증 로직 구현
|
|
53
|
+
- 로그인 페이지에 폼 유효성 검사 추가
|
|
61
54
|
|
|
62
|
-
|
|
55
|
+
[fix] 결제 모듈
|
|
56
|
+
- 결제 실패 시 재시도 로직 수정
|
|
63
57
|
|
|
64
|
-
|
|
58
|
+
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
59
|
+
```
|
|
65
60
|
|
|
66
|
-
|
|
61
|
+
## Step 4: 결과 출력
|
|
67
62
|
|
|
68
|
-
|
|
63
|
+
커밋 완료 후 커밋 메시지 전문을 사용자에게 보여줘라.
|