@simplysm/sd-claude 14.0.56 → 14.0.58
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/references/sd-simplysm-v14/angular/ui-data/sd-crud-list.md +99 -1
- package/claude/references/sd-simplysm-v14/angular/ui-data/sd-sheet.md +27 -0
- package/claude/references/sd-simplysm-v14/angular/ui-form/sd-select.md +20 -0
- package/claude/references/sd-simplysm-v14/sd-claude/assets.md +3 -5
- package/claude/rules/sd-claude-rules.md +31 -2
- package/claude/rules/sd-options.md +19 -22
- package/claude/rules/sd-response-format.md +36 -0
- package/claude/skills/sd-check/SKILL.md +30 -3
- package/claude/skills/sd-clarify/SKILL.md +94 -0
- package/claude/skills/sd-claude-docs/SKILL.md +62 -29
- package/claude/skills/sd-claude-docs/merge-source.py +47 -0
- package/claude/skills/sd-commit/SKILL.md +3 -11
- package/claude/skills/sd-debug/SKILL.md +322 -31
- package/claude/skills/sd-debug/references/ach-matrix.md +154 -0
- package/claude/skills/sd-debug/references/branching-5whys.md +126 -0
- package/claude/skills/sd-debug/references/fishbone-categories.md +142 -0
- package/claude/skills/sd-debug/references/fta-template.md +176 -0
- package/claude/skills/sd-debug/references/repro-collab.md +159 -0
- package/claude/skills/sd-debug/references/repro-minimize.md +107 -0
- package/claude/skills/sd-debug/references/verification-tools.md +204 -0
- package/claude/skills/sd-dev/SKILL.md +18 -73
- package/claude/skills/sd-plan/SKILL.md +156 -40
- package/claude/skills/sd-prompt/SKILL.md +68 -25
- package/claude/skills/sd-prompt/references/eval-runner.md +2 -2
- package/claude/skills/sd-refactor/SKILL.md +2 -2
- package/claude/skills/sd-review/SKILL.md +201 -25
- package/claude/skills/sd-review/merge-source.py +66 -0
- package/claude/skills/sd-tdd/SKILL.md +3 -4
- package/claude/skills/sd-use/SKILL.md +5 -8
- package/claude/skills/sd-wbs/SKILL.md +163 -31
- package/package.json +1 -1
- package/claude/skills/sd-claude-docs/merge-source.sh +0 -23
- package/claude/skills/sd-dev/subagent-preamble.md +0 -22
- package/claude/skills/sd-inner-clarify/SKILL.md +0 -78
- package/claude/skills/sd-inner-debug/SKILL.md +0 -145
- package/claude/skills/sd-inner-review/SKILL.md +0 -173
- package/claude/skills/sd-inner-review/merge-source.sh +0 -41
|
@@ -182,7 +182,7 @@ viewType에 따라 렌더링 위치가 달라진다:
|
|
|
182
182
|
| `item` | `TItem` | 현재 행 항목 (명시적 이름) |
|
|
183
183
|
| `index` | `number` | 행 인덱스 |
|
|
184
184
|
| `depth` | `number` | 트리 데이터의 중첩 깊이 |
|
|
185
|
-
| `edit` | `boolean` | 현재 행이 편집 모드인지 여부. 행 클릭(또는 더블클릭) 시 `true`가 된다. `SdTextfield`의 `[readonly]`에 `!edit`을 바인딩하여 인라인 편집을 구현한다. |
|
|
185
|
+
| `edit` | `boolean` | 현재 행이 편집 모드인지 여부. 행 클릭(또는 더블클릭) 시 `true`가 된다. `SdTextfield`의 `[readonly]`에 `!edit`을 바인딩하여 인라인 편집을 구현한다. **`SdSelect`/`SdSharedDataSelect`/`SdCheckbox`/`SdButton`류는 `readonly` 입력 자체가 없으며 클릭 한 번에 즉시 동작하므로 `let-edit`을 받지 않고 `[disabled]="!canEdit()"`만 사용한다 (자세한 내용은 [`sd-sheet.md`](./sd-sheet.md)의 "컨트롤별 `edit` 모드 처리" 표 참조).** |
|
|
186
186
|
|
|
187
187
|
```html
|
|
188
188
|
<!-- 읽기 전용 셀 -->
|
|
@@ -592,6 +592,88 @@ export class CustomerList implements SdSelectModal<number> {
|
|
|
592
592
|
</sd-crud-list>
|
|
593
593
|
```
|
|
594
594
|
|
|
595
|
+
## Usage: 외부 input(초기 필터)을 받는 모달
|
|
596
|
+
|
|
597
|
+
`SdSelectModal`로도 사용되면서 동시에 페이지 라우팅으로도 진입 가능한 컴포넌트는, 호출자가 `inputs`로 강제 주입하는 초기 필터(`includeCustomerIds`, `includeGoodsIds`, `excludeIds` 등)와 사용자가 화면에서 변경하는 `filter`/`lastFilter`가 같은 키를 공유한다. 이때 effect를 **두 개로 분리**해야 한다.
|
|
598
|
+
|
|
599
|
+
### ✅ 권장: input 동기화와 검색 트리거를 분리
|
|
600
|
+
|
|
601
|
+
```typescript
|
|
602
|
+
constructor() {
|
|
603
|
+
// effect 1: 외부 input → filter/lastFilter 단방향 동기화 (input 변경 시만 트리거)
|
|
604
|
+
effect(() => {
|
|
605
|
+
const cIds = this.includeCustomerIds() ?? [];
|
|
606
|
+
const gIds = this.includeGoodsIds() ?? [];
|
|
607
|
+
const xIds = this.excludeIds() ?? [];
|
|
608
|
+
|
|
609
|
+
untracked(() => {
|
|
610
|
+
this.filter.update((f) => ({
|
|
611
|
+
...f,
|
|
612
|
+
includeCustomerIds: cIds,
|
|
613
|
+
includeGoodsIds: gIds,
|
|
614
|
+
excludeIds: xIds,
|
|
615
|
+
}));
|
|
616
|
+
this.lastFilter.set({ ...this.filter() });
|
|
617
|
+
});
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
// effect 2: lastFilter/page/sortingDefs → 검색 (사용자 onFilterSubmit/페이지 이동/정렬 시 트리거)
|
|
621
|
+
effect(() => {
|
|
622
|
+
if (!this.perms().includes("use") || !this.ready()) {
|
|
623
|
+
this.initialized.set(true);
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
this.lastFilter();
|
|
628
|
+
this.page();
|
|
629
|
+
this.sortingDefs();
|
|
630
|
+
|
|
631
|
+
void untracked(async () => {
|
|
632
|
+
this.busyCount.update((v) => v + 1);
|
|
633
|
+
await this._sdToast.try(async () => {
|
|
634
|
+
await this._refresh();
|
|
635
|
+
});
|
|
636
|
+
this.busyCount.update((v) => v - 1);
|
|
637
|
+
this.initialized.set(true);
|
|
638
|
+
});
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
- effect 1은 **input signal에만 의존**. 페이지 모드(input 미전달)에서는 init 1회만 실행되고 이후 트리거되지 않으므로, 사용자가 화면에서 바꾼 `filter`/`lastFilter`를 덮어쓰지 않는다.
|
|
644
|
+
- effect 2는 **lastFilter/page/sortingDefs에만 의존**. `onFilterSubmit()`이 `lastFilter.set` 하면 검색이 자동 실행된다.
|
|
645
|
+
- 모달 모드에서 호출자가 inputs를 한 번만 전달하므로, 모달이 열린 동안 effect 1이 재트리거되지 않아 모달 내 사용자 변경도 보존된다.
|
|
646
|
+
|
|
647
|
+
### ❌ 안티패턴: 한 effect에서 input vs lastFilter 비교 후 reset
|
|
648
|
+
|
|
649
|
+
```typescript
|
|
650
|
+
constructor() {
|
|
651
|
+
effect(() => {
|
|
652
|
+
if (!this.perms().includes("use") || !this.ready()) { /* ... */ return; }
|
|
653
|
+
|
|
654
|
+
const cIds = this.includeCustomerIds() ?? []; // 페이지 모드: 항상 []
|
|
655
|
+
const lf = this.lastFilter(); // 사용자 검색 직후: [123]
|
|
656
|
+
if (!obj.equal(cIds, lf.includeCustomerIds)) { // ❌ input과 lastFilter 비교
|
|
657
|
+
untracked(() => {
|
|
658
|
+
this.filter.update((f) => ({ ...f, includeCustomerIds: cIds }));
|
|
659
|
+
this.lastFilter.set({ ...this.filter() }); // ❌ 사용자 변경을 [] 로 덮어씀
|
|
660
|
+
this.page.set(0);
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
this.lastFilter();
|
|
665
|
+
this.page();
|
|
666
|
+
this.sortingDefs();
|
|
667
|
+
|
|
668
|
+
void untracked(async () => { await this._refresh(); });
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
- 사용자가 화면에서 필터를 변경하고 `onFilterSubmit()` 호출 → `lastFilter.set([123])` → 이 effect 재실행 → `cIds=[]`와 `lastFilter=[123]`이 다르다고 판단 → `filter`/`lastFilter`를 `[]`로 reset → `_refresh()`는 빈 필터로 검색.
|
|
674
|
+
- 결과: 페이지 모드에서 필터가 항상 빈 배열로 동작하는 것처럼 보임 (필터 미적용).
|
|
675
|
+
- 외부 input은 "외부에서 명령적 reset"의 트리거여야 하며, 사용자 변경(`lastFilter`)과 동등 비교의 기준이 되어선 안 된다.
|
|
676
|
+
|
|
595
677
|
## Anti-patterns
|
|
596
678
|
|
|
597
679
|
```html
|
|
@@ -620,4 +702,20 @@ export class CustomerList implements SdSelectModal<number> {
|
|
|
620
702
|
<!-- ❌ cell 템플릿에서 items 시그널 호출을 빠뜨리지 않는다 -->
|
|
621
703
|
<ng-template [cell]="[]" let-item="item"> <!-- ❌ 타입 추론 불가 -->
|
|
622
704
|
<ng-template [cell]="items()" let-item="item"> <!-- ✅ -->
|
|
705
|
+
|
|
706
|
+
<!-- ❌ select류 컨트롤에 [readonly]="!edit"을 바인딩하지 않는다 -->
|
|
707
|
+
<sd-select [readonly]="!edit" ...>
|
|
708
|
+
<!-- → typecheck 에러: Can't bind to 'readOnly' since it isn't a known property of 'sd-select' -->
|
|
709
|
+
|
|
710
|
+
<!-- ❌ 위 에러를 회피하려고 disabled에 !edit을 합치지 않는다 -->
|
|
711
|
+
<!-- (select는 즉시 변경 컨트롤이라 edit 모드 분기가 의미 없고, -->
|
|
712
|
+
<!-- 값 표시 행에서도 disabled로 회색 처리되어 권한 없음 시각과 혼동됨) -->
|
|
713
|
+
<ng-template [cell]="items()" let-item="item" let-edit="edit">
|
|
714
|
+
<sd-select [disabled]="!canEdit() || !edit" ...>
|
|
715
|
+
</ng-template>
|
|
716
|
+
|
|
717
|
+
<!-- ✅ select류는 edit 모드 분기 없음. let-edit 안 받고 disabled는 권한만 -->
|
|
718
|
+
<ng-template [cell]="items()" let-item="item">
|
|
719
|
+
<sd-select [disabled]="!canEdit()" ...> <!-- ✅ -->
|
|
720
|
+
</ng-template>
|
|
623
721
|
```
|
|
@@ -111,6 +111,33 @@ class SdSheetColumnCellTemplate<T> {
|
|
|
111
111
|
- **일반 텍스트**: `<div class="p-xs-sm">` 로 감싸 기본 패딩 적용
|
|
112
112
|
- **컨트롤 삽입**: 반드시 `[inset]="true"` + `[size]="'sm'"` 지정
|
|
113
113
|
|
|
114
|
+
**컨트롤별 `edit` 모드 처리** — `SdSheetCellContext.edit`은 셀이 편집 진입 모드인지 여부(행 클릭/더블클릭으로 활성)다. 컨트롤 종류에 따라 처리가 다르다:
|
|
115
|
+
|
|
116
|
+
| 컨트롤 | `[disabled]` | `[readonly]` | `let-edit="edit"` |
|
|
117
|
+
|--------|-------------|-------------|---------------------|
|
|
118
|
+
| `SdTextfield` (text/number/date 등) | `!canEdit()` | `!edit` | 받음 |
|
|
119
|
+
| `SdSelect` / `SdSharedDataSelect` | `!canEdit()` | (사용 안 함) | **받지 않음** |
|
|
120
|
+
| `SdCheckbox` | `!canEdit()` | (사용 안 함) | 받지 않음 |
|
|
121
|
+
| `SdButton` | `!canEdit()` | (사용 안 함) | 받지 않음 |
|
|
122
|
+
|
|
123
|
+
`readonly`는 "값은 보이되 편집 진입을 막는다", `disabled`는 "회색 + 비활성"이라 의미·시각이 다르다. textfield 류는 둘을 분리해 인라인 편집(읽기 모드 → 클릭 → 편집 모드) UX를 구현한다.
|
|
124
|
+
|
|
125
|
+
select·체크박스·버튼류는 클릭 한 번으로 즉시 동작하는 컨트롤이라 `edit` 모드 분기 자체가 의미 없다. `let-edit="edit"`을 받지 않고 `[disabled]`는 권한(`!canEdit()`)만 반영한다.
|
|
126
|
+
|
|
127
|
+
```html
|
|
128
|
+
<!-- ❌ select류 컨트롤에서 disabled에 !edit을 합치지 않는다 -->
|
|
129
|
+
<ng-template [cell]="items()" let-item="item" let-edit="edit">
|
|
130
|
+
<sd-select [disabled]="!canEdit() || !edit" ...>
|
|
131
|
+
</ng-template>
|
|
132
|
+
|
|
133
|
+
<!-- ✅ select는 edit 모드 분기 없음. let-edit 안 받고 disabled는 권한만 -->
|
|
134
|
+
<ng-template [cell]="items()" let-item="item">
|
|
135
|
+
<sd-select [disabled]="!canEdit()" ...>
|
|
136
|
+
</ng-template>
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
> **주의**: `SdSelect`/`SdSharedDataSelect`/`SdCheckbox`/`SdButton`은 `readonly` 입력을 **제공하지 않는다**. `[readonly]="!edit"`을 바인딩하면 typecheck 에러(`Can't bind to 'readOnly' since it isn't a known property of 'sd-...'`)가 발생한다. textfield 패턴(`disabled`/`readonly` 분리)을 select류에 그대로 적용하지 말 것.
|
|
140
|
+
|
|
114
141
|
### `SdSheetCellContext`
|
|
115
142
|
|
|
116
143
|
```typescript
|
|
@@ -45,6 +45,26 @@ class SdSelect<T, M extends keyof SelectModeValue<T>> {
|
|
|
45
45
|
|
|
46
46
|
**스타일 적용**: `contentClass`/`contentStyle`은 트리거 영역(선택값 텍스트와 드롭다운 화살표가 함께 놓인 박스)에만 적용된다.
|
|
47
47
|
|
|
48
|
+
## 빈 값(`undefined`) 항목 표시 권장 패턴
|
|
49
|
+
|
|
50
|
+
`SdSelect`에서 `[value]="undefined"` 항목은 일반 항목과 시각적으로 구분되도록 라벨을 회색으로 처리한다. 사용자가 "값 없음"을 즉시 인지하고 의미 있는 값과 혼동하지 않도록 한다.
|
|
51
|
+
|
|
52
|
+
```html
|
|
53
|
+
<sd-select [(value)]="item.weekOffset" (valueChange)="mark(items)">
|
|
54
|
+
<sd-select-item [value]="undefined">
|
|
55
|
+
<span class="tx-theme-gray-default">미지정</span>
|
|
56
|
+
</sd-select-item>
|
|
57
|
+
<sd-select-item [value]="0">+0주</sd-select-item>
|
|
58
|
+
<sd-select-item [value]="1">+1주</sd-select-item>
|
|
59
|
+
<sd-select-item [value]="2">+2주</sd-select-item>
|
|
60
|
+
</sd-select>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- `tx-theme-gray-default`은 `@simplysm/angular`의 회색 텍스트 토큰이다.
|
|
64
|
+
- 본 패턴은 **single 모드 한정**이다 — 필터의 "전체"(모든 옵션 포함), nullable 컬럼의 "미지정" 등 single 모드의 빈 값 라벨에 적용한다.
|
|
65
|
+
- multi 모드는 `hideSelectAll` 옵션으로 "전체 선택"이 자체 제공되므로 별도 `[value]="undefined"` 항목을 두지 않는다.
|
|
66
|
+
- `placeholder` 만으로는 사용자가 한 번 값을 선택한 뒤 빈 값으로 복귀할 수 없으므로, `[value]="undefined"` 항목을 명시하고 라벨에 회색을 적용하는 것이 권장 패턴이다.
|
|
67
|
+
|
|
48
68
|
## Related Types
|
|
49
69
|
|
|
50
70
|
### `SdSelectItem`
|
|
@@ -36,19 +36,17 @@ claude/
|
|
|
36
36
|
| `sd-check/` | sd-check | typecheck/lint/test 실행 및 에러 해결 |
|
|
37
37
|
| `sd-claude-docs/` | sd-claude-docs | CLAUDE.md + usage 문서 동시 생성 |
|
|
38
38
|
| `sd-commit/` | sd-commit | 전체 변경사항에 대한 단일 커밋 생성 |
|
|
39
|
-
| `sd-debug/` | sd-debug | 버그 근본 원인 분석 및
|
|
39
|
+
| `sd-debug/` | sd-debug | 버그 근본 원인 분석(ACH) 및 보고 |
|
|
40
40
|
| `sd-deliverable/` | sd-deliverable | 매뉴얼/SIT 문서 생성 |
|
|
41
41
|
| `sd-dev/` | sd-dev | 통합 개발 오케스트레이터 (요구명세 → TDD → 리뷰) |
|
|
42
42
|
| `sd-doc-extract/` | sd-doc-extract | 문서 파일 텍스트/이미지 추출 (Python) |
|
|
43
|
-
| `sd-
|
|
44
|
-
| `sd-inner-debug/` | sd-inner-debug | (내부 전용) 근본 원인 분석(ACH) 로직 |
|
|
45
|
-
| `sd-inner-review/` | sd-inner-review | (내부 전용) 코드 리뷰 분석 로직 |
|
|
43
|
+
| `sd-clarify/` | sd-clarify | (내부 전용) 명확성 분류·근거 탐색·명확화 질문 |
|
|
46
44
|
| `sd-issue/` | sd-issue | GitHub 이슈 생성 |
|
|
47
45
|
| `sd-outlook/` | sd-outlook | Outlook 메일 검색/다운로드 (Python) |
|
|
48
46
|
| `sd-plan/` | sd-plan | 요구명세/구현계획 작성 |
|
|
49
47
|
| `sd-prompt/` | sd-prompt | 스킬/프롬프트 파일 작성/개선 |
|
|
50
48
|
| `sd-refactor/` | sd-refactor | 리팩토링 분석 리포트 생성 |
|
|
51
|
-
| `sd-review/` | sd-review | 코드 리뷰
|
|
49
|
+
| `sd-review/` | sd-review | 코드 리뷰 및 수정 개발 연결 |
|
|
52
50
|
| `sd-tdd/` | sd-tdd | TDD 개발 |
|
|
53
51
|
| `sd-use/` | sd-use | 자연어 → sd-\* 스킬 라우팅 |
|
|
54
52
|
| `sd-wbs/` | sd-wbs | WBS Feature 분해 |
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
# 대화 규칙
|
|
10
10
|
|
|
11
|
-
-
|
|
11
|
+
- 모든 요청에 대해 항상 깊이 생각 할 것.
|
|
12
12
|
- 내장 도구 적극 활용 (Read/Grep/Glob/Bash/WebFetch/WebSearch/Skill/TaskCreate 등)
|
|
13
|
-
- 사용자 요청의 의도가 불명확할 때는 `/sd-
|
|
13
|
+
- 사용자 요청의 의도가 불명확할 때는 `/sd-clarify` 스킬을 호출하여 명확화.
|
|
14
14
|
- 맥락에 맞는 용어 사용
|
|
15
15
|
- 업무 기능·요구사항 논의 → 업무 용어 (사용자가 화면에서 뭘 하는지)
|
|
16
16
|
- DB 스키마 설계 → 테이블·컬럼명
|
|
@@ -21,6 +21,35 @@
|
|
|
21
21
|
- 명시적 요청없이 코드/문서등을 바로 수정하지 말것
|
|
22
22
|
- 사용자가 직접 확인해야할 사항이 있으면, 계속 진행하지 말고 멈추고 사용자에게 직접 확인 결과를 요청할 것.
|
|
23
23
|
|
|
24
|
+
# 질문 vs 수정 분리
|
|
25
|
+
|
|
26
|
+
- 질문형 요청("이게 왜 이래?", "어떻게 동작해?", "맞아?")은 분석·설명으로 처리한다. 사용자가 명시적으로 "수정해줘", "고쳐줘", "바꿔줘"라고 요청하지 않으면 코드/문서 수정으로 전환하지 않는다.
|
|
27
|
+
- "A를 B로 바꿔" 같은 명시적 변경 지시가 있을 때만 즉시 수정한다.
|
|
28
|
+
- 해결 방식이 열린 요청(예: "이거 어떻게 해결하지?", "리팩토링 방안 좀")은 수정 대상·방향·검증 계획을 먼저 설명하고 사용자 승인을 받은 뒤 수정한다.
|
|
29
|
+
|
|
30
|
+
# 사용자 편의성 우선
|
|
31
|
+
|
|
32
|
+
**CRITICAL: 구현 복잡도·코드 양·리팩토링 부담보다 사용자 편의성을 우선한다.**
|
|
33
|
+
|
|
34
|
+
- 구현 복잡도와 사용자 편의성이 충돌하면 편의성을 택한다.
|
|
35
|
+
- 복잡도가 크게 증가해도 편의성 이득이 분명하면 채택한다.
|
|
36
|
+
- '구현이 어렵다'는 이유로 편의성 다운그레이드 금지.
|
|
37
|
+
- 선택지 평가 시 '사용자 편의성' 축을 반드시 포함하고 가중치를 둔다.
|
|
38
|
+
|
|
39
|
+
# 사용성 보존
|
|
40
|
+
|
|
41
|
+
**CRITICAL: 버그 수정·규칙 준수·타입/lint 오류 해결 작업은 사용성 변경 요청이 아니다.**
|
|
42
|
+
|
|
43
|
+
- 사용자 흐름, 화면 동작, 문구, 기본값, 옵션 의미, 공개 API 동작은 보존한다.
|
|
44
|
+
- 작업 중 사용성 문제를 발견해도 같이 고치지 말고, 별도 이슈로 보고만 한다.
|
|
45
|
+
- 사용성 변경이 불가피하면 변경되는 사용성, 대안, 영향을 사전 설명하고 사용자 응답을 대기한다.
|
|
46
|
+
|
|
47
|
+
# 구현 방식 결정 분리
|
|
48
|
+
|
|
49
|
+
- 사용자가 목표·방향·통합 여부를 확정해도 구현 방식은 별도 결정사항이다.
|
|
50
|
+
- 구현 방식 후보가 2개 이상이거나 새 개념(내부 모드/플래그/래퍼/호환 계층/파일 삭제·이동/호출 흐름 변경) 도입이 필요하면 `.claude/rules/sd-options.md`의 형식으로 선택지를 제시하고 응답을 대기한다.
|
|
51
|
+
- 회피용 우회 구조(재귀, 순환 의존, 호환성 문제 등)가 발견되면 먼저 사용자에게 보고하고, 그 다음 sd-options 형식으로 질문한다.
|
|
52
|
+
|
|
24
53
|
# Playwright
|
|
25
54
|
|
|
26
55
|
- 사용자가 접속주소를 알려주지 않았다면, 반드시 사용자에게 접속주소를 요청할것. (서버 강제 실행 금지)
|
|
@@ -6,36 +6,25 @@
|
|
|
6
6
|
|
|
7
7
|
- "이 정도 질문은 과하다", "단순 확인이니 생략"은 위반이다
|
|
8
8
|
- 단일 경로만 합리적이라 느껴질 때도, "수행 안 함"을 포함한 선택지 구조로 제시한다
|
|
9
|
-
- 가벼운 사안은 경량 모드로 오버헤드를 낮추되, 선택지 구조와 `AskUserQuestion` 호출은 생략 불가
|
|
10
9
|
|
|
11
10
|
## 공통 규칙
|
|
12
11
|
|
|
13
|
-
-
|
|
12
|
+
- 질문 대기열 우선: 사용자 답변이 필요한 항목이 있으면 질문 대기열에 등록한다. 사용자 답변으로 새 질문이 생기면 후속 프로세스를 시작하지 말고 질문 대기열에 추가한다.
|
|
13
|
+
- 결정 대상 명시: 각 선택지 묶음 전에 `결정 대상 {번호}/{전체}: {파일경로:라인}` 출력. 단일 결정사항이면 `결정 대상: {파일경로:라인}` 출력.
|
|
14
14
|
- 하나의 선택지를 추천하고 사유 한 줄 요약
|
|
15
|
-
- 복수
|
|
15
|
+
- 복수 질문: 질문은 한 번에 하나씩 제시한다. 각 질문마다 사용자 답변을 받은 뒤 다음 질문을 제시한다.
|
|
16
|
+
- 답변 누적: 앞선 질문의 답변은 저장된 결정으로 취급한다. 다음 질문을 하거나 전체 답변 수집을 완료하기 전까지, 앞선 답변에 따른 수정·실행·해결 프로세스를 시작하지 않는다.
|
|
17
|
+
- 실행 시작 조건: 질문 대기열이 비고 모든 필수 질문의 답변을 받은 뒤에만 수정·실행·검증 등 후속 프로세스를 시작한다.
|
|
18
|
+
- 누락 답변 처리: 사용자가 현재 질문에 답하지 않으면 같은 질문을 다시 묻는다. 누락 항목을 임의 추천안으로 처리하지 않는다.
|
|
19
|
+
- 추가 질문 처리: 답변 수집 중 또는 작업 중 새로 물어봐야 할 항목이 발견되면 질문 대기열에 추가하고, 다시 한 번에 하나씩 질문한다.
|
|
20
|
+
- 질문 정렬: 발견된 질문은 발생 출처(Step/Feature 번호/대상 식별자) 단위로 묶음 분류한다. 한 묶음을 모두 소진한 뒤 다음 묶음으로 넘어가며, 진행 중 묶음 내에서 발견된 새 질문은 해당 묶음 끝에 추가한다. 묶음 간 순서는 의존성·상위→하위 순으로 한다.
|
|
16
21
|
- 도구 호출 의무: 선택지 출력 후 즉시 `AskUserQuestion` tool을 호출하여 응답을 종료한다. 텍스트로 "진행할까요?" 묻고 응답 대기하면 위반.
|
|
17
22
|
- `AskUserQuestion`이 deferred tool로 표시되어 있으면 먼저 `ToolSearch query="select:AskUserQuestion"`로 스키마를 로드한 뒤 호출한다.
|
|
23
|
+
- `AskUserQuestion`의 선택지(`options`)는 평균 점수 내림차순으로 정렬하여 전달한다. 동점이면 추천안을 우선 배치한다.
|
|
18
24
|
|
|
19
|
-
##
|
|
20
|
-
|
|
21
|
-
사안의 무게에 따라 경량 모드와 전체 모드 중 하나를 선택한다.
|
|
22
|
-
|
|
23
|
-
### 경량 모드 — 적용 대상 중 가벼운 결정
|
|
24
|
-
|
|
25
|
-
조건: 영향 범위가 단일 파일·수 줄 이내이고, 각 선택지의 차이가 한눈에 명확할 때.
|
|
25
|
+
## 선택지 제시 형식
|
|
26
26
|
|
|
27
27
|
필수 항목:
|
|
28
|
-
- 결정 대상 한 줄
|
|
29
|
-
- 2~4개 선택지 + "수행 안 함"
|
|
30
|
-
- 각 선택지: 한 줄 요약 + 한 줄 트레이드오프 + 10점 만점 단일 점수
|
|
31
|
-
- 추천 한 줄
|
|
32
|
-
- `AskUserQuestion` 호출
|
|
33
|
-
|
|
34
|
-
### 전체 모드 — 적용 대상 중 무거운 결정
|
|
35
|
-
|
|
36
|
-
조건: 설계·아키텍처·공개 API·규칙/설정 파일·복수 파일 영향·되돌리기 어려운 변경.
|
|
37
|
-
|
|
38
|
-
필수 항목 (공통 규칙 + 아래):
|
|
39
28
|
|
|
40
29
|
- 근거 제시
|
|
41
30
|
- 현재 상태 인용: 파일경로:라인번호 필수. 코드블록 사용 시에도 경로:라인 병기
|
|
@@ -46,4 +35,12 @@
|
|
|
46
35
|
- 축별 점수
|
|
47
36
|
- 맥락에 맞는 관점(축) 3개 이상 선정
|
|
48
37
|
- 축별 점수를 반드시 노출한 뒤 평균을 10점 만점으로 병기 (최종 점수만 쓰는 것 금지)
|
|
49
|
-
|
|
38
|
+
- 표기 형식: 단일 매트릭스 표 1개로 표시한다. 행 = 선택지(평균 내림차순), 열 = 평가축 + 평균. 선택지마다 별도 표 작성 금지.
|
|
39
|
+
- 예시:
|
|
40
|
+
```
|
|
41
|
+
| 선택지 | 일관성 | 단순성 | 워크플로 보존 | 평균 |
|
|
42
|
+
|---|---|---|---|---|
|
|
43
|
+
| A. xxx | 10 | 10 | 7 | **9.0** |
|
|
44
|
+
| B. yyy | 6 | 7 | 9 | **7.3** |
|
|
45
|
+
| C. 수행 안 함 | 2 | 10 | 5 | **5.7** |
|
|
46
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# 사용자 응답 형식 (Claude Code 채팅 출력 전용)
|
|
2
|
+
|
|
3
|
+
적용 범위: 사용자에게 출력되는 채팅 응답에만 적용한다.
|
|
4
|
+
파일 작성(.md/.ts/.json/매뉴얼/README/SIT/Spec/Plan 등 모든 산출물)에는 적용하지 않는다.
|
|
5
|
+
파일 작성 시에는 해당 파일이 렌더링될 환경(GitHub/Web/Word 등)의 일반 마크다운 관례를 따른다.
|
|
6
|
+
|
|
7
|
+
## 구조
|
|
8
|
+
|
|
9
|
+
- 결론 우선: 답변 첫 줄에 결론을 둔다. 근거·세부는 그 아래에 배치.
|
|
10
|
+
- 헤더로 분리: 응답이 3개 이상 논점/단계로 구성되면 `##`/`###` 헤더로 섹션을 나눈다. 짧은 답변(1~2단락)에는 헤더 금지. 헤더는 색상 강조보다 "섹션 분리" 용도다.
|
|
11
|
+
- 가로선 분리: 큰 논리 블록(예: 결론 → 분석 → 변경안 → 결정 요청) 사이에 유니코드 가로선 `────────────────────────────────────────` (U+2500 반복, 40자 권장)을 삽입. markdown `---` HR은 Claude Code 터미널에서 가로선으로 렌더링되지 않으므로 사용 금지.
|
|
12
|
+
- 불릿 우선: 항목이 2개 이상이거나 병렬 구조면 산문 대신 불릿 리스트 사용. 3줄 이상 텍스트가 이어지면 빈 줄 또는 리스트로 끊는다.
|
|
13
|
+
- 표 활용: 대비·비교·다축 평가는 표(table)로 정돈. 정렬·가시성 우수.
|
|
14
|
+
- 코드블록 활용: 명령어 1줄 이상, 코드 인용, 파일 내용 발췌, 변경 전후 본문은 fenced code block으로 분리.
|
|
15
|
+
- 꼬리 요약: 응답이 30줄 이상이면 마지막에 가로선 분리 후 `## 요약` 헤더 + 핵심 불릿 3~5개를 출력한다. 30줄 미만이면 출력 금지.
|
|
16
|
+
|
|
17
|
+
## 색상 활용 (Claude Code 터미널 기준)
|
|
18
|
+
|
|
19
|
+
- 직접 색 지정은 불가능하다. 자동으로 색이 입혀지는 markdown 요소를 의도적으로 사용한다.
|
|
20
|
+
- 강조 위계는 GUI 마크다운과 다르다: 인라인 코드(녹색, 강함) > 헤더(굵음만, 약함) > `**bold**`(효과 0).
|
|
21
|
+
- 키워드 강조는 인라인 코드(`\``)를 사용. 사용자 환경에서 유일한 강한 색상 강조 수단.
|
|
22
|
+
- 정/부 대비, 변경 전후, 권장/금지 대비는 ` ```diff ` 블록으로 표현 (`+` 녹색, `-` 빨강). `!`는 강조 효과가 약하므로 사용 자제.
|
|
23
|
+
- 인용·주의·권고는 blockquote(`>`)로 분리 (세로선 + 이탤릭체로 시각 구분).
|
|
24
|
+
|
|
25
|
+
## 인라인 표기
|
|
26
|
+
|
|
27
|
+
- 백틱 표기: 파일경로·명령어·심볼·식별자·기호는 인라인 코드(`\``)로 감싼다. 파일 위치는 `path/file.ts:42` 형식.
|
|
28
|
+
- 표기 통일: 같은 키워드를 따옴표("...")와 백틱(`...`)으로 이중 표기 금지. 한 가지 표기로만 사용.
|
|
29
|
+
- `**bold**` 사용 금지: 색상 효과 0이고 한글 모노스페이스에선 굵기 차이도 인지 어렵다. 결정적 키워드 강조는 인라인 코드로 처리.
|
|
30
|
+
- 이모지 금지: 사용자가 명시 요청한 경우만 사용.
|
|
31
|
+
|
|
32
|
+
## 어조
|
|
33
|
+
|
|
34
|
+
- 한 문장 한 정보: 한 문장에 여러 정보를 담지 않는다. 부연은 다음 문장으로 분리.
|
|
35
|
+
- 사족 금지: "좋은 질문입니다", "알겠습니다", "~할 수도 있을 것 같습니다" 같은 완충/사과/감탄 표현 제거. 단정적 어조 사용.
|
|
36
|
+
- 응답 길이 매칭: 단순 확인 질문엔 1~3줄, 분석/설계 질문엔 필요한 만큼. 짧은 답에 헤더·가로선·표를 억지로 넣지 않는다.
|
|
@@ -9,7 +9,7 @@ description: typecheck, lint, test를 실행하고 에러 발생시 사용자
|
|
|
9
9
|
|
|
10
10
|
### 에러 분석 및 수정
|
|
11
11
|
|
|
12
|
-
에러 분석: `/sd-
|
|
12
|
+
에러 분석: `/sd-debug`의 ACH 분석 규칙을 적용한다. 아래 에러 처리 범위와 에스컬레이션 규칙을 우선한다.
|
|
13
13
|
|
|
14
14
|
#### 에러 처리 범위
|
|
15
15
|
|
|
@@ -27,7 +27,7 @@ description: typecheck, lint, test를 실행하고 에러 발생시 사용자
|
|
|
27
27
|
**CRITICAL: 아래 2가지 경우에만 사용자에게 보고/선택지 제시한다. 그 외 사유로는 절대(NEVER) 보고·질문·선택지 제시 금지.**
|
|
28
28
|
|
|
29
29
|
화이트리스트 (이 2가지가 전부):
|
|
30
|
-
1. **동일/유사 에러 2회 반복**: 1회차에 `/sd-
|
|
30
|
+
1. **동일/유사 에러 2회 반복**: 1회차에 `/sd-debug`의 ACH 분석 규칙으로 근본 원인 분석 및 수정 시도 → 2회차 재발 시 중단하고 분석·시도 내역 보고.
|
|
31
31
|
2. **원인 특정 불가**: 추측으로 수정 시도 금지, 즉시 보고.
|
|
32
32
|
|
|
33
33
|
**금지 사항 (자주하는 환각)**:
|
|
@@ -104,7 +104,34 @@ typecheck 명령어를 실행한다. (`출력 캡처 규칙`에 따라 파일로
|
|
|
104
104
|
테스트 명령어를 실행한다. (`출력 캡처 규칙`에 따라 파일로 리다이렉트)
|
|
105
105
|
|
|
106
106
|
- 에러 발생 시: `에러 분석 및 수정`에 따라, 테스트 실패의 원인을 분석하고 코드를 수정한다.
|
|
107
|
-
|
|
107
|
+
|
|
108
|
+
### 코드 수정 후 테스트 실패 처리
|
|
109
|
+
|
|
110
|
+
**CRITICAL: 이 대화세션에서 코드 수정이 있었고 이후 테스트가 실패하면, 실패 원인을 "코드 버그"로 단정하기 전에 반드시(MUST) 테스트 변경 누락 가능성을 먼저 검토한다.**
|
|
111
|
+
|
|
112
|
+
코드 수정 후 테스트 실패를 처리할 때는 아래 순서를 지킨다:
|
|
113
|
+
|
|
114
|
+
1. 현재 세션에서 수정한 코드 diff와 테스트 실패 내용을 대조한다.
|
|
115
|
+
2. 실패한 테스트, fixture, expected/golden 파일이 수정된 동작을 검증하는지 확인한다.
|
|
116
|
+
3. 관련 테스트 변경이 없거나 expected/golden만 낡아 보이면, 사용자 요청·현재 대화 history·현재 diff를 근거로 의도된 동작인지 판단한다.
|
|
117
|
+
4. 대화 history만으로 의도가 불명확하면 관련 파일의 git history를 확인한다.
|
|
118
|
+
5. 실패 원인을 아래 중 하나로 1차 분류한다:
|
|
119
|
+
- **구현 버그**: 코드가 사용자 요청 또는 기존 계약을 어긴 경우 코드 수정.
|
|
120
|
+
- **테스트 변경 누락**: 코드 동작이 사용자 요청에 맞고 테스트만 예전 동작을 기대하는 경우 테스트, fixture, expected/golden 수정.
|
|
121
|
+
- **테스트 데이터 갱신 누락**: snapshot/expected/golden 출력만 달라진 경우 변경 의도 확인 후 해당 테스트 데이터 수정.
|
|
122
|
+
- **무관한 기존 실패**: `에러 처리 범위`에 따라 조용히 스킵.
|
|
123
|
+
- **원인 특정 불가**: 에스컬레이션 규칙에 따라 즉시 보고.
|
|
124
|
+
6. 1차 분류 결과와 근거 전체를 `/sd-clarify`로 전달하여 분류와 처리 방향의 명확성을 판정한다. sd-check가 자체 판단으로 명확한 항목을 제외하고 보내지 않는다.
|
|
125
|
+
7. `/sd-clarify`가 분류와 처리 방향을 명확하다고 판정하면 즉시 처리한다:
|
|
126
|
+
- **구현 버그가 명확함**: 코드 수정.
|
|
127
|
+
- **테스트 변경 누락이 명확함**: 테스트, fixture, expected/golden 수정.
|
|
128
|
+
- **테스트 데이터 갱신 누락이 명확함**: snapshot/expected/golden 수정.
|
|
129
|
+
- **무관한 기존 실패가 명확함**: `에러 처리 범위`에 따라 조용히 스킵.
|
|
130
|
+
8. `/sd-clarify`가 1%라도 불확실하다고 판정하면 처리하지 않는다. 사용자에게 분류 근거와 처리 방향을 확인받고 승인된 처리만 실행한다.
|
|
131
|
+
|
|
132
|
+
**NEVER: 테스트를 통과시키기 위해 현재 세션의 의도된 코드 변경을 예전 동작으로 되돌리지 않는다.** 코드 롤백성 수정은 실패 원인이 구현 버그로 확정된 경우에만 허용한다. "테스트가 기존 값을 기대한다"는 사실만으로 구현 버그를 확정할 수 없다.
|
|
133
|
+
|
|
134
|
+
**ALWAYS: 코드 수정으로 공개 동작, 렌더링 결과, SQL/DDL 출력, 직렬화 결과, 에러 메시지, fixture 구조가 바뀌었으면 관련 테스트와 expected/golden 파일 갱신 여부를 확인한다.** 테스트 변경 누락이 확인되면 코드가 아니라 테스트 산출물을 수정한다.
|
|
108
135
|
|
|
109
136
|
## Step 5: 반복 혹은 완료
|
|
110
137
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sd-clarify
|
|
3
|
+
description: 명확성 분류·근거 탐색·재분류·명확화 질문 프로세스. 타 스킬내에서 호출되거나, 사용자 요청이 불명확할때 사용된다.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# sd-clarify: 명확화 프로세스
|
|
7
|
+
|
|
8
|
+
정보의 명확성 판단 및 불명확한 정보를 명확화 하고자 할 때 적용한다.
|
|
9
|
+
파악한 정보를 확실성 수준별로 분류하고, 불명확한 항목은 사용자에게 질문하여 해소한다.
|
|
10
|
+
|
|
11
|
+
## Step 1: 명확성 분류 (1차)
|
|
12
|
+
|
|
13
|
+
정보의 명확성을 다음 기준으로 분류한다.
|
|
14
|
+
|
|
15
|
+
- **VERIFIED**: 사용자가 직접 말했거나 문서/코드에 명시된 것
|
|
16
|
+
- **INFERRED**
|
|
17
|
+
- **High**: 타겟 코드베이스에서 동일 패턴을 확인했거나 공식 문서에 근거가 있는 추론
|
|
18
|
+
- **Medium**: 일반적 도메인 관행이나 유사 사례에 기반한 추론. 마이그레이션 원본, 이전 버전, 외부 프로젝트의 패턴은 "유사 사례"에 해당
|
|
19
|
+
- **Low**: 약한 유추나 제한적 근거에 기반한 추론
|
|
20
|
+
- **ASSUMED**: 추측에 해당
|
|
21
|
+
|
|
22
|
+
## Step 2: 근거 탐색 (질문 전 필수)
|
|
23
|
+
|
|
24
|
+
**CRITICAL: Medium/Low/ASSUMED로 분류된 모든 항목은 사용자에게 질문하기 전에 반드시 근거를 한번 더 탐색한다.**
|
|
25
|
+
|
|
26
|
+
근거 출처는 항목의 성격에 따라 결정한다. 컨텍스트 회수와 타겟 탐색 중 어느 한쪽으로 미리 편향시키지 않는다.
|
|
27
|
+
|
|
28
|
+
### 2-1. 컨텍스트 회수
|
|
29
|
+
|
|
30
|
+
지금까지 누적된 맥락 전체에서 근거를 찾는다.
|
|
31
|
+
|
|
32
|
+
- **사용자 메시지** — 현재/이전 턴의 지시, 인용, 예시, 제약
|
|
33
|
+
- **호출자에게서 받은 인자** — 이 스킬을 부른 상위 스킬(sd-plan/sd-wbs 등)이 전달한 정보
|
|
34
|
+
- **이미 읽은 tool 결과** — 직전 Read/Grep/Glob/WebFetch 출력, 첨부된 문서 내용
|
|
35
|
+
- **세션 내 이미 생성된 산출물** — spec, plan, 직전 단계 보고 등
|
|
36
|
+
|
|
37
|
+
### 2-2. 타겟 탐색
|
|
38
|
+
|
|
39
|
+
항목의 성격에 맞는 소스를 확인한다. 컨텍스트 회수에서 결론이 보여도, 아래 강제 항목에 해당하면 반드시 탐색한다.
|
|
40
|
+
|
|
41
|
+
- **타겟 코드베이스** — Grep/Read/Glob으로 동일/유사 패턴. **다음 항목은 코드베이스 탐색 필수(컨텍스트 회수로 종결 금지):** UI 컴포넌트 구조·레이아웃·생김새, 메뉴/네비게이션 분할, 라우팅 구조, 도메인 엔터티 구조, 네이밍 컨벤션, 디렉토리 구조
|
|
42
|
+
- **참조 문서** — `.claude/references/**`, CLAUDE.md 등 프로젝트 문서
|
|
43
|
+
- **사용자가 제공한 원본 자료** — 첨부 문서·파일·경로를 끝까지 확인 (완독. 키워드 검색만으로 종결 금지)
|
|
44
|
+
- **공식 문서** — 외부 라이브러리/프레임워크의 공식 문서
|
|
45
|
+
|
|
46
|
+
### 실패 시그널 (Step 3 진입 전 자가 검증)
|
|
47
|
+
|
|
48
|
+
각 Medium/Low/ASSUMED 항목마다 다음 중 하나를 **한 줄로** 댈 수 있어야 한다.
|
|
49
|
+
|
|
50
|
+
- 찾음: `{파일/문서}:{라인/페이지/섹션}` + 인용·요약
|
|
51
|
+
- 못 찾음: 어디를 봤는지(회수한 맥락 + 탐색한 소스) 명시
|
|
52
|
+
|
|
53
|
+
"어차피 모를 것"이라는 판단으로 건너뛰는 것은 **금지(NEVER)**.
|
|
54
|
+
|
|
55
|
+
## Step 3: 재분류
|
|
56
|
+
|
|
57
|
+
탐색 결과를 바탕으로 각 항목을 재분류한다.
|
|
58
|
+
|
|
59
|
+
- 탐색으로 근거 확인됨 → **VERIFIED** 또는 **INFERRED High**로 승격 → 질문 제외
|
|
60
|
+
- 탐색했으나 근거 없음 → 기존 분류 유지 → 질문 대상
|
|
61
|
+
|
|
62
|
+
## Step 4: 재분류 보고 (필수)
|
|
63
|
+
|
|
64
|
+
최종 분류 결과를 **표 형태로 사용자에게 출력**한다.
|
|
65
|
+
|
|
66
|
+
### 표 출력
|
|
67
|
+
|
|
68
|
+
| 항목 | 1차 분류 | 탐색 위치 | 인용/요약 | 재분류 |
|
|
69
|
+
| ----------- | -------- | ------------------------- | --------------- | -------- |
|
|
70
|
+
| (정보 항목) | ASSUMED | 원본.docx p.3 / foo.ts:42 | "..." 또는 요약 | VERIFIED |
|
|
71
|
+
|
|
72
|
+
- **탐색 위치**는 파일경로:라인번호, 문서명:페이지/섹션, 메일 식별자, 회의록 발화자:시점 등 **구체 좌표**로 명시한다. "전체 검토", "문서 봄", "전반적으로 확인" 같은 추상 보고는 **금지(NEVER)**.
|
|
73
|
+
- **인용/요약**은 위 "인용 형식" 규칙을 따른다. 인용이 비어 있으면 해당 항목은 ASSUMED 유지(승격 금지).
|
|
74
|
+
- **근거 없음**으로 남기려면 (a) 어떤 키워드/구간을 봤는지, (b) 어떤 자료의 어떤 부분에서 부재를 확인했는지를 두 줄 이상 구체 명시한다. "탐색했으나 근거 없음" 한 줄로 종결하면 위반.
|
|
75
|
+
- 비정형 자료(메일, 회의 대본, 메시지 본문)가 호출자(sd-wbs 등)에서 보고되었는데 표에 해당 자료 인용이 1건도 없으면, 끝까지 읽지 않은 신호로 간주하여 Step 2로 되돌아간다.
|
|
76
|
+
- 보고 직후, 질문 대상이 남아 있으면 Step 5로 진행한다.
|
|
77
|
+
|
|
78
|
+
#### 인용 형식
|
|
79
|
+
|
|
80
|
+
표의 "인용/요약" 칼럼에 사용한다.
|
|
81
|
+
|
|
82
|
+
- **정형 문서**: `파일경로:라인` 또는 `문서명 p.N` / `섹션명`
|
|
83
|
+
- **비정형 자료**:
|
|
84
|
+
- 메일: `메일 [제목] / 발신자 / 일시 — "..."`
|
|
85
|
+
- 회의 대본: `회의록 [회의명] / 발화자 / 시점 또는 라인 — "..."`
|
|
86
|
+
- 메시지 본문: `사용자 메시지 ({n}번째 턴) — "..."`
|
|
87
|
+
- 인용은 1~2문장으로 의미가 드러나야 한다. 좌표만 적고 인용을 생략하는 것은 **금지**.
|
|
88
|
+
|
|
89
|
+
## Step 5: 명확화 질문
|
|
90
|
+
|
|
91
|
+
재분류 후에도 **INFERRED Medium/Low** 또는 **ASSUMED**로 남은 항목은 **MUST** 사용자에게 질문한다.
|
|
92
|
+
|
|
93
|
+
- 질문 방법: @.claude/rules/sd-options.md
|
|
94
|
+
- VERIFIED와 INFERRED High는 명확한 것으로 본다.
|