@simplysm/sd-claude 14.0.46 → 14.0.47

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.
@@ -219,6 +219,15 @@ abstract class SdSharedDataProvider<T extends Record<string, SharedDataBase<stri
219
219
  | `emitAsync(name, changeKeys?)` | 변경 이벤트 발행. 내부에서 `client.getEvent<typeof SdSharedDataChangeEvent>("SdSharedDataChange").emit(...)` 호출 |
220
220
  | `wait()` | 모든 로딩 완료까지 대기 |
221
221
 
222
+ ### 로딩 전략 (Lazy Loading)
223
+
224
+ **`register()`는 메타정보만 등록하고 실제 데이터를 가져오지 않는다.** 타입별 데이터는 해당 타입의 `getHandle(name)`이 **처음 호출되는 시점**에 `info.getter()`를 실행하여 로딩된다. 즉 `initialize()`에서 여러 타입을 `register()` 해도 앱 시작 시 전체가 일괄 로딩되지 않으며, 실제로 사용되는 타입만 온디맨드로 로딩된다.
225
+
226
+ - 첫 `getHandle()` 호출 → `getter()` 실행 + `SdSharedDataChange` 리스너 등록
227
+ - 이후 같은 타입의 `getHandle()` 호출은 캐시된 `itemsSignal`을 재사용
228
+ - 이후 갱신은 서버에서 `emitAsync()`로 발행된 `SdSharedDataChange` 이벤트 수신 시에만 발생 (`changeKeys`가 있으면 부분 업데이트, 없으면 전체 리로드)
229
+ - `register()`를 동일 `name`으로 재호출하면 `generation`이 증가하고 `needsReload=true`로 표시되어, 다음 `getHandle()` 호출 시 재로딩된다
230
+
222
231
  ## `SdSharedDataChangeEvent`
223
232
 
224
233
  공유 데이터 변경 이벤트 정의. `defineEvent`로 생성되며, 이벤트 이름 문자열 `"SdSharedDataChange"`를 인자로 받는다.
