@conscience-technology/ctds 0.3.4 → 0.4.1

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.
Files changed (53) hide show
  1. package/assets/components/Button/Button.module.css +2 -2
  2. package/assets/components/EventListItem/EventListItem.module.css +220 -0
  3. package/assets/components/EventListItem/EventListItem.tsx +205 -0
  4. package/assets/components/EventListItem/index.ts +8 -0
  5. package/assets/components/Icon/Icon.tsx +80 -41
  6. package/assets/components/Kanban/Kanban.module.css +339 -0
  7. package/assets/components/Kanban/Kanban.tsx +371 -0
  8. package/assets/components/Kanban/index.ts +10 -0
  9. package/assets/components/ListItem/ListItem.module.css +91 -211
  10. package/assets/components/ListItem/ListItem.tsx +130 -154
  11. package/assets/components/ListItem/index.ts +2 -2
  12. package/assets/components/MetricCard/MetricCard.module.css +5 -5
  13. package/assets/components/PageHeader/PageHeader.module.css +109 -0
  14. package/assets/components/PageHeader/PageHeader.tsx +112 -0
  15. package/assets/components/PageHeader/index.ts +2 -0
  16. package/assets/components/Sidebar/Sidebar.module.css +81 -4
  17. package/assets/components/Sidebar/Sidebar.tsx +11 -2
  18. package/assets/components/SplitButton/SplitButton.module.css +3 -3
  19. package/assets/components/Stepper/Stepper.module.css +196 -52
  20. package/assets/components/Stepper/Stepper.tsx +68 -13
  21. package/assets/components/Switch/Switch.module.css +1 -9
  22. package/assets/components/Topbar/Topbar.module.css +33 -5
  23. package/assets/components/Topbar/Topbar.tsx +62 -7
  24. package/assets/components/_data.ts +11 -4
  25. package/assets/components/index.ts +2 -0
  26. package/assets/components/tokens.css +23 -10
  27. package/assets/prompts/ASSEMBLY.md +219 -0
  28. package/assets/prompts/PRINCIPLES.md +70 -0
  29. package/assets/prompts/axes/icon.md +7 -1
  30. package/assets/prompts/axes/palette.md +11 -0
  31. package/assets/prompts/components/_variants.md +5 -1
  32. package/assets/prompts/components/callout.md +3 -3
  33. package/assets/prompts/components/event-list-item.md +103 -0
  34. package/assets/prompts/components/generated-image.md +80 -0
  35. package/assets/prompts/components/hint.md +57 -0
  36. package/assets/prompts/components/kanban.md +167 -0
  37. package/assets/prompts/components/list-item.md +182 -204
  38. package/assets/prompts/components/metric-card.md +2 -2
  39. package/assets/prompts/components/page-header.md +155 -0
  40. package/assets/prompts/components/toast.md +1 -0
  41. package/assets/prompts/components/topbar.md +77 -59
  42. package/assets/prompts/recipes/README.md +102 -0
  43. package/assets/prompts/recipes/card-row.md +58 -0
  44. package/assets/prompts/recipes/form-footer.md +76 -0
  45. package/assets/prompts/recipes/meta-line.md +61 -0
  46. package/assets/prompts/recipes/page-banner.md +121 -0
  47. package/assets/prompts/recipes/page-header.md +93 -0
  48. package/assets/prompts/recipes/section-header.md +90 -0
  49. package/assets/prompts/themes/focus.md +72 -0
  50. package/assets/skills/ctds/SKILL.md +1 -0
  51. package/assets/skills/ctds-page/SKILL.md +12 -2
  52. package/assets/skills/ctds-wireframe/SKILL.md +35 -1
  53. package/package.json +2 -4
