@simplysm/sd-claude 13.0.85 → 13.0.87
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/README.md +160 -30
- package/claude/rules/sd-claude-rules.md +14 -11
- package/claude/rules/sd-library-issue.md +9 -4
- package/claude/rules/sd-readme.md +5 -0
- package/claude/skills/sd-audit/SKILL.md +133 -0
- package/claude/skills/sd-check/SKILL.md +111 -49
- package/claude/skills/sd-commit/SKILL.md +121 -32
- package/claude/skills/sd-debug/SKILL.md +96 -82
- package/claude/skills/sd-document/SKILL.md +64 -58
- package/claude/skills/sd-document/_common.py +1 -6
- package/claude/skills/sd-document/extract_docx.py +0 -1
- package/claude/skills/sd-document/extract_pdf.py +17 -25
- package/claude/skills/sd-document/extract_pptx.py +0 -1
- package/claude/skills/sd-document/extract_xlsx.py +2 -4
- package/claude/skills/sd-email-analyze/SKILL.md +33 -23
- package/claude/skills/sd-init/SKILL.md +99 -80
- package/claude/skills/sd-plan/SKILL.md +113 -119
- package/claude/skills/sd-plan-dev/SKILL.md +122 -0
- package/claude/skills/sd-readme/SKILL.md +147 -100
- package/claude/skills/sd-spec/SKILL.md +207 -0
- package/claude/skills/sd-spec/sections/api.md +85 -0
- package/claude/skills/sd-spec/sections/architecture.md +104 -0
- package/claude/skills/sd-spec/sections/db.md +99 -0
- package/claude/skills/sd-spec/sections/process.md +98 -0
- package/claude/skills/sd-spec/sections/ui.md +146 -0
- package/claude/skills/sd-test/SKILL.md +116 -0
- package/claude/skills/sd-use/SKILL.md +149 -0
- package/package.json +1 -1
- package/claude/rules/sd-simplysm-usage.md +0 -7
- package/claude/skills/sd-api-review/SKILL.md +0 -85
- package/claude/skills/sd-document/__pycache__/_common.cpython-313.pyc +0 -0
- package/claude/skills/sd-review/SKILL.md +0 -72
- package/claude/skills/sd-simplify/SKILL.md +0 -66
|
@@ -1,63 +1,152 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sd-commit
|
|
3
|
-
description:
|
|
3
|
+
description: 변경사항을 분석하여 [type] scope 형식의 커밋 메시지를 생성하고 커밋. 사용자가 커밋을 요청할 때 사용
|
|
4
|
+
argument-hint: "[all]"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
#
|
|
7
|
+
# sd-commit: 커밋
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
변경사항을 분석하여 커밋 메시지를 생성하고 커밋한다.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
## 1. 인자 파싱
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
`$ARGUMENTS`에서 staging 전략을 결정한다.
|
|
14
|
+
|
|
15
|
+
| 인자 | 동작 |
|
|
16
|
+
|------|------|
|
|
17
|
+
| (없음) | 현재 대화에서 수정한 파일만 `git add {파일1} {파일2} ...`로 staging (시크릿 파일 제외) |
|
|
18
|
+
| `all` | `git add -A`로 모든 변경사항(untracked 포함)을 staging |
|
|
19
|
+
|
|
20
|
+
## 2. 정보 수집
|
|
21
|
+
|
|
22
|
+
### `all` 인자인 경우
|
|
23
|
+
|
|
24
|
+
1. Bash로 `git add -A`를 실행하여 모든 변경사항을 먼저 staging한다
|
|
25
|
+
2. 이후 다음 명령어를 Bash로 **병렬 실행**한다:
|
|
26
|
+
- `git status` (staging 결과 확인, `-uall` 플래그 금지)
|
|
27
|
+
- `git diff --staged` (staging된 전체 변경사항 확인)
|
|
28
|
+
|
|
29
|
+
### 인자 없음인 경우
|
|
30
|
+
|
|
31
|
+
현재 대화에서 Edit/Write 도구로 수정한 파일 목록을 대화 맥락에서 파악한다.
|
|
32
|
+
|
|
33
|
+
다음 명령어를 Bash로 **병렬 실행**한다:
|
|
34
|
+
|
|
35
|
+
- `git status` (전체 상태 확인, `-uall` 플래그 금지)
|
|
36
|
+
- `git diff -- {대화에서 수정한 파일들}` (해당 파일들의 unstaged 변경사항)
|
|
37
|
+
- `git diff --staged -- {대화에서 수정한 파일들}` (해당 파일들의 staged 변경사항)
|
|
38
|
+
|
|
39
|
+
대화에서 수정한 파일이 없으면 "현재 대화에서 수정한 파일이 없습니다."를 출력하고 종료한다.
|
|
13
40
|
|
|
14
|
-
##
|
|
41
|
+
## 3. 변경사항 분석
|
|
15
42
|
|
|
16
|
-
|
|
43
|
+
### 3-1. 변경사항 없음
|
|
17
44
|
|
|
18
|
-
|
|
19
|
-
-
|
|
45
|
+
git status/diff 결과가 모두 비어있으면 (staged, unstaged, untracked 모두 없음):
|
|
46
|
+
- "커밋할 변경사항이 없습니다."를 출력하고 종료한다
|
|
20
47
|
|
|
21
|
-
|
|
48
|
+
### 3-2. 시크릿 파일 확인
|
|
22
49
|
|
|
23
|
-
|
|
50
|
+
변경 파일 중 시크릿 파일(`.env`, `credentials.json`, `*.key`, `*.pem` 등)이 포함되어 있으면:
|
|
51
|
+
- 해당 파일명을 명시하여 경고를 출력한다
|
|
52
|
+
- staging 대상 및 커밋 메시지에서 제외한다
|
|
24
53
|
|
|
25
|
-
|
|
54
|
+
### 3-3. 변경사항 분류
|
|
26
55
|
|
|
27
|
-
|
|
56
|
+
변경된 파일과 diff 내용을 분석하여 변경의 성격을 파악한다:
|
|
57
|
+
- `feat`: 새 기능 추가
|
|
58
|
+
- `fix`: 버그 수정
|
|
59
|
+
- `refactor`: 리팩터링 (동작 변경 없음)
|
|
60
|
+
- `test`: 테스트 추가/수정
|
|
61
|
+
- `docs`: 문서 변경
|
|
62
|
+
- `chore`: 빌드, 설정, 의존성 등 기타 변경
|
|
28
63
|
|
|
29
|
-
|
|
64
|
+
## 4. 커밋 메시지 작성
|
|
30
65
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
66
|
+
### 형식
|
|
67
|
+
|
|
68
|
+
첫 줄은 전체 변경사항을 요약하는 **커밋 헤더**이다.
|
|
69
|
+
빈 줄 후 `[type] scope` 헤더와 bullet point로 세부 내용을 기술한다.
|
|
70
|
+
마지막에 `Co-Authored-By` 트레일러를 포함한다.
|
|
36
71
|
|
|
37
|
-
Single-topic example:
|
|
38
72
|
```
|
|
39
|
-
|
|
73
|
+
{전체 요약 커밋 헤더}
|
|
40
74
|
|
|
41
|
-
|
|
42
|
-
-
|
|
75
|
+
[type] {변경 대상 요약}
|
|
76
|
+
- {세부 변경 내용}
|
|
77
|
+
- {세부 변경 내용}
|
|
43
78
|
|
|
44
79
|
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
45
80
|
```
|
|
46
81
|
|
|
47
|
-
|
|
82
|
+
### 다중 변경사항
|
|
83
|
+
|
|
84
|
+
여러 종류의 변경이 있으면 `[type] scope` 그룹을 빈 줄로 구분하여 나열한다.
|
|
85
|
+
|
|
48
86
|
```
|
|
49
|
-
|
|
87
|
+
core-common 유틸 함수 추가 및 solid DatePicker 버그 수정
|
|
50
88
|
|
|
51
|
-
[feat]
|
|
52
|
-
-
|
|
53
|
-
- Add form validation to the login page
|
|
89
|
+
[feat] core-common 유틸 함수 추가
|
|
90
|
+
- StringUtil에 camelToKebab 변환 함수 추가
|
|
54
91
|
|
|
55
|
-
[fix]
|
|
56
|
-
-
|
|
92
|
+
[fix] solid DatePicker 버그 수정
|
|
93
|
+
- timezone 오프셋 미적용으로 인한 날짜 표시 오류 수정
|
|
57
94
|
|
|
58
95
|
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
59
96
|
```
|
|
60
97
|
|
|
61
|
-
|
|
98
|
+
### 단일 변경사항
|
|
99
|
+
|
|
100
|
+
변경이 한 종류이면 `[type] scope` 그룹 1개만 작성한다.
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
solid DatePicker timezone 버그 수정
|
|
104
|
+
|
|
105
|
+
[fix] solid DatePicker 버그 수정
|
|
106
|
+
- timezone 오프셋 미적용으로 인한 날짜 표시 오류 수정
|
|
107
|
+
|
|
108
|
+
Co-Authored-By: Claude <noreply@anthropic.com>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 메시지 작성 원칙
|
|
112
|
+
|
|
113
|
+
- "what"이 아닌 "why"에 초점을 맞춘다
|
|
114
|
+
- 커밋 헤더는 간결하게 작성한다
|
|
115
|
+
- scope는 변경 대상을 요약한다
|
|
116
|
+
|
|
117
|
+
## 5. Staging 및 커밋
|
|
118
|
+
|
|
119
|
+
### Staging
|
|
120
|
+
|
|
121
|
+
- `all` 인자: 2단계에서 이미 staging 완료. 추가 작업 없음
|
|
122
|
+
- 인자 없음: 현재 대화에서 수정한 파일 중 시크릿 파일을 제외하고 `git add {파일1} {파일2} ...`로 staging한다
|
|
123
|
+
|
|
124
|
+
### 커밋
|
|
125
|
+
|
|
126
|
+
HEREDOC 형식으로 커밋 메시지를 전달한다. `--no-verify`, `--no-gpg-sign` 등 hook 우회 플래그를 사용하지 않는다.
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
git commit -m "$(cat <<'EOF'
|
|
130
|
+
{커밋 메시지}
|
|
131
|
+
EOF
|
|
132
|
+
)"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
`--amend`는 사용하지 않는다. 항상 새 커밋을 생성한다.
|
|
136
|
+
|
|
137
|
+
## 6. 커밋 후 검증
|
|
138
|
+
|
|
139
|
+
### 성공 시
|
|
140
|
+
|
|
141
|
+
Bash로 `git status`를 실행하여 커밋이 정상적으로 완료되었는지 확인한다.
|
|
142
|
+
|
|
143
|
+
### pre-commit hook 실패 시
|
|
144
|
+
|
|
145
|
+
실패 원인을 사용자에게 보고하고 중단한다.
|
|
146
|
+
|
|
147
|
+
## 7. 완료 안내
|
|
148
|
+
|
|
149
|
+
커밋 후 `git rev-parse HEAD`로 새 커밋 해시를 얻고, 해시와 커밋 메시지 전문을 함께 출력한다.
|
|
150
|
+
마지막에 "커밋을 취소하려면 수동으로 되돌리세요."라고 안내한다.
|
|
62
151
|
|
|
63
|
-
|
|
152
|
+
`git push`는 수행하지 않는다. git config는 수정하지 않는다.
|
|
@@ -1,122 +1,136 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sd-debug
|
|
3
|
-
description:
|
|
3
|
+
description: 문제의 근본 원인을 분석하고 해결책을 제시하여 debug.md로 저장. 사용자가 버그/에러/오류/예외/비정상 동작의 원인 분석을 요청할 때 사용
|
|
4
|
+
argument-hint: "<문제 현상 설명>"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
#
|
|
7
|
+
# sd-debug: 근본 원인 분석 및 해결
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
사용자가 문제(버그, 에러, 비정상 동작 등)를 만났을 때, 현상을 입력받아 근본적 원인을 깊이 분석하고 해결책을 제시한다. 채택된 해결책은 debug.md로 저장되어 `/sd-plan`의 입력으로 사용 가능하다.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
## 1. 입력 파싱
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
`$ARGUMENTS`에서 문제 현상 텍스트를 추출한다.
|
|
14
|
+
- `$ARGUMENTS`가 비어있으면 현재 대화 맥락에서 문제 현상을 파악한다. 대화 맥락도 없으면 AskUserQuestion으로 문제 현상을 요청한다
|
|
15
|
+
- 문제 현상에서 topic을 영문 kebab-case로 변환한다 (예: "createEffect 무한루프" → `create-effect-infinite-loop`, "DB 연결 타임아웃" → `db-connection-timeout`)
|
|
16
|
+
- 특수문자(`#`, `/`, `\`, `(`, `)`, `.` 등)는 제거하거나 `-`로 치환한다 (예: "ORM 쿼리 오류 (v2.0)" → `orm-query-error-v2-0`)
|
|
17
|
+
- 이미 kebab-case이면 그대로 사용한다
|
|
13
18
|
|
|
14
|
-
##
|
|
19
|
+
## 2. 코드베이스 분석
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
- **Error type**: Compilation error / runtime error / type error / logic error / build error / unexpected behavior, etc.
|
|
22
|
-
- **Related clues**: Keywords useful for codebase exploration, such as file paths, function names, line numbers, package names, error codes, etc.
|
|
21
|
+
문제 현상과 관련된 코드베이스를 분석한다.
|
|
22
|
+
- Agent tool (subagent_type: Explore)을 활용하여 관련 파일, 패키지, 의존성을 탐색한다
|
|
23
|
+
- 에러 메시지, 스택 트레이스, 코드 경로 등을 기반으로 관련 코드를 파악한다
|
|
24
|
+
- 필요에 따라 Glob, Grep, Read 등을 직접 사용할 수도 있다
|
|
25
|
+
- 분석 결과로 현재 상태, 관련 코드/패키지, 기존 구현 방식을 파악한다
|
|
23
26
|
|
|
24
|
-
##
|
|
27
|
+
## 3. 근본 원인 분석 및 해결책 제시
|
|
25
28
|
|
|
26
|
-
|
|
29
|
+
코드베이스 분석 결과를 바탕으로 문제의 근본 원인을 깊이 파고들어 분석하고, 각 원인별 해결책을 방안으로 제시한다.
|
|
27
30
|
|
|
28
|
-
|
|
31
|
+
**핵심 원칙 — 편법/우회방법 절대 금지:**
|
|
32
|
+
- 증상을 숨기는 해결이 아닌, 원인 자체를 제거하는 방향으로 분석한다
|
|
33
|
+
- 예: `setTimeout` 추가, `try-catch`로 에러 무시, 플래그 변수로 조건 우회 등은 편법이다
|
|
34
|
+
- 반드시 "왜 이 문제가 발생하는가?"를 근원까지 추적한다
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
하나의 문제에 대해 근본 원인을 여러 관점에서 분석할 수 있다. 각 원인 분석 + 그에 따른 해결책이 하나의 **방안**이 된다.
|
|
31
37
|
|
|
32
|
-
|
|
33
|
-
2. **No speculative fixes**: Do not attempt to find the cause through trial-and-error by modifying code and checking results. Read the code and trace the logic to identify the cause.
|
|
34
|
-
3. **No workarounds**: Do not propose solutions that mask symptoms, such as `as` type assertions, `any`, `// @ts-ignore`, hardcoding, or swallowing exceptions (ignoring after `catch`).
|
|
35
|
-
4. **Test failure triage**: When tests fail, first compare the intended behavior the test validates against the code's actual behavior. If the behavior change was intentional, update the test; if unintentional, fix the code. If intent cannot be determined, ask the user.
|
|
36
|
-
5. **Distinguish symptoms from causes**: The point where the error message appears may not be the actual cause. Trace back from the error location to find the real cause.
|
|
38
|
+
다음 구조로 방안들을 제시한다:
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
```
|
|
41
|
+
### 방안 1: {방안 제목}
|
|
42
|
+
- 근본 원인: {이 관점에서 본 원인 상세 분석}
|
|
43
|
+
- 해결 방안: {상세 설명}
|
|
44
|
+
- 점수: {N}/10
|
|
45
|
+
|
|
46
|
+
### 방안 2: {방안 제목}
|
|
47
|
+
- 근본 원인: {이 관점에서 본 원인 상세 분석}
|
|
48
|
+
- 해결 방안: {상세 설명}
|
|
49
|
+
- 점수: {N}/10
|
|
50
|
+
|
|
51
|
+
### 방안 3: {방안 제목}
|
|
52
|
+
- 근본 원인: {이 관점에서 본 원인 상세 분석}
|
|
53
|
+
- 해결 방안: {상세 설명}
|
|
54
|
+
- 점수: {N}/10
|
|
55
|
+
|
|
56
|
+
### 반론
|
|
57
|
+
- 설명: {이 문제를 굳이 수정하지 않아도 되는 이유}
|
|
58
|
+
- 점수: {N}/10
|
|
59
|
+
```
|
|
39
60
|
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
- **Impact scope**: List of files/functions affected by this problem
|
|
45
|
-
- **Resolution options**: Possible solutions (including target files for each)
|
|
61
|
+
- 1개 이상의 방안을 제시한다 (방안 수는 유동적)
|
|
62
|
+
- 각 방안과 "반론"은 모두 10점 만점으로 점수를 부여한다
|
|
63
|
+
- 점수 기준: 높을수록 해당 선택이 적절함을 의미한다
|
|
64
|
+
- 모든 방안은 편법/우회가 아닌 근원적 해결책이어야 한다
|
|
46
65
|
|
|
47
|
-
##
|
|
66
|
+
## 4. 결과 표시 및 선택
|
|
48
67
|
|
|
49
|
-
|
|
68
|
+
근본 원인 분석 결과 방안이 하나도 도출되지 않은 경우 "분석 결과 코드베이스에서 근본 원인을 식별할 수 없습니다."를 출력하고 문서 저장 없이 종료한다.
|
|
50
69
|
|
|
51
|
-
|
|
52
|
-
|
|
70
|
+
1. 모든 방안을 **자세한 설명을 텍스트로 먼저 출력**한다
|
|
71
|
+
- 각 방안의 근본 원인 분석 + 해결 방안 + 점수를 명확히 표시
|
|
72
|
+
- 반론의 상세 설명 + 점수를 명확히 표시
|
|
73
|
+
- 각 선택지 간 트레이드오프를 포함
|
|
74
|
+
2. **자동 결정 조건**에 해당하면 결정 결과를 텍스트로 출력한다
|
|
75
|
+
3. 자동 결정 조건에 해당하지 않으면 `AskUserQuestion`을 **1개만** 호출하여 방안 선택을 요청한다
|
|
76
|
+
- 선택지: 각 방안명 + "안함"
|
|
53
77
|
|
|
54
|
-
|
|
55
|
-
<Summarize the error/problem in one sentence>
|
|
78
|
+
**자동 결정 조건 (묻지 않는 경우):**
|
|
56
79
|
|
|
57
|
-
|
|
58
|
-
|
|
80
|
+
모든 선택지(방안들 + 반론)를 동등하게 놓고 비교한다:
|
|
81
|
+
- 반론 점수가 모든 방안 점수보다 높으면 (단 1점이라도) → 무조건 자동 거부 (안함, 사용자에게 묻지 않음)
|
|
82
|
+
- 예: 방안1 5점, 방안2 3점, 반론 6점 → 반론(6) > 방안1(5) 이므로 무조건 자동 거부
|
|
83
|
+
- 가장 높은 점수가 나머지 모든 점수 각각의 2배 이상이면 → 자동 결정
|
|
84
|
+
- 가장 높은 것이 방안이면 → 해당 방안 자동 채택
|
|
85
|
+
- 가장 높은 것이 반론이면 → 자동 거부 (안함)
|
|
86
|
+
- 예: 방안1 8점, 방안2 3점, 반론 2점 → 8 ≥ 3×2 이고 8 ≥ 2×2 이므로 방안1 자동 채택
|
|
87
|
+
- 예: 방안1 6점, 방안2 5점, 반론 4점 → 6 < 5×2 이므로 자동 결정 미충족 → AskUserQuestion
|
|
88
|
+
- 예: 방안1 3점, 방안2 2점, 반론 8점 → 8 ≥ 3×2 이고 8 ≥ 2×2 이므로 자동 거부
|
|
89
|
+
- 모든 선택지의 점수가 0이면 → "분석 결과 유효한 해결책을 도출할 수 없습니다."를 출력하고 종료한다
|
|
90
|
+
- 가장 높은 점수가 동점이면 → 자동 결정 불가 → AskUserQuestion으로 사용자에게 질문
|
|
59
91
|
|
|
60
|
-
|
|
61
|
-
<Explain the root cause clearly and specifically. Include file paths and line numbers.>
|
|
92
|
+
## 5. 결과 문서 저장
|
|
62
93
|
|
|
63
|
-
|
|
64
|
-
- <Affected file/function 1>
|
|
65
|
-
- <Affected file/function 2>
|
|
94
|
+
채택된 방안을 debug.md로 저장한다.
|
|
66
95
|
|
|
67
|
-
|
|
96
|
+
**파일 경로:**
|
|
97
|
+
- 디렉토리: `.tasks/{yyMMddHHmmss}_{topic}/`
|
|
98
|
+
- `yyMMddHHmmss`는 현재 시간 (Bash `date +%y%m%d%H%M%S`로 생성)
|
|
99
|
+
- `{topic}`은 1단계에서 변환한 kebab-case topic
|
|
100
|
+
- 파일명: `debug.md`
|
|
101
|
+
- 디렉토리가 없으면 먼저 생성한다
|
|
68
102
|
|
|
69
|
-
|
|
70
|
-
- Target files: <List of file paths>
|
|
71
|
-
- Behavioral change: <Does this change any existing behavior? "None — preserves intended behavior" or describe what changes>
|
|
72
|
-
- Pros: ...
|
|
73
|
-
- Cons: ...
|
|
103
|
+
**debug.md 구조:**
|
|
74
104
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
- Behavioral change: <Does this change any existing behavior? "None — preserves intended behavior" or describe what changes>
|
|
78
|
-
- Pros: ...
|
|
79
|
-
- Cons: ...
|
|
105
|
+
```markdown
|
|
106
|
+
# 디버그 결과: {topic 설명}
|
|
80
107
|
|
|
81
|
-
|
|
82
|
-
<The most appropriate option and the reasoning>
|
|
83
|
-
```
|
|
108
|
+
## 개요
|
|
84
109
|
|
|
85
|
-
|
|
110
|
+
{문제 현상의 목적과 배경}
|
|
86
111
|
|
|
87
|
-
|
|
88
|
-
Please review the diagnosis results.
|
|
89
|
-
1. The diagnosis is accurate — proceed with the recommended option
|
|
90
|
-
2. The diagnosis is accurate, but proceed with a different option (specify number)
|
|
91
|
-
3. The diagnosis is inaccurate — I will provide additional information
|
|
92
|
-
```
|
|
112
|
+
## 현재 상태
|
|
93
113
|
|
|
94
|
-
|
|
95
|
-
- **Option 2 selected**: Proceed to Step 4 based on the option specified by the user.
|
|
96
|
-
- **Option 3 selected**: Return to Step 2 incorporating the additional information provided by the user.
|
|
114
|
+
{코드베이스 분석 결과 - 관련 기존 코드/패키지, 현재 구현 방식, 관련 의존성}
|
|
97
115
|
|
|
98
|
-
##
|
|
116
|
+
## 요구사항
|
|
99
117
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
```
|
|
103
|
-
Formulate a plan to implement the resolution based on the following debugging diagnosis:
|
|
118
|
+
### R1. {채택된 방안명}
|
|
104
119
|
|
|
105
|
-
|
|
106
|
-
<Problem summary from Step 3>
|
|
120
|
+
**근본 원인**
|
|
107
121
|
|
|
108
|
-
|
|
109
|
-
<Root cause from Step 3>
|
|
122
|
+
{채택된 방안의 근본 원인 상세 분석}
|
|
110
123
|
|
|
111
|
-
|
|
112
|
-
<Detailed content of the resolution option selected by the user>
|
|
124
|
+
**해결 방안**
|
|
113
125
|
|
|
114
|
-
|
|
115
|
-
<List of target file paths from the resolution option>
|
|
126
|
+
{채택된 방안의 상세 내용}
|
|
116
127
|
```
|
|
117
128
|
|
|
118
|
-
|
|
129
|
+
- "안함"이 선택된 경우 debug.md를 저장하지 않고 "채택된 해결책이 없어 문서를 저장하지 않습니다."를 출력한다
|
|
119
130
|
|
|
120
|
-
|
|
131
|
+
## 6. 완료 안내
|
|
121
132
|
|
|
122
|
-
|
|
133
|
+
문서 작성이 완료되면 다음을 출력한다:
|
|
134
|
+
- 완성된 문서의 파일 경로
|
|
135
|
+
- 사용자에게 직접 문서를 확인할 것을 권장
|
|
136
|
+
- 다음 단계 안내: "다음 단계로 `/sd-plan`을 실행하세요."
|
|
@@ -1,109 +1,115 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sd-document
|
|
3
|
-
description:
|
|
3
|
+
description: 문서 파일(.docx/.xlsx/.pptx/.pdf)을 읽어 분석하거나, 새 문서를 생성. 사용자가 워드/엑셀/PPT/PDF 파일의 분석이나 생성을 요청할 때 사용
|
|
4
|
+
argument-hint: "<문서 파일 경로>"
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
#
|
|
7
|
+
# sd-document: 문서 파일 읽기/쓰기
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
문서 파일(.docx/.xlsx/.pptx/.pdf)을 Python 스크립트로 읽어 텍스트와 이미지를 추출하거나, 새 문서를 생성한다.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
## 1. 인자 파싱
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
`$ARGUMENTS`에서 문서 파일 경로를 추출한다.
|
|
14
|
+
- `$ARGUMENTS`가 비어있으면 현재 대화 맥락에서 `.docx`, `.xlsx`, `.pptx`, `.pdf` 파일 경로를 찾는다. 대화 맥락도 없으면 AskUserQuestion으로 파일 경로를 요청한다
|
|
15
|
+
- 지원 확장자(`.docx`, `.xlsx`, `.pptx`, `.pdf`)가 아니면 "지원하지 않는 파일 형식입니다"를 안내하고 종료한다
|
|
13
16
|
|
|
14
|
-
##
|
|
17
|
+
## 2. 작업 방향 결정
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
사용자의 요청이 **읽기**(분석/추출)인지 **쓰기**(생성)인지 **편집**(기존 파일 수정)인지 판단한다.
|
|
17
20
|
|
|
18
|
-
-
|
|
19
|
-
-
|
|
21
|
+
- **읽기** → 3단계로 이동
|
|
22
|
+
- **쓰기** → 5단계로 이동
|
|
23
|
+
- **편집** → 3단계로 먼저 이동하여 기존 내용을 파악한 뒤, 5단계에서 수정 스크립트를 작성한다
|
|
20
24
|
|
|
21
|
-
###
|
|
25
|
+
### 포맷별 지원 현황
|
|
22
26
|
|
|
23
|
-
|
|
|
24
|
-
|
|
25
|
-
| DOCX |
|
|
26
|
-
| XLSX |
|
|
27
|
-
| PPTX |
|
|
28
|
-
| PDF |
|
|
27
|
+
| 포맷 | 읽기 | 쓰기 | 라이브러리 |
|
|
28
|
+
|------|------|------|-----------|
|
|
29
|
+
| DOCX | 지원 | 지원 | `python-docx` |
|
|
30
|
+
| XLSX | 지원 | 지원 | `openpyxl`, `pandas` |
|
|
31
|
+
| PPTX | 지원 | 미지원 | `python-pptx` |
|
|
32
|
+
| PDF | 지원 | 미지원 | `pdfplumber`, `pypdf` |
|
|
29
33
|
|
|
30
|
-
|
|
34
|
+
누락 패키지는 스크립트 최초 실행 시 자동 설치된다.
|
|
31
35
|
|
|
32
|
-
##
|
|
36
|
+
## 3. 읽기: 추출 스크립트 실행
|
|
33
37
|
|
|
34
|
-
|
|
38
|
+
파일 확장자에 맞는 추출 스크립트를 Bash로 실행한다:
|
|
35
39
|
|
|
36
40
|
```bash
|
|
37
|
-
python
|
|
38
|
-
python
|
|
39
|
-
python
|
|
40
|
-
python
|
|
41
|
+
python ${CLAUDE_SKILL_DIR}/extract_docx.py <파일경로>
|
|
42
|
+
python ${CLAUDE_SKILL_DIR}/extract_xlsx.py <파일경로>
|
|
43
|
+
python ${CLAUDE_SKILL_DIR}/extract_pptx.py <파일경로>
|
|
44
|
+
python ${CLAUDE_SKILL_DIR}/extract_pdf.py <파일경로>
|
|
41
45
|
```
|
|
42
46
|
|
|
43
|
-
###
|
|
44
|
-
- **stdout**: Text and positional information (Markdown format)
|
|
45
|
-
- **Image files**: Saved to `<filename>_files/` directory
|
|
47
|
+
### 출력
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
- **stdout**: 텍스트 및 위치 정보 (Markdown 형식)
|
|
50
|
+
- **이미지 파일**: `<파일명>_files/` 디렉토리에 저장
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
|--------|----------------------|
|
|
51
|
-
| DOCX | Paragraph flow order (text-image inline) |
|
|
52
|
-
| XLSX | Cell position (A1, B2, etc.) |
|
|
53
|
-
| PPTX | Shape left/top coordinates (inches) + slide number |
|
|
54
|
-
| PDF | Page number |
|
|
52
|
+
### 위치 정보
|
|
55
53
|
|
|
56
|
-
|
|
54
|
+
| 포맷 | 위치 표현 |
|
|
55
|
+
|------|----------|
|
|
56
|
+
| DOCX | 문단 흐름 순서 (텍스트-이미지 인라인) |
|
|
57
|
+
| XLSX | 셀 위치 (A1, B2 등) |
|
|
58
|
+
| PPTX | Shape 좌표 (left/top 인치) + 슬라이드 번호 |
|
|
59
|
+
| PDF | 페이지 번호 |
|
|
57
60
|
|
|
58
|
-
|
|
61
|
+
## 4. 읽기: 추출 결과 분석
|
|
59
62
|
|
|
60
|
-
|
|
61
|
-
2. **Text**: Analyze/summarize the text output to stdout according to the user's request
|
|
63
|
+
3단계 출력에서 추출된 파일 경로를 확인하고 다음을 수행한다:
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
1. **이미지**: `_files/` 디렉토리에 저장된 각 이미지를 **Read** 도구로 열어 시각적 분석
|
|
66
|
+
2. **텍스트**: stdout에 출력된 텍스트를 사용자 요청에 맞게 분석/요약
|
|
64
67
|
|
|
65
|
-
|
|
68
|
+
분석 완료 후 종료한다.
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
## 5. 쓰기: 문서 생성/편집
|
|
68
71
|
|
|
69
|
-
|
|
72
|
+
사용자 요청에 따라 Python 스크립트를 작성하여 문서를 생성하거나 편집한다.
|
|
73
|
+
PPTX, PDF 쓰기는 미지원이므로 요청 시 안내한다.
|
|
74
|
+
|
|
75
|
+
### DOCX (`python-docx`)
|
|
70
76
|
|
|
71
77
|
```python
|
|
72
78
|
from docx import Document
|
|
73
79
|
|
|
74
|
-
doc = Document() #
|
|
75
|
-
# doc = Document("existing.docx") #
|
|
76
|
-
doc.add_heading("
|
|
77
|
-
doc.add_paragraph("
|
|
80
|
+
doc = Document() # 새 문서
|
|
81
|
+
# doc = Document("existing.docx") # 기존 문서 편집
|
|
82
|
+
doc.add_heading("제목", level=1)
|
|
83
|
+
doc.add_paragraph("본문 내용")
|
|
78
84
|
table = doc.add_table(rows=2, cols=3)
|
|
79
|
-
table.cell(0, 0).text = "
|
|
85
|
+
table.cell(0, 0).text = "항목"
|
|
80
86
|
doc.save("output.docx")
|
|
81
87
|
```
|
|
82
88
|
|
|
83
|
-
|
|
89
|
+
기존 문서 편집: `Document("existing.docx")`로 열어 `paragraph.text`, `table.cell().text`를 수정한다.
|
|
84
90
|
|
|
85
91
|
### XLSX (`openpyxl`)
|
|
86
92
|
|
|
87
|
-
|
|
93
|
+
데이터와 수식 중심. 서식(색상, 테두리)은 필수가 아니다.
|
|
88
94
|
|
|
89
95
|
```python
|
|
90
96
|
from openpyxl import Workbook
|
|
91
97
|
|
|
92
98
|
wb = Workbook()
|
|
93
99
|
ws = wb.active
|
|
94
|
-
ws["A1"] = "
|
|
95
|
-
ws["B1"] = "
|
|
96
|
-
ws.append(["
|
|
97
|
-
ws.append(["
|
|
100
|
+
ws["A1"] = "항목"
|
|
101
|
+
ws["B1"] = "수량"
|
|
102
|
+
ws.append(["사과", 10])
|
|
103
|
+
ws.append(["배", 20])
|
|
98
104
|
ws["B4"] = "=SUM(B2:B3)"
|
|
99
105
|
wb.save("output.xlsx")
|
|
100
106
|
```
|
|
101
107
|
|
|
102
|
-
|
|
103
|
-
|
|
108
|
+
기존 파일 편집: `load_workbook("existing.xlsx")`로 열어 수정한다.
|
|
109
|
+
pandas DataFrame 내보내기: `df.to_excel("output.xlsx", index=False)`
|
|
104
110
|
|
|
105
|
-
##
|
|
111
|
+
## 6. 주의사항
|
|
106
112
|
|
|
107
|
-
-
|
|
108
|
-
-
|
|
109
|
-
- **XLSX data_only**: `load_workbook(data_only=True)
|
|
113
|
+
- **문자 인코딩**: 스크립트에 UTF-8 처리가 내장되어 있으므로 반드시 스크립트를 통해 추출한다
|
|
114
|
+
- **이미지 누락**: 추출 후 `_files/` 디렉토리의 이미지를 반드시 Read한다
|
|
115
|
+
- **XLSX data_only**: `load_workbook(data_only=True)`는 수식을 제거한다. 수식 보존이 필요하면 `data_only=False`를 사용한다
|
|
@@ -32,13 +32,8 @@ def print_header(file_path: Path):
|
|
|
32
32
|
print(f"# {file_path.name}\n")
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
_created_dirs: set[Path] = set()
|
|
36
|
-
|
|
37
|
-
|
|
38
35
|
def save_image(out_dir: Path, img_idx: int, blob: bytes, ext: str) -> Path:
|
|
39
|
-
|
|
40
|
-
out_dir.mkdir(parents=True, exist_ok=True)
|
|
41
|
-
_created_dirs.add(out_dir)
|
|
36
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
42
37
|
img_path = out_dir / f"img_{img_idx:03d}.{ext}"
|
|
43
38
|
img_path.write_bytes(blob)
|
|
44
39
|
return img_path
|