@@ -36,9 +36,14 @@ class SdCollapseIcon {
36
36
 
37
37
  ## Tab
38
38
 
39
+ > **CRITICAL — 역할 범위**
40
+ > `sd-tab`/`sd-tab-item`은 **상단의 탭 선택 UI만** 담당한다. 내부 뷰(패널) 전환 기능은 **없다**.
41
+ > `sd-tab-item`의 `<ng-content>`는 **탭 라벨 전용**이다. 이 안에 시트/폼/상세 등 뷰 콘텐츠를 넣지 않는다.
42
+ > 뷰 콘텐츠는 `sd-tab` **바깥**에서 선택된 `value`를 기준으로 `@if` / `@switch`로 제어한다.
43
+
39
44
  ### `SdTab`
40
45
 
41
- 탭 컨테이너 컴포넌트.
46
+ 탭 컨테이너 컴포넌트. 선택된 값을 `value` model로 보관한다.
42
47
 
43
48
  ```typescript
44
49
  @Component({ selector: "sd-tab" })
@@ -49,7 +54,7 @@ class SdTab<T> {
49
54
 
50
55
  ### `SdTabItem`
51
56
 
52
- 탭 항목 컴포넌트.
57
+ 탭 항목 컴포넌트. 자신의 `value`가 부모 `SdTab.value`와 같으면 선택 상태가 된다. 클릭 시 부모 `value`를 자신의 `value`로 세팅한다.
53
58
 
54
59
  ```typescript
55
60
  @Component({ selector: "sd-tab-item" })
@@ -58,6 +63,33 @@ class SdTabItem<T> {
58
63
  }
59
64
  ```
60
65
 
66
+ ### 사용 예시
67
+
68
+ ```html
69
+ <!-- ✅ 올바른 사용: 탭은 선택 UI, 뷰는 @if로 제어 -->
70
+ <sd-tab [(value)]="tab">
71
+ <sd-tab-item [value]="'list'">목록</sd-tab-item>
72
+ <sd-tab-item [value]="'detail'">상세</sd-tab-item>
73
+ </sd-tab>
74
+
75
+ @if (tab() === "list") {
76
+ <sd-sheet ...></sd-sheet>
77
+ }
78
+ @if (tab() === "detail") {
79
+ <app-detail ...></app-detail>
80
+ }
81
+ ```
82
+
83
+ ```html
84
+ <!-- ❌ 잘못된 사용: sd-tab-item 안에 뷰 콘텐츠를 넣음 -->
85
+ <sd-tab [(value)]="tab">
86
+ <sd-tab-item [value]="'list'">
87
+ 목록
88
+ <sd-sheet ...></sd-sheet> <!-- 금지: 라벨 영역에 뷰를 넣지 않는다 -->
89
+ </sd-tab-item>
90
+ </sd-tab>
91
+ ```
92
+
61
93
  ## Pagination
62
94
 
63
95
  ### `SdPagination`
@@ -371,6 +371,16 @@ export class ExcelCell {
371
371
 
372
372
  셀 스타일을 설정한다. 기존 스타일이 있으면 클론 후 병합한다.
373
373
 
374
+ 커스텀 Excel formatCode를 지정하려면 `numberFormatCode`를 사용한다:
375
+
376
+ ```typescript
377
+ await cell.setStyle({ numberFormatCode: "0.000000" }); // 소수점 6자리
378
+ await cell.setStyle({ numberFormatCode: "#,##0.00" }); // 천 단위 구분 + 2자리
379
+ await cell.setStyle({ numberFormatCode: "0.00%" }); // 퍼센트
380
+ ```
381
+
382
+ `numberFormat`(프리셋)과 `numberFormatCode`(커스텀)가 동시에 지정되면 `numberFormatCode`가 우선 적용된다.
383
+
374
384
  | Parameter | Type | Description |
375
385
  |-----------|------|-------------|
376
386
  | `opts` | `ExcelStyleOptions` | 스타일 옵션 (배경색, 테두리, 정렬, 숫자 형식) |
@@ -82,6 +82,7 @@ export interface ExcelStyleOptions {
82
82
  horizontalAlign?: ExcelHorizontalAlign;
83
83
  verticalAlign?: ExcelVerticalAlign;
84
84
  numberFormat?: ExcelNumberFormat;
85
+ numberFormatCode?: string;
85
86
  }
86
87
  ```
87
88
 
@@ -91,7 +92,10 @@ export interface ExcelStyleOptions {
91
92
  | `border` | `ExcelBorderPosition[] \| undefined` | 테두리 위치 배열 |
92
93
  | `horizontalAlign` | `ExcelHorizontalAlign \| undefined` | 가로 정렬 |
93
94
  | `verticalAlign` | `ExcelVerticalAlign \| undefined` | 세로 정렬 |
94
- | `numberFormat` | `ExcelNumberFormat \| undefined` | 숫자 형식 |
95
+ | `numberFormat` | `ExcelNumberFormat \| undefined` | 숫자 형식 프리셋 |
96
+ | `numberFormatCode` | `string \| undefined` | 커스텀 Excel formatCode 문자열 (예: `"0.000000"`, `"#,##0.00"`, `"0.00%"`) |
97
+
98
+ **우선순위:** `numberFormatCode`가 지정되면 `numberFormat`보다 우선 적용된다. 동일한 formatCode는 `numFmts`에 중복 등록되지 않는다.
95
99
 
96
100
  ### `ExcelBorderPosition`
97
101
 
@@ -57,7 +57,7 @@ claude/
57
57
  ---
58
58
  name: sd-commit
59
59
  description: 전체 변경사항에 대한 단일 커밋을 생성하는 스킬. ...
60
- model: haiku
60
+ model: claude-haiku-4-5
61
61
  ---
62
62
  ```
63
63
 
@@ -13,23 +13,23 @@ import type { ServiceMethods } from "@simplysm/service-server";
13
13
 
14
14
  ## 패키지별 상세 문서
15
15
 
16
- | 패키지 | 문서 |
17
- | -------------------------------------- | ----------------------------------------------------------------------------- |
18
- | @simplysm/angular | [usage.md](../references/sd-simplysm14/angular/usage.md) |
19
- | @simplysm/capacitor-plugin-auto-update | [usage.md](../references/sd-simplysm14/capacitor-plugin-auto-update/usage.md) |
20
- | @simplysm/capacitor-plugin-file-system | [usage.md](../references/sd-simplysm14/capacitor-plugin-file-system/usage.md) |
21
- | @simplysm/capacitor-plugin-intent | [usage.md](../references/sd-simplysm14/capacitor-plugin-intent/usage.md) |
22
- | @simplysm/capacitor-plugin-usb-storage | [usage.md](../references/sd-simplysm14/capacitor-plugin-usb-storage/usage.md) |
23
- | @simplysm/core-browser | [usage.md](../references/sd-simplysm14/core-browser/usage.md) |
24
- | @simplysm/core-common | [usage.md](../references/sd-simplysm14/core-common/usage.md) |
25
- | @simplysm/core-node | [usage.md](../references/sd-simplysm14/core-node/usage.md) |
26
- | @simplysm/excel | [usage.md](../references/sd-simplysm14/excel/usage.md) |
27
- | @simplysm/lint | [usage.md](../references/sd-simplysm14/lint/usage.md) |
28
- | @simplysm/orm-common | [usage.md](../references/sd-simplysm14/orm-common/usage.md) |
29
- | @simplysm/orm-node | [usage.md](../references/sd-simplysm14/orm-node/usage.md) |
30
- | @simplysm/sd-claude | [usage.md](../references/sd-simplysm14/sd-claude/usage.md) |
31
- | @simplysm/sd-cli | [usage.md](../references/sd-simplysm14/sd-cli/usage.md) |
32
- | @simplysm/service-client | [usage.md](../references/sd-simplysm14/service-client/usage.md) |
33
- | @simplysm/service-common | [usage.md](../references/sd-simplysm14/service-common/usage.md) |
34
- | @simplysm/service-server | [usage.md](../references/sd-simplysm14/service-server/usage.md) |
35
- | @simplysm/storage | [usage.md](../references/sd-simplysm14/storage/usage.md) |
16
+ | 패키지 | 문서 |
17
+ | -------------------------------------- | ----------------------------------------------------------------- |
18
+ | @simplysm/angular | [usage.md](./sd-simplysm14/angular/usage.md) |
19
+ | @simplysm/capacitor-plugin-auto-update | [usage.md](./sd-simplysm14/capacitor-plugin-auto-update/usage.md) |
20
+ | @simplysm/capacitor-plugin-file-system | [usage.md](./sd-simplysm14/capacitor-plugin-file-system/usage.md) |
21
+ | @simplysm/capacitor-plugin-intent | [usage.md](./sd-simplysm14/capacitor-plugin-intent/usage.md) |
22
+ | @simplysm/capacitor-plugin-usb-storage | [usage.md](./sd-simplysm14/capacitor-plugin-usb-storage/usage.md) |
23
+ | @simplysm/core-browser | [usage.md](./sd-simplysm14/core-browser/usage.md) |
24
+ | @simplysm/core-common | [usage.md](./sd-simplysm14/core-common/usage.md) |
25
+ | @simplysm/core-node | [usage.md](./sd-simplysm14/core-node/usage.md) |
26
+ | @simplysm/excel | [usage.md](./sd-simplysm14/excel/usage.md) |
27
+ | @simplysm/lint | [usage.md](./sd-simplysm14/lint/usage.md) |
28
+ | @simplysm/orm-common | [usage.md](./sd-simplysm14/orm-common/usage.md) |
29
+ | @simplysm/orm-node | [usage.md](./sd-simplysm14/orm-node/usage.md) |
30
+ | @simplysm/sd-claude | [usage.md](./sd-simplysm14/sd-claude/usage.md) |
31
+ | @simplysm/sd-cli | [usage.md](./sd-simplysm14/sd-cli/usage.md) |
32
+ | @simplysm/service-client | [usage.md](./sd-simplysm14/service-client/usage.md) |
33
+ | @simplysm/service-common | [usage.md](./sd-simplysm14/service-common/usage.md) |
34
+ | @simplysm/service-server | [usage.md](./sd-simplysm14/service-server/usage.md) |
35
+ | @simplysm/storage | [usage.md](./sd-simplysm14/storage/usage.md) |
@@ -79,12 +79,15 @@
79
79
  - **클래스 필드 vs prototype**: `Object.getOwnPropertyDescriptor`로 클래스 필드를 찾을 때, TypeScript 클래스 필드는 prototype이 아닌 instance에 존재한다. prototype에서 찾으면 `undefined` 반환
80
80
  - **요청하지 않은 기능 추가 금지**: 원본 코드에 없고 사용자가 요청하지 않은 기능을 임의로 추가하지 않는다. 기존 코드의 이벤트/패턴을 그대로 유지하고, 요청된 변경만 수행한다.
81
81
  - **프로젝트 구조 이해 필수**: 코드를 배치하기 전에 해당 디렉토리가 빌드 산출물인지, 영구 소스인지 반드시 확인한다. 모르면 사용자에게 질문한다.
82
+ - `eslint-disable @typescript-eslint/require-await` 금지
82
83
 
83
84
  # @simplysm 패키지 참조
84
85
 
85
- - `@simplysm/*` 패키지 사용 시, `.claude/references/sd-simplysm{메이저버전}.md`를 읽고 해당 패키지의 문서 경로를 찾아 읽는다.
86
- - 해당 문서에는 지침 및 사용법이 기록되어 있다.
87
- - 주의사항: 해당 패키지의 `CLAUDE.md`를 읽는것이 아니다.
86
+ - `@simplysm/*` 패키지 사용 시, 해당 참조문서를 읽고 해당 패키지의 문서 경로를 찾아 읽는다.
87
+ - v14: `.claude/references/sd-simplysm14.md`
88
+ - v12: `.claude/references/sd-simplysm12.md`
89
+ - 해당 문서에는 지침 및 사용법이 기록되어 있다.
90
+ - 주의사항: 해당 패키지의 `CLAUDE.md`를 읽는것이 아니다.
88
91
  - simplysm 패키지의 경우 context7은 구버전일 수 있으니 사용을 지양한다.
89
92
 
90
93
  # 프로젝트 경계
@@ -1,8 +1,7 @@
1
1
  ---
2
2
  name: sd-claude-docs
3
3
  description: 프로젝트 분석을 통해 CLAUDE.md와 LLM용 usage 문서를 동시 생성하는 스킬. "init", "CLAUDE.md 생성", "usage 문서 생성", "LLM 문서 만들어줘", "패키지 문서 생성" 등을 요청할 때 사용한다.
4
- model: sonnet[1m]
5
- effort: low
4
+ model: claude-sonnet-4-5
6
5
  ---
7
6
 
8
7
  # sd-claude-docs: CLAUDE.md + usage 문서 통합 생성
@@ -91,7 +90,7 @@ root 문서는 생성·변경하지 않는다.
91
90
 
92
91
  ## Step 3: 패키지별 문서 생성 (모노레포)
93
92
 
94
- 각 패키지에 대해 **Agent 도구로 subagent(model: `sonnet`, effort: `low`)를 병렬 실행**한다.
93
+ 각 패키지에 대해 **Agent 도구로 subagent(model: `claude-sonnet-4-5`)를 병렬 실행**한다.
95
94
  하나의 메시지에서 모든 패키지의 Agent 호출을 동시에 보낸다.
96
95
 
97
96
  ### subagent 프롬프트
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: sd-commit
3
3
  description: 전체 변경사항에 대한 단일 커밋을 생성하는 스킬. "커밋", "commit", "변경사항 커밋" 등을 요청할 때 사용한다.
4
- model: haiku
4
+ model: claude-haiku-4-5
5
5
  ---
6
6
 
7
7
  # sd-commit: 그룹별 커밋
@@ -1,8 +1,7 @@
1
1
  ---
2
2
  name: sd-deliverable
3
3
  description: 코드 분석 기반으로 사용자 매뉴얼(md)과 SIT 문서(md)를 생성·업데이트하는 스킬. "매뉴얼 만들어줘", "SIT 문서 만들어줘", "산출물 생성", "매뉴얼 업데이트" 등을 요청할 때 사용한다.
4
- model: sonnet
5
- effort: low
4
+ model: claude-sonnet-4-5
6
5
  ---
7
6
 
8
7
  # sd-deliverable: 매뉴얼 & SIT 생성
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: sd-doc-extract
3
3
  description: 문서 파일(docx, xlsx, xlsb, pptx, pdf, eml, msg)에서 텍스트, 이미지, 임베디드 파일을 추출하는 스킬. "문서 추출", "문서 분해", "docx 분석", "PDF 내용 뽑아줘", "eml 파일 추출" 등을 요청할 때 사용한다.
4
- model: haiku
4
+ model: claude-haiku-4-5
5
5
  ---
6
6
 
7
7
  # sd-doc-extract: 문서 분해/추출
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: sd-issue
3
3
  description: simplysm 라이브러리에 대한 GitHub 이슈를 생성하는 스킬. "이슈 생성", "이슈 등록", "버그 리포트" 등을 요청할 때 사용한다.
4
- model: haiku
4
+ model: claude-haiku-4-5
5
5
  ---
6
6
 
7
7
  # sd-issue: simplysm 이슈 생성
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: sd-outlook
3
3
  description: Microsoft Graph API를 통해 Outlook 메일을 검색·다운로드하는 스킬. "메일 조회", "메일 검색", "특정 업체 메일 수집", "outlook" 등을 요청할 때 사용한다.
4
- model: haiku
4
+ model: claude-haiku-4-5
5
5
  ---
6
6
 
7
7
  # sd-outlook: Outlook 메일 검색/다운로드
@@ -33,7 +33,14 @@ description: 스킬/프롬프트 파일의 작성·개선을 위한 EDD 스킬.
33
33
 
34
34
  ## Step 2: Eval 시나리오 정의
35
35
 
36
- 프롬프트 작성 전에 성공여부를 판단하기 위한 Eval문서를 먼저 작성한다.
36
+ Eval은 스킬/프롬프트가 틀에서 작동하는지 보는 **스모크 테스트**이다. 세부 지시를 하나하나 검증하지 않으므로, 가볍고 빠르게 돈다.
37
+
38
+ ### 시나리오 구성 원칙
39
+
40
+ - **시나리오**: 최소 성공 시나리오 1~2개 및 회귀 테스트 시나리오
41
+ - **happy-path 중심**: 대표적 성공 케이스 1개는 프롬프트 작성 전에 먼저 작성한다. 실사용에서 실패가 관찰되면 회귀 테스트로 추가한다
42
+ - **사전 조건 최소화**: 긴 파일 세팅·복잡한 디렉토리 구성 요구 지양
43
+ - **빠른 실행**: 수분 내 종료되는 단순 입력으로 구성한다
37
44
 
38
45
  ### Eval 유형
39
46
 
@@ -46,48 +53,44 @@ description: 스킬/프롬프트 파일의 작성·개선을 위한 EDD 스킬.
46
53
 
47
54
  Judge의 정확도는 체크리스트의 품질에 달려있다. 다음 원칙을 따른다:
48
55
 
49
- #### 1) 행동/결과 중심 — 도구명을 사용하지 않는다
56
+ #### 1) 산출물 중심 — 과정이 아닌 결과를 본다
57
+
58
+ 체크리스트는 **스킬/프롬프트가 만들어낸 산출물이 목적을 달성했는가**를 본다. 중간 과정·도구 사용·질문 여부는 체크하지 않는다.
50
59
 
51
- 특정 도구에 의존하면 환경에 따라 판정이 달라진다. "무엇을 했는가"를 기술한다:
52
- 특히 AskUserQuestion의 경우 Eval환경에서는 질문하지 않고 답을 스스로 도출하므로, 이에 유의한다.
53
60
  ```
54
- (X) "불명확한 부분에 대해 AskUserQuestion 도구를 호출했다"
55
- (O) "불명확한 부분에 대한 선택을 제시했다."
61
+ (X) "불명확한 부분에 대해 사용자에게 질문했다" — 프로세스
62
+ (X) "Read 도구로 파일을 읽었다" — 도구 사용
63
+ (X) "FAIL 원인을 분석하고 개선안을 제시했다" — 프로세스
56
64
 
57
- (X) "Read 도구로 파일을 읽었다"
58
- (O) "파일을 읽었다."
65
+ (O) "Impact Mapping 트리(Goal→Actor→Impact→Deliverable)가 산출되었다"
66
+ (O) "모든 Feature가 Goal까지 역추적 가능하다"
67
+ (O) "SKILL.md에 프론트매터(name, description)가 포함되었다"
68
+ ```
59
69
 
60
- (X) "Glob으로 탐색했다"
61
- (O) "기존 스킬 목록이 출력에 반영되어 있다"
70
+ #### 2) 상황 의존 금지 — 구조·구현 세부에 종속되지 않는다
71
+
72
+ SKILL.md의 Step 구조·도구명·파일 형식 같은 구현 세부에 종속된 항목은 배제한다. 구조가 바뀌면 체크도 깨지기 때문이다.
73
+
74
+ ```
75
+ (X) "Eval 파일이 프롬프트보다 먼저 작성되었다" — Step 순서에 종속
76
+ (X) "격리된 workspace(.tmp/)에서 claude -p가 실행되었다" — 실행 환경 세부
77
+ (O) "신규 스킬 요청에 대해 SKILL.md가 생성되었다" — 스킬 목적 자체
62
78
  ```
63
79
 
64
- #### 2) 객관적 기준 — 주관적 표현을 제거한다
80
+ #### 3) 객관적 기준 — 주관적 표현을 제거한다
65
81
 
66
82
  ```
67
83
  (X) "프롬프트 내용이 좋은가"
68
84
  (O) "모호한 표현('적절한', '필요시', '경우에 따라' 등)이 없는가"
69
85
  ```
70
86
 
71
- #### 3) 단일 기준 — 하나의 항목은 하나만 평가한다
87
+ #### 4) 단일 기준 — 하나의 항목은 하나만 평가한다
72
88
 
73
89
  ```
74
90
  (X) "파일을 읽고 올바른 분석을 출력했다"
75
- (O) "해당 파일을 읽었다."
76
91
  (O) "분석 결과가 사실에 부합한다"
77
92
  ```
78
93
 
79
- #### 4) 프로세스 중심 — 추론 결과가 아닌 규칙 적용 여부를 평가한다
80
-
81
- LLM이 특정 형태의 결과를 출력했는지가 아니라, 프로세스/규칙을 따랐는지를 기준으로 작성한다:
82
-
83
- ```
84
- (X) "기존 스킬/룰 목록이 출력에 포함되었다" — 특정 출력 형태를 기대
85
- (O) "기존 스킬/룰과의 충돌·중복 여부를 확인했다" — 규칙 적용 여부를 평가
86
-
87
- (X) "3개의 개선안이 출력에 포함되었다" — 추론 결과의 수량을 기대
88
- (O) "FAIL 원인을 분석하고 개선안을 제시했다" — 프로세스 수행 여부를 평가
89
- ```
90
-
91
94
  ### Eval 파일 형식
92
95
 
93
96
  #### 입력 작성 원칙
@@ -137,7 +140,6 @@ LLM이 특정 형태의 결과를 출력했는지가 아니라, 프로세스/규
137
140
  - **강한 규칙에 키워드를 구분한다** — `MUST`, `NEVER`, `ALWAYS`, `CRITICAL`, `IMPORTANT`, `required`, `prohibited`. IMPORTANT/CRITICAL은 진짜 중요한 규칙에만 사용한다.
138
141
  - **모호한 표현을 제거한다** — "적절하게", "필요시", "경우에 따라" 등은 LLM이 추측하게 만든다. 구체적인 조건과 행동으로 바꾸거나 AskUserQuestion을 활용한다.
139
142
  - **간결하게 유지한다** — SKILL.md는 200줄 이하를 목표로 한다. 200줄이 넘을 경우 "Progressive Disclosure" 원칙에 따라 파일을 분리한다.
140
- - **과적합을 방지한다** — 특정 Eval 시나리오에만 맞추지 말고, 일반적으로 통하는 표현으로 작성한다.
141
143
 
142
144
  ## Step 4: Eval 실행 & 판정
143
145
 
@@ -156,15 +158,13 @@ Judge 보고서의 개선 제안을:
156
158
 
157
159
  ## Step 5: 프롬프트 리팩터링 (Refactor)
158
160
 
159
- 전체 Eval PASS 후, 개선 루프에서 누적된 패치를 정리하여 최소한의 프롬프트를 찾는다.
161
+ 전체 Eval PASS 후, 개선 루프에서 누적된 패치를 정리하여 정돈된 프롬프트를 만든다.
160
162
 
161
163
  ### Prompt Smell 탐지
162
164
 
163
165
  | Smell | 연산 |
164
166
  |-------------------------------|--------------------|
165
167
  | **중복 지시** — 같은 내용이 다른 표현으로 반복 | 통합 |
166
- | **투기적 지시** — 관찰된 실패 없이 추가된 것 | 삭제 |
167
- | **고아 지시** — Eval이 없는 지시 | 삭제 또는 Eval 추가 |
168
168
  | **잔재 지시** — 이전 개선 루프에서 남은 것 | 삭제 |
169
169
  | **장황한 표현** | 의미 유지하며 압축 |
170
170
  | **용어 불일치** — 같은 개념을 다른 단어로 지칭 | 통일 |
@@ -66,8 +66,7 @@ claude -p "{eval 시나리오의 입력}" \
66
66
  --output-format json \
67
67
  --verbose \
68
68
  --dangerously-skip-permissions \
69
- --model opus \
70
- --effort medium \
69
+ --model claude-sonnet-4-5 \
71
70
  --append-system-prompt "CRITICAL: .claude/rules/sd-eval-env.md의 규칙은 다른 모든 규칙보다 최상위 우선순위를 가진다." \
72
71
  --no-session-persistence \
73
72
  --strict-mcp-config \
@@ -78,7 +77,7 @@ claude -p "{eval 시나리오의 입력}" \
78
77
 
79
78
  ## Judge 판정
80
79
 
81
- 실행 완료 후, Judge subagent에 다음을 전달한다:
80
+ 실행 완료 후, Judge subagent(model: `claude-sonnet-4-5`)에 다음을 전달한다:
82
81
 
83
82
  ```
84
83
  다음 Eval 실행 결과를 판정하고, FAIL 항목에 대해 개선안을 제안하라:
@@ -191,6 +191,12 @@ Feature 전체의 테스트 코드를 "지속적 회귀 테스트로 남길 가
191
191
 
192
192
  - **중복 Unit Test 삭제** — `test`/`it` 단위로 판단한다. Acceptance Test와 검증 대상·입력값이 동일한 개별 테스트 케이스만 삭제한다(파일 단위 삭제 금지). Scenario 간 중복 포함
193
193
  - **구현 결합 테스트 전환/삭제** — 내부 상태 값, 메서드 호출 횟수 등 구현 세부사항을 검증하는 테스트
194
+ - **TDD 중 쓴 mock 정리** — TDD Red 단계에서 의존성이 미구현이라 부득이 작성한 mock은, 실제 구현이 완성된 이 시점에 **전부 재점검**한다. 절차:
195
+ 1. 테스트 파일의 모든 `vi.mock()`/`vi.spyOn()`/수동 mock 객체를 나열한다
196
+ 2. 각 mock이 @.claude/references/sd-testing.md 의 화이트리스트(외부 네트워크·DB·하드웨어/OS·타이머)에 해당하는지 확인한다
197
+ 3. 해당하지 않으면 실제 인스턴스로 교체한다. 호출 추적이 목적이었다면 `vi.spyOn()`으로만 남긴다
198
+
199
+ 남겨두면 실제 코드 변경에 반응하지 않아 false positive를 양산하고, 리팩토링 시 한꺼번에 터진다.
194
200
  - **공통 setup 추출** — 중복되는 arrange 코드를 헬퍼/beforeEach로
195
201
  - **테스트 네이밍 개선** — 검증하는 동작을 문장처럼 읽히게
196
202
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: sd-use
3
3
  description: 자연어 요청을 적절한 sd-* 스킬로 라우팅하는 스킬. "sd-use 커밋해줘", "sd-use --help" 등을 요청할 때 사용한다.
4
- model: haiku
4
+ model: claude-haiku-4-5
5
5
  ---
6
6
 
7
7
  # sd-use: SD 스킬 라우터
@@ -74,6 +74,7 @@ Feature는 독립적으로 설계·개발·검증할 수 있는 최소 기능
74
74
  묶지 않음)
75
75
  - 범주는 Epic, 개별 기능이 Feature (예: "알림" Epic → 토스트 알림, 모달 알림, 이메일 알림 각각이 Feature)
76
76
  - 가능한한 의존성 순서로 정렬
77
+ - **테스트 작성을 별도 Feature로 분리하지 않는다(NEVER).** 각 Feature는 `sd-tdd`로 구현될 때 테스트와 프로덕션 코드를 함께 작성한다.
77
78
 
78
79
  ### Feature 작성 규칙
79
80
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simplysm/sd-claude",
3
- "version": "14.0.46",
3
+ "version": "14.0.47",
4
4
  "description": "심플리즘 패키지 - Claude Code 셋업",
5
5
  "author": "심플리즘",
6
6
  "license": "Apache-2.0",