@@ -0,0 +1,93 @@
1
+ # Page Header
2
+
3
+ ### 원칙
4
+ 페이지 바디 최상단에 쓰는 **"이 페이지가 뭘 하는 곳인가"** 블록. Topbar가 shell chrome(ID·전역 action)을 담는다면, Page Header는 **콘텐츠 레이어의 첫 블록**이다. [[components/topbar]]가 명시한 "큰 타이틀은 body 첫 블록 자리"를 받는 자리.
5
+
6
+ ### Anatomy
7
+ 3개 요소가 수직으로 쌓인다. (옵션 요소는 생략 가능)
8
+
9
+ ```
10
+ [eyebrow] ← 옵션: 상위 맥락 (breadcrumb·카테고리) — xs/muted
11
+ [h1 title] [actions] ← 필수: 큰 타이틀 + 우측 액션 (옵션)
12
+ [description] ← 옵션: 1~2줄 서브텍스트, muted
13
+ ```
14
+
15
+ - eyebrow와 title 사이: `space-1`
16
+ - title과 description 사이: `space-2`
17
+ - 블록 전체 아래 (다음 섹션까지): `space-6` (앱 리듬) / `space-10` (랜딩 리듬)
18
+ - actions는 title과 같은 row — `align-items: center`, `flex: 1 1 auto` title / `flex: 0 0 auto` actions
19
+
20
+ ### Do
21
+ - h1: `text-4xl` (랜딩) / `text-3xl` (앱), **`font-medium` 또는 그 이하** ([[tokens/typography]] font weight cap)
22
+ - h1에 **반드시 `line-height: var(--lh-tight)`** 명시 ([[tokens/spacing]] "텍스트 gap·line-height")
23
+ - description: `text-base` / `color: var(--fg-muted)` / `max-width: 60ch`
24
+ - actions는 [[components/_variants]] 액션 매핑에 따름 — 중요=`primary`, 서브=`outline`
25
+ - 액션 2개 이상이면 서로 간 gap은 `space-1` 고정 ([[tokens/spacing]])
26
+
27
+ ### Don't
28
+ - [HARD] h1 아래 `margin-bottom`을 자식(h1)이 걸고 **동시에** 부모 wrapper도 gap을 걸지 않는다 — 이중 여백 ([[tokens/spacing]] Don't)
29
+ - [HARD] h1을 `font-semibold`/`font-bold`로 쓰지 않는다 — [[tokens/typography]] font weight cap
30
+ - [HARD] uppercase + letter-spacing 조합 금지 — 메모리 [no-uppercase]
31
+ - [SOFT] eyebrow 없이 breadcrumb만 Topbar leading에 두는 패턴은 피한다 — 페이지 식별이 shell로 샌다. Topbar leading에는 workspace/section만, 페이지 이름은 body로
32
+
33
+ ### Fallback
34
+ 서브텍스트가 애매하면 생략. 설명이 1줄 미만이면 쓰지 않는다. actions도 없으면 h1 단독으로.
35
+
36
+ ### 조립 예시
37
+ ```tsx
38
+ <header className="page-header">
39
+ {/* eyebrow 옵션 */}
40
+ <div className="eyebrow">프로젝트</div>
41
+ <div className="title-row">
42
+ <h1>개발 계획·실행</h1>
43
+ <div className="actions">
44
+ <Button variant="outline" size="md">가져오기</Button>
45
+ <Button variant="primary" size="md">새 계획</Button>
46
+ </div>
47
+ </div>
48
+ <p className="description">
49
+ 확정본을 선택해 개발 계획을 요청하고, 계획과 작업 범위를 승인한 뒤 실행하세요.
50
+ </p>
51
+ </header>
52
+ ```
53
+
54
+ ```css
55
+ .page-header {
56
+ display: flex;
57
+ flex-direction: column;
58
+ gap: var(--space-1); /* eyebrow→title */
59
+ margin-bottom: var(--space-6);
60
+ }
61
+ .page-header .title-row {
62
+ display: flex;
63
+ align-items: center;
64
+ gap: var(--space-3);
65
+ }
66
+ .page-header h1 {
67
+ flex: 1 1 auto;
68
+ font-size: var(--text-3xl);
69
+ font-weight: var(--font-weight-medium);
70
+ line-height: var(--lh-tight);
71
+ }
72
+ .page-header .actions {
73
+ display: flex;
74
+ gap: var(--space-1);
75
+ flex: 0 0 auto;
76
+ }
77
+ .page-header .description {
78
+ color: var(--fg-muted);
79
+ margin-top: var(--space-1); /* title→description은 더 가깝게 */
80
+ max-width: 60ch;
81
+ }
82
+ .page-header .eyebrow {
83
+ font-size: var(--text-xs);
84
+ color: var(--fg-muted);
85
+ }
86
+ ```
87
+
88
+ ### 관련
89
+ - [[recipes/section-header]] — 하위 섹션의 유사 패턴
90
+ - [[components/topbar]] — shell 쪽. "큰 타이틀은 body 첫 블록 자리" 지침의 수신처
91
+ - [[components/breadcrumb]] — eyebrow 자리에 쓸 수 있는 vendor
92
+ - [[tokens/spacing]] — 블록 아래 리듬 선택
93
+ - [[tokens/typography]] — font weight cap, lh-tight
@@ -0,0 +1,90 @@
1
+ # Section Header
2
+
3
+ ### 원칙
4
+ 페이지 바디 안의 **섹션 경계**를 알리는 중간 블록. Page Header보다 작고 조용하다. 섹션이 반복될 때 **같은 리듬·같은 위계**로 등장해야 페이지가 흩어지지 않는다.
5
+
6
+ ### Anatomy
7
+ 한 줄 row + (옵션) 설명.
8
+
9
+ ```
10
+ [h2 title] [count] [actions] ← 필수: h2, 옵션: count badge / 우측 액션
11
+ [description] ← 옵션: 1줄 설명 (muted)
12
+ ```
13
+
14
+ - title과 count: `space-2` (한 줄 안)
15
+ - title row와 description: `space-1`
16
+ - 섹션 header와 body(리스트/카드 등) 사이: `space-3`. **body 내부 아이템끼리 gap(space-1)보다 반드시 한 단계 더 넓어야** 위계 성립. 둘이 같으면 "타이틀과 아이템이 같은 레벨"로 뭉쳐 보임
17
+ - 섹션끼리는 **반복되는 작업 단위**면 `space-20`(80px), 섹션 내부 블록 묶음이면 `space-6` ([[ASSEMBLY]] §2a 갭 가이드)
18
+
19
+ ### Do
20
+ - h2: **`text-lg` 기본**, 랜딩 리듬이면 `text-xl` 까지. **`font-medium`** ([[tokens/typography]] "섹션 h2/h3는 semibold 금지"). text-xl 이상은 "크고 얇은" 함정에 빠지기 쉬움 — 콘솔 리듬에서는 피함
21
+ - count badge: [[components/badge]] `soft` variant, title 바로 오른쪽
22
+ - actions는 title row 끝에 — `flex: 0 0 auto`
23
+ - actions 중 가장 흔한 "새로고침·더보기"는 [[components/icon-button]] `ghost` 또는 `outline`
24
+ - 액션이 2개 이상이면 서로 간 gap `space-1`
25
+
26
+ ### Don't
27
+ - [HARD] `<section>` 태그를 쓰지 않는다 — AppShell의 `.content section`이 `padding-top: space-20`(80px)을 꽂아 "섹션 머리에 거대한 여백" 함정 발생. `<div>`로 짠다 ([[feedback-no-semantic-tags-in-components]])
28
+ - [HARD] h2를 `font-semibold`/`font-bold`로 쓰지 않는다 — [[tokens/typography]] font weight cap
29
+ - [HARD] h2 아래에 `border-bottom`을 깔지 않는다. 섹션 분리는 **gap**이 담당. 선 + 공간은 이중 분리
30
+ - [HARD] 섹션끼리 `space-6` 이상 gap으로 분리하지 않는다 — 각 섹션이 border/배경으로 분리돼 있으면 과한 공간은 "구조가 끊긴" 결과 ([[tokens/spacing]] Don't)
31
+ - [SOFT] title row에 액션이 **3개 이상**이면 Toolbar를 쓴다. 액션이 많으면 섹션이 아니라 toolbar가 맞음
32
+
33
+ ### Fallback
34
+ 설명이 애매하면 생략. actions도 없으면 h2 단독으로. count badge는 숫자가 **의미 있을 때만**(총 몇 개인지 알아야 하는 리스트 등) — 장식용 금지.
35
+
36
+ ### 조립 예시
37
+ ```tsx
38
+ <div>
39
+ <header className="section-header">
40
+ <div className="title-row">
41
+ <h2>작업 계획</h2>
42
+ <Badge variant="soft">4</Badge>
43
+ <div className="actions">
44
+ <IconButton icon={<Icon name="arrow-clockwise" />} variant="ghost" aria-label="새로고침" />
45
+ </div>
46
+ </div>
47
+ <p className="description">
48
+ 요청한 계획을 검토하고 승인하세요.
49
+ </p>
50
+ </header>
51
+ <div className="section-body">
52
+ {/* 섹션 바디 */}
53
+ </div>
54
+ </div>
55
+ ```
56
+
57
+ ```css
58
+ .section-header {
59
+ display: flex;
60
+ flex-direction: column;
61
+ gap: var(--space-1);
62
+ margin-bottom: var(--space-3);
63
+ }
64
+ .section-header .title-row {
65
+ display: flex;
66
+ align-items: center;
67
+ gap: var(--space-2);
68
+ }
69
+ .section-header h2 {
70
+ font-size: var(--text-lg);
71
+ font-weight: var(--font-weight-medium);
72
+ line-height: var(--lh-tight);
73
+ }
74
+ .section-header .actions {
75
+ display: flex;
76
+ gap: var(--space-1);
77
+ margin-left: auto;
78
+ }
79
+ .section-header .description {
80
+ color: var(--fg-muted);
81
+ font-size: var(--text-sm);
82
+ }
83
+ ```
84
+
85
+ ### 관련
86
+ - [[recipes/page-header]] — 상위 블록. 위계상 h1 → h2
87
+ - [[components/badge]] — count badge
88
+ - [[components/icon-button]] — 섹션 액션
89
+ - [[tokens/spacing]] — 섹션 간 gap
90
+ - [[tokens/typography]] — font weight cap
@@ -0,0 +1,72 @@
1
+ # Focus
2
+
3
+ ### 원칙
4
+ 데이터 밀도 중심 — 관리자 대시보드, 분석 도구, 로그 뷰어, 트레이딩 콘솔처럼 **한 화면에 많은 정보를 올려야 하고 사용자가 매일 몇 시간씩 들여다보는** 자리의 Theme. 꾸밈을 걷어내고 밀도를 올려 "읽기 좋음"에 전부를 투자한다. `spare`가 "매일 쓰는 도구의 중앙값"이라면 `focus`는 그 극단 — 밀도를 한 단계 더 올리고 브랜드 액센트를 완전히 중성화한다.
5
+
6
+ ### Do
7
+ - 테이블·리스트·사이드바에 가능한 많은 행을 노출. 섹션 간 호흡은 Density가 결정하되 추가 margin은 금지.
8
+ - 상태는 색이 아니라 **배지·형태·weight**로 먼저 전달. 색은 status(warning/danger/success/info)에만 남긴다.
9
+ - 액션은 Toolbar·IconButton·DropdownMenu 중심. 큰 primary 버튼은 폼 제출·CTA 자리에만.
10
+ - 모든 숫자·금액 셀은 좌측 정렬 유지 — [[feedback_no_right_align_numbers]] 그대로.
11
+ - 사이드바·탑바는 작은 size(sm)로 밀도를 더 쪼은다.
12
+
13
+ ### Don't
14
+ - 마케팅·랜딩·온보딩에 쓰지 않는다. 액센트가 없어 전환이 안 터진다.
15
+ - "비어 보여서" 간격이나 장식을 추가하지 않는다. compact density는 의도된 밀도.
16
+ - `vivid`/`pastel` palette로 override하지 않는다 — 밀도가 높을수록 색 노이즈가 피로를 가속.
17
+ - 브랜드 identity를 색으로 보여야 하는 자리엔 이 Theme이 맞지 않음. [[themes/spare]]나 [[themes/expressive]]로.
18
+
19
+ ### Fallback
20
+ 축 preset은 아래 표 값으로 고정. palette만 브랜드 선호에 따라 `mono` ↔ `standard` 사이 선택 가능.
21
+
22
+ ### 관련
23
+ - [[themes/_SCHEMA]] — Theme 스키마
24
+ - [[themes/spare]] — "매일 쓰는 도구의 중앙값". 밀도를 한 단계 낮춘 버전.
25
+ - [[axes/palette]] — `mono` 값과의 상호작용(아이콘·포커스·nav-active 전부 중성 fg 톤).
26
+ - [[axes/density]] — `compact` 값 전용 프리셋.
27
+
28
+ ---
29
+
30
+ ### Signature
31
+ 이 Theme IS "매일 몇 시간씩 머무는 작업실" UI. 데이터 밀도가 디자인의 1원칙이고, 꾸밈은 피로 가속기라는 전제 위에 있다. 터미널의 자제력을 웹 앱의 레이어에 끌어들인 결과물 — not minimalism, but engineered legibility.
32
+
33
+ ### Preset
34
+
35
+ | Axis | Value | Why |
36
+ |---|---|---|
37
+ | [[axes/mode]] | `dark` | 장시간 사용 환경에서 피로 최소화. light override는 소비자 선호. |
38
+ | [[axes/palette]] | `mono` | 브랜드 액센트 완전 제거. 아이콘·포커스·nav-active 전부 fg 톤. status만 유색 유지. |
39
+ | [[axes/shape]] | `crisp` | 격자 자체가 신호. soft radius는 밀도 환경에서 "뭉개짐"으로 읽힌다. |
40
+ | [[axes/density]] | `compact` | 핵심 축. 행 간격·컨트롤 높이가 한 단계 좁아진다. |
41
+ | [[axes/font]] | `lang=ko` | 한국어 기본. 폰트 스택은 Font 축이 담당. |
42
+ | [[axes/icon]] | `phosphor` | regular/fill 매트릭 완전 매칭. 밀도 환경에선 아이콘 식별이 중요. |
43
+ | [[axes/motion]] | `calm` | 애니메이션 최소화 — 눈이 머무는 시간이 길어 bounce/overshoot가 피로. none은 접근성 승인된 사용자용. |
44
+
45
+ ### Layout
46
+ 2-column 또는 3-pane이 디폴트 — 좌측 사이드바(sm size) + 중앙 작업 영역 + 우측 디테일 패널. 한 화면에 가능한 많은 정보를 수평으로 분할. 1-column 중심 레이아웃(블로그·마케팅)엔 맞지 않음.
47
+
48
+ ### Imagery
49
+ 없음. 데이터와 아이콘만. 사진·일러스트는 이 Theme의 성격과 어긋남 — 작업 중 시선을 분산시킴. 예외: 사용자 아바타·조직 로고 같은 identity 식별자.
50
+
51
+ ### Decoration
52
+ 없음. hairline과 bg-subtle의 톤 차이만으로 그룹 구분. gradient·noise·pattern 금지. 이 Theme에서 "장식은 피로"의 공리.
53
+
54
+ ### Negative
55
+ - no primary accent color — status 외 모든 색은 중성 fg 톤
56
+ - no large hero section — "눈에 띄는 한 자리"가 없는 게 디폴트
57
+ - no illustrations · no photography — 작업 영역에 아트는 노이즈
58
+ - no soft radius — crisp 격자가 밀도의 전제
59
+ - no bouncy motion — overshoot는 매일 보기 피곤
60
+
61
+ ### Override
62
+ 전부 자유. 사용자가 "focus에서 shape만 soft로"처럼 지시하면 그대로 적용. 책임은 사용자. Theme 선언을 벗어난 조합의 완성도는 보증하지 않는다 ([[PRINCIPLES]] §7).
63
+
64
+ ### Known Gaps
65
+ - 랜딩·마케팅 자리는 커버 안 함 — [[themes/expressive]]로.
66
+ - 모바일 터치 중심 UX는 커버 안 함 — compact density는 데스크톱·태블릿 가로 전제.
67
+ - 색으로 identity를 전달해야 하는 브랜드엔 맞지 않음 — mono가 디폴트이므로.
68
+
69
+ ### Iteration Guide
70
+ 1. 밀도를 더 올리고 싶으면 size prop(xs/sm)으로 가되, density 축 자체는 compact에서 더 내릴 수 없다 — compact이 최종 밀도.
71
+ 2. palette를 `mono`에서 `standard` 또는 `calm`으로 올리는 override는 허용. 그 외(vivid/pastel)는 Theme과 상충.
72
+ 3. motion을 bouncy로 올리는 override는 **금지** — focus의 핵심 자제가 깨짐.
@@ -20,6 +20,7 @@ Layer 1(shadcn 방식 컴포넌트 코드) + Layer 2(AI 프롬프트 컨텍스
20
20
  5. **애매하면 묻는다** — 규칙으로 판단 안 서면 사용자 확인.
21
21
 
22
22
  전체 원칙: `prompts/PRINCIPLES.md`.
23
+ 벤더에 없는 자리를 조립할 땐: `prompts/ASSEMBLY.md` + `prompts/recipes/*.md`.
23
24
 
24
25
  ## 작업 유형 → 스킬 라우팅
25
26
 
@@ -7,22 +7,32 @@ description: CTDS 페이지·대시보드·레이아웃을 조합할 때 발동.
7
7
 
8
8
  페이지는 **조합**이지 제작이 아니다. 기존 `web/components/` 에서 골라 배치하고, 축 값에 따라 간격·크기·배치를 조정한다. 새 컴포넌트가 필요하면 `ctds-component`로 넘긴다.
9
9
 
10
+ **벤더에 없는 자리를 수제 조립해야 하면 반드시 `prompts/ASSEMBLY.md`를 먼저 읽는다.** 조립 알고리즘 5단계와 자리별 레시피(`prompts/recipes/`)가 리듬·위계·여백을 보장한다.
11
+
10
12
  ## 판단 순서
11
13
 
12
14
  1. 현재 프리셋·축 값 확인 — 특히 **Density** (compact / comfortable)
13
15
  2. 필요한 컴포넌트가 모두 존재하는지 확인 → `web/components/`
14
16
  3. shell 선택 (AppFrame / Sidebar / SidebarSplit / Topbar) — `web/components/AppFrame/` 등
15
17
  4. 섹션 조립 — Spacing 토큰으로 간격, Density에 따라 스케일링
16
- 5. 접촉 금지·스크롤 패딩 등 레이아웃 규칙 적용
17
- 6. 접근성 — 랜드마크, 포커스 순서, 키보드 네비
18
+ 5. **벤더에 없는 자리는 `prompts/ASSEMBLY.md` 알고리즘대로 조립 + `recipes/*.md` 참조**
19
+ 6. 접촉 금지·스크롤 패딩 등 레이아웃 규칙 적용
20
+ 7. 접근성 — 랜드마크, 포커스 순서, 키보드 네비
18
21
 
19
22
  ## 참조 매트릭스
20
23
 
21
24
  | 조건 | 읽을 문서 |
22
25
  |---|---|
23
26
  | 항상 | `prompts/PRINCIPLES.md` |
27
+ | 벤더에 없는 자리 조립 | `prompts/ASSEMBLY.md` + `prompts/recipes/<자리>.md` |
24
28
  | 간격·여백 | `prompts/tokens/spacing.md` + `prompts/axes/density.md` |
25
29
  | shell·네비 | `prompts/components/topbar.md`, `web/components/{AppFrame,Sidebar,SidebarSplit,Topbar}/` |
30
+ | 페이지 상단 블록 | `prompts/recipes/page-header.md` |
31
+ | 섹션 상단 블록 | `prompts/recipes/section-header.md` |
32
+ | 카드처럼 보이는 리스트 row | `prompts/recipes/card-row.md` |
33
+ | 메타 라벨 가로 나열 | `prompts/recipes/meta-line.md` |
34
+ | 폼·모달 하단 액션 | `prompts/recipes/form-footer.md` |
35
+ | 페이지 폭 안내 바 | `prompts/recipes/page-banner.md` |
26
36
  | 리스트 | `prompts/components/list-item.md` |
27
37
  | 테이블 | `prompts/components/{table-row,table-row-edit,table-row-select,table-header}.md` |
28
38
  | 폼 | `prompts/components/{form-field,input,select,checkbox,radio,switch}.md` |
@@ -44,6 +44,7 @@ description: 와이어프레임·목업·기존 페이지를 CTDS로 번역·교
44
44
  5. **여백 리듬** ⭐ — 섹션 간 여백이 `--space-4/6/8` 토큰 리듬을 따르는가? 하드코딩이나 중구난방인 간격 플래그.
45
45
  6. **"빈 자리" 감지** — 눈으로 봤을 때 어색하게 비어 보이는 자리가 있는가? 그 자리에 CTDS가 요구하는 요소(타이틀·설명 1줄·보조 액션)가 들어가야 하는가?
46
46
  7. **그룹핑** — 가까이 있는데 역할이 다른 요소가 섞여있지 않은가? 역할이 같은데 분리돼 있지 않은가?
47
+ 8. **"한 몸처럼 붙은 두 버튼" 감지** ⭐ — 라벨 영역 옆에 작은 caret(▾)·아이콘 영역이 **구분선 하나로 붙어있는** 형태가 보이면 거의 100% **SplitButton**이다. Button 두 개로 조립하거나 Button 안에 caret을 억지로 넣지 말 것. ([[antipattern_split_button_as_two_buttons]])
47
48
 
48
49
  진단 결과는 보정 패스 전에 **글로 적어서 사용자에게 공유**. 자동으로 넘어가지 말 것.
49
50
 
@@ -59,10 +60,35 @@ description: 와이어프레임·목업·기존 페이지를 CTDS로 번역·교
59
60
  | 네모 박스 안 숫자 | 그냥 Card | MetricCard (label + value + delta) |
60
61
  | 긴 가로 바 액션 (저장·취소) | 큰 Button 2개 | 페이지 하단 Toolbar 또는 폼 Footer 패턴 |
61
62
  | "+ 새로 만들기" 가로 바 | FilterButton | Button variant="primary" 또는 EmptyState CTA |
63
+ | **라벨 + 작은 ▾ caret이 한 몸처럼 붙은 버튼** (예: `+ New note ▾`, `저장 ▾`) | 수제 Button + Button 조립, Button 안에 caret 아이콘 억지로 넣기 | **SplitButton** — main(기본 액션) + menu(▾ 드롭다운). 둘이 시각적으로 붙어있고 클릭 영역이 분리된 모든 패턴 ([[components/split-button]]) |
62
64
  | 색상 라벨 (상태) | Chip | Badge (상태·메타=Badge, 선택 필터=Chip) |
63
65
 
64
66
  의미 매핑 안티패턴은 `~/.claude/projects/-Users-heeyoung-Documents-CTDS/memory/` 에서 `antipattern_*.md` 로 축적된다. 매핑 전에 메모리 인덱스에서 관련 안티패턴 검색.
65
67
 
68
+ ### 패스 3.5. 커버리지 결정 — 벤더 그대로 vs 로컬 파생 vs 수제 (⭐ 통일성의 핵심)
69
+
70
+ 패스 3에서 매핑한 각 자리에 대해 **세 단계 중 어느 길인지** 반드시 결정하고 글로 적는다. 수제(div+span 조립)로 빠지는 순간 토큰·여백·사이즈 리듬이 전부 깨진다 — 이게 번역이 어색해지는 1번 원인.
71
+
72
+ **결정 트리** (위에서부터 순서대로 적용):
73
+
74
+ 1. **CTDS 벤더 컴포넌트가 그대로 맞음** → 그대로 import해서 사용. 끝.
75
+ 2. **살짝 다름** (라벨 하나 더, trailing 영역 하나 추가, 특정 variant 미지원 등) → **로컬 파생 컴포넌트** 생성:
76
+ - 가장 비슷한 CTDS 벤더 컴포넌트 코드(JSX + CSS Module)를 **그대로 복사해서 소비 프로젝트 로컬 경로**(예: `web/app/_components/` 또는 `app/components/<page>/_parts/`)에 **다른 이름**으로 둠.
77
+ - 거기서 **디자인만 살짝** 조정. 토큰·height·padding·gap·radius 기본값은 **건드리지 말고 유지** — 조정은 추가 요소/위치/variant 수준.
78
+ - **CTDS 벤더 패키지는 절대 수정 금지** ([[feedback_no_vendor_modification]]).
79
+ 3. **벤더에 비슷한 것조차 없음** → `prompts/recipes/<자리>.md` 반드시 확인 ([[ASSEMBLY]]). 레시피에도 없으면 **수제가 아니라 사용자에게 보고** — "이 자리 벤더/레시피 둘 다 없음, 어떻게 할지" 물어본다. 임의로 div+span 수제 조립 금지.
80
+
81
+ **왜 로컬 파생이 수제보다 통일성이 좋은가**:
82
+ - 수제 조립은 토큰 선택부터 틀어진다. padding `12px`·gap `8px` 같은 직관에서 뽑은 값들이 CTDS space scale(--space-2=8, --space-3=12 등)과 미묘하게 어긋나거나, 심지어 하드코딩됨 ([[feedback_no_hardcoded_values]]).
83
+ - 로컬 파생은 **CTDS 벤더의 토큰 선택을 그대로 베낀 상태에서 시작**하므로 height·radius·font·icon size·transition까지 전부 CTDS 궤도 위에 올라가 있음. 조정은 "추가 요소를 어디 꽂을지"만 결정하면 됨.
84
+ - Shape/Density/Hue 축이 바뀌어도 벤더 토큰을 참조하고 있으니 로컬 파생도 같이 반응.
85
+
86
+ **로컬 파생 결정 시 확인**:
87
+ - 어떤 벤더 컴포넌트에서 베낄지 (파일 경로 명시)
88
+ - 어디에 둘지 (`_components/` or `_parts/`)
89
+ - 무엇을 바꿀지 (추가 slot, 삭제한 variant, 추가 라벨 — "디자인 기본값 건드리지 않음" 명시)
90
+ - 베끼면서 토큰 하드코딩 금지, 기존 토큰 그대로 유지
91
+
66
92
  ### 패스 4. 보정 — CTDS 리듬으로 재설계
67
93
 
68
94
  패스 2에서 플래그한 어색함을 전부 보정한 뒤에만 코드 작성:
@@ -72,12 +98,19 @@ description: 와이어프레임·목업·기존 페이지를 CTDS로 번역·교
72
98
  - **여백 리듬**: 섹션 간 `--space-6` 또는 `--space-8`, 섹션 안 블록 간 `--space-4`, 작은 컴포넌트 간 `--space-1`.
73
99
  - **그룹핑 재편**: 역할이 같은 것은 하나의 Section/Card에, 다른 것은 분리.
74
100
  - **원본에 없던 CTDS 패턴 추가**: EmptyState·Toolbar·Breadcrumb 등 원본엔 없지만 CTDS 페이지에 필요한 요소는 **추가하는 게 기본**.
101
+ - **벤더에 없는 자리는 레시피 참조**: 페이지 헤더·섹션 헤더·카드 row·메타 라인·폼 푸터·안내 배너 등 자주 등장하는 자리는 `prompts/recipes/<자리>.md`를 **반드시 열어** 토큰·구조 조합을 확인. 수제 조립로 가지 않는다 ([[ASSEMBLY]]).
75
102
 
76
103
  ## 체크리스트 — 번역 완료 전 전부 통과
77
104
 
78
105
  - [ ] 패스 1 (분석) 결과를 글로 적었는가
79
106
  - [ ] 패스 2 (진단) 결과를 사용자에게 공유했는가 — 자동 넘김 금지
80
107
  - [ ] 1:1 매핑이 아닌 역할 기반 매핑인가
108
+ - [ ] **각 자리마다 "벤더 그대로 / 로컬 파생 / 레시피 조립" 중 어느 길인지 글로 결정했는가** ⭐
109
+ - [ ] **수제 조립(div+span, 토큰 하드코딩)으로 간 자리가 하나도 없는가** ⭐ 벤더에 비슷한 것도 없고 레시피에도 없으면 **사용자에게 보고**
110
+ - [ ] 로컬 파생을 만든 경우: 벤더 코드 그대로 베꼈고 토큰 기본값 유지했는가 (디자인 조정은 추가 요소·위치 수준)
111
+ - [ ] CTDS 벤더 패키지(`packages/ctds-cli/assets/`, `node_modules/ctds/`)를 수정하지 않았는가
112
+ - [ ] **Sidebar가 있으면 Header/Body inner/Footer 패딩 공급 계획을 조립 전에 세웠는가** ⭐ ([[feedback_wireframe_sidebar_padding_check]])
113
+ - [ ] **Topbar 안 IdentityButton·identity 트리거에 sub prop 넣지 않았는가** (2줄 금지, [[feedback_topbar_single_line_identity]])
81
114
  - [ ] Topbar에 h1 또는 breadcrumb가 있는가 (없다면 명시적으로 이유)
82
115
  - [ ] 라벨 없는 섹션이 없는가
83
116
  - [ ] 한 영역 안 컴포넌트 `size` 통일 — 기본 `sm`
@@ -90,7 +123,8 @@ description: 와이어프레임·목업·기존 페이지를 CTDS로 번역·교
90
123
 
91
124
  | 조건 | 읽을 문서 |
92
125
  |---|---|
93
- | 항상 | `prompts/PRINCIPLES.md` + 메모리 `antipattern_*.md` 전체 |
126
+ | 항상 | `prompts/PRINCIPLES.md` + `prompts/ASSEMBLY.md` + 메모리 `antipattern_*.md` 전체 |
127
+ | 벤더에 없는 자리 조립 | `prompts/recipes/<자리>.md` (page-header, section-header, card-row, meta-line, form-footer, page-banner 등) |
94
128
  | 밀도 결정 | `prompts/axes/density.md` + [[feedback_default_size_sm]] |
95
129
  | 여백 리듬 | `prompts/tokens/spacing.md` |
96
130
  | shell·네비 | `prompts/components/{topbar,sidebar,app-frame}.md` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@conscience-technology/ctds",
3
- "version": "0.3.4",
3
+ "version": "0.4.1",
4
4
  "description": "CTDS — 하이브리드 디자인 시스템 설치 · 온보딩 CLI (shadcn식 코드 생성기)",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -14,15 +14,13 @@
14
14
  "bin",
15
15
  "src",
16
16
  "assets",
17
- "templates",
18
17
  "README.md"
19
18
  ],
20
19
  "exports": {
21
20
  ".": {
22
21
  "import": "./bin/ctds.js"
23
22
  },
24
- "./assets/*": "./assets/*",
25
- "./templates/*": "./templates/*"
23
+ "./assets/*": "./assets/*"
26
24
  },
27
25
  "scripts": {
28
26
  "bundle-assets": "node ./scripts/bundle-assets.mjs",