@qijenchen/design-system 0.1.0-beta.72 → 0.1.0-beta.74

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 (43) hide show
  1. package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
  2. package/ds-canonical/fork/governance.lock +106 -2
  3. package/ds-canonical/fork/launchers/inject_fork_governance_preamble.sh +8 -0
  4. package/ds-canonical/fork/manifest.json +15 -1
  5. package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +183 -0
  6. package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +65 -0
  7. package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +229 -0
  8. package/ds-canonical/fork/skills/delivery-handoff/references/flow-diagram.md +180 -0
  9. package/ds-canonical/fork/skills/delivery-handoff/references/handoff-template.md +177 -0
  10. package/ds-canonical/fork/skills/delivery-handoff/references/inventory-checklist.md +196 -0
  11. package/ds-canonical/fork/skills/performance-audit/SKILL.md +107 -0
  12. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +232 -0
  13. package/ds-canonical/fork/skills/product-ui-audit/references/audit-checks.md +246 -0
  14. package/ds-canonical/fork/skills/product-ui-audit/references/common-misuses.md +329 -0
  15. package/ds-canonical/fork/skills/product-ui-audit/references/report-template.md +159 -0
  16. package/ds-canonical/fork/skills/propose-options/SKILL.md +177 -0
  17. package/ds-canonical/fork/skills/prototype/SKILL.md +244 -0
  18. package/ds-canonical/fork/skills/prototype/references/audit-checks.md +38 -0
  19. package/ds-canonical/fork/skills/prototype/references/benchmark-sources.md +94 -0
  20. package/ds-canonical/fork/skills/prototype/references/checkpoints.md +191 -0
  21. package/ds-canonical/fork/skills/prototype/references/evaluation-matrix.md +141 -0
  22. package/ds-canonical/fork/skills/prototype/references/ooux-template.md +198 -0
  23. package/ds-canonical/fork/skills/prototype/references/proposal-template.md +229 -0
  24. package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +200 -0
  25. package/ds-canonical/fork/skills/ux-audit/SKILL.md +130 -0
  26. package/ds-canonical/fork/skills/visual-audit/SKILL.md +247 -0
  27. package/ds-canonical/fork/skills/visual-audit/output/.gitkeep +0 -0
  28. package/ds-canonical/fork/skills/visual-audit/references/audit-architecture.md +101 -0
  29. package/ds-canonical/fork/skills/visual-audit/references/visual-checklist.md +297 -0
  30. package/ds-canonical/fork/skills/visual-audit/references/world-class-benchmarks.md +198 -0
  31. package/ds-canonical/hooks/check_plugin_fork_health.sh +2 -2
  32. package/ds-canonical/hooks/lib/_app_shell_primary_header_consistency.sh +36 -6
  33. package/ds-canonical/hooks/session_start_governance_check.sh +1 -1
  34. package/ds-canonical/hooks/tests/test_check_app_shell_primary_header_consistency.sh +58 -2
  35. package/ds-canonical/skills/design-system-audit/SKILL.md +2 -2
  36. package/llms-full.txt +1 -1
  37. package/llms.txt +1 -1
  38. package/package.json +1 -1
  39. package/src/components/AppShell/_demo-helpers.tsx +25 -1
  40. package/src/components/AppShell/app-shell.principles.stories.tsx +3 -2
  41. package/src/components/AppShell/app-shell.spec.md +12 -7
  42. package/src/components/AppShell/app-shell.stories.tsx +6 -0
  43. package/src/components/Sidebar/sidebar.spec.md +2 -0
@@ -0,0 +1,329 @@
1
+ # Common Misuses — 元件誤用 negative example 庫
2
+
3
+ 針對本 DS 常見的元件誤用 pattern。每筆:**誤用 → 正解 → 理由**。
4
+
5
+ ---
6
+
7
+ ## Button 誤用
8
+
9
+ ### ❌ 多個 primary Button 並列
10
+
11
+ ```tsx
12
+ <div className="flex gap-2">
13
+ <Button variant="primary">儲存</Button>
14
+ <Button variant="primary">下載</Button>
15
+ <Button variant="primary">分享</Button>
16
+ </div>
17
+ ```
18
+
19
+ **正解**:一個 row 一個 primary,其他降階。
20
+
21
+ ```tsx
22
+ <div className="flex gap-2">
23
+ <Button variant="primary">儲存</Button>
24
+ <Button variant="tertiary">下載</Button>
25
+ <Button variant="tertiary">分享</Button>
26
+ </div>
27
+ ```
28
+
29
+ **理由**:primary 是「這個流程的主 CTA」,多個 primary 會讓使用者不知該點哪個。
30
+
31
+ ### ❌ icon-only 無 aria-label
32
+
33
+ ```tsx
34
+ <Button iconOnly startIcon={Trash} /> // ❌
35
+ ```
36
+
37
+ **正解**:`aria-label="刪除"`。screen reader 必要。
38
+
39
+ ### ❌ Button 巢狀
40
+
41
+ ```tsx
42
+ <Button onClick={outer}>
43
+ 外層
44
+ <Button>內層</Button> {/* ❌ 巢狀 button invalid HTML */}
45
+ </Button>
46
+ ```
47
+
48
+ **正解**:拆成兩個 sibling Button 或 inline ItemInlineAction。
49
+
50
+ ---
51
+
52
+ ## Field / Input 誤用
53
+
54
+ ### ❌ 裸 `<input>` 未包 Field wrapper
55
+
56
+ ```tsx
57
+ <input type="text" className="border rounded p-2" /> {/* ❌ */}
58
+ ```
59
+
60
+ **正解**:用 `<Input>` 元件或包 Field wrapper。
61
+
62
+ **理由**:DS `<Input>` 已帶 fieldWrapperStyles(hover / focus / error / disabled 狀態全套),自 roll `<input>` 失去一致性。
63
+
64
+ ### ❌ Input 外層自訂 border / padding
65
+
66
+ ```tsx
67
+ <div className="border-2 border-primary p-3 rounded-xl">
68
+ <Input />
69
+ </div>
70
+ ```
71
+
72
+ **正解**:用 Input 的 `error` prop 或 cva variant,不自套 wrapper。
73
+
74
+ ---
75
+
76
+ ## Dialog / Popover / Sheet 誤用
77
+
78
+ ### ❌ Dialog 內放 Popover(巢狀浮層)
79
+
80
+ ```tsx
81
+ <Dialog>
82
+ <DialogContent>
83
+ <Popover>...</Popover> {/* ❌ 浮層巢狀不推薦 */}
84
+ </DialogContent>
85
+ </Dialog>
86
+ ```
87
+
88
+ **正解**:改用 Dialog 內 Tabs / Accordion / SelectMenu 等 inline 結構。
89
+
90
+ ### ❌ Dialog 無 DialogTitle
91
+
92
+ ```tsx
93
+ <DialogContent>
94
+ <p>確定刪除?</p>
95
+ <Button>確定</Button>
96
+ </DialogContent>
97
+ ```
98
+
99
+ **正解**:必有 DialogTitle + DialogDescription(a11y 必要)。
100
+
101
+ ```tsx
102
+ <DialogContent>
103
+ <DialogHeader><DialogTitle>刪除專案?</DialogTitle></DialogHeader>
104
+ <DialogBody><p>此動作無法復原</p></DialogBody>
105
+ <DialogFooter>
106
+ <Button variant="tertiary">取消</Button>
107
+ <Button variant="primary">確定刪除</Button>
108
+ </DialogFooter>
109
+ </DialogContent>
110
+ ```
111
+
112
+ ### ❌ Popover 當 Tooltip 用
113
+
114
+ ```tsx
115
+ <Popover>
116
+ <PopoverTrigger asChild>
117
+ <button>hover me</button>
118
+ </PopoverTrigger>
119
+ <PopoverContent>提示文字</PopoverContent>
120
+ </Popover>
121
+ ```
122
+
123
+ **正解**:Tooltip 元件。Popover 是 click 觸發互動面板,Tooltip 是 hover 觸發純文字提示。
124
+
125
+ ---
126
+
127
+ ## Empty / 空狀態誤用
128
+
129
+ ### ❌ 自寫 flex+icon+title+desc 垂直居中
130
+
131
+ ```tsx
132
+ <div className="flex flex-col items-center text-center gap-2 py-12">
133
+ <FileSearch size={48} className="text-fg-muted" />
134
+ <div className="text-body-lg font-medium">沒有符合的結果</div>
135
+ <div className="text-body text-fg-secondary">請調整篩選條件</div>
136
+ <Button>重設篩選</Button>
137
+ </div>
138
+ ```
139
+
140
+ **正解**:
141
+
142
+ ```tsx
143
+ <Empty
144
+ icon={FileSearch}
145
+ title="沒有符合的結果"
146
+ description="請調整篩選條件"
147
+ action={<Button>重設篩選</Button>}
148
+ />
149
+ ```
150
+
151
+ **理由**:Empty 元件 own icon size(Avatar 48px)/ typography tier / gap token。自寫 drift 風險。
152
+
153
+ ---
154
+
155
+ ## Skeleton / CircularProgress / Empty 混用
156
+
157
+ ### ❌ Loading 狀態用 Empty
158
+
159
+ ```tsx
160
+ {isLoading && <Empty description="Loading..." />} {/* ❌ */}
161
+ ```
162
+
163
+ **正解**:Skeleton(骨架)或 CircularProgress(不知時長,indeterminate)。Empty 是「確認無資料」。全頁 loading 可 `<Empty icon={<CircularProgress size={48}/>} title="載入中" />`。
164
+
165
+ ### ❌ Error 狀態用 Empty
166
+
167
+ ```tsx
168
+ {error && <Empty description="載入失敗" />} {/* ❌ */}
169
+ ```
170
+
171
+ **正解**:`<Alert variant="error">`。Empty 是中性空(可能有操作解除),Error 是需處理的問題。
172
+
173
+ ---
174
+
175
+ ## ProgressBar / CircularProgress 混用
176
+
177
+ ### ❌ 不知進度硬套 ProgressBar(value=0 / 亂跳)
178
+
179
+ ```tsx
180
+ <ProgressBar value={isLoading ? 30 : 100} /> // ❌ 進度無法量化
181
+ ```
182
+
183
+ **正解**:`<CircularProgress>`(不傳 value)做 indeterminate。ProgressBar 是 determinate。
184
+
185
+ ### ❌ 已知百分比的大區塊進度用 CircularProgress indeterminate
186
+
187
+ ```tsx
188
+ <CircularProgress /> {/* 明明已知 45% */}
189
+ ```
190
+
191
+ **正解**:大區塊 / 頁面級用 `<ProgressBar value={45} affix="value" />`;inline 小空間用 `<CircularProgress value={45} affix="value" />`。
192
+
193
+ ---
194
+
195
+ ## Tabs / Accordion / Carousel 誤用
196
+
197
+ ### ❌ Tabs 切換「獨立功能」而非平行視圖
198
+
199
+ ```tsx
200
+ <Tabs>
201
+ <TabsTrigger value="settings">設定</TabsTrigger>
202
+ <TabsTrigger value="logout">登出</TabsTrigger> {/* ❌ 登出是 action 不是 tab */}
203
+ </Tabs>
204
+ ```
205
+
206
+ **正解**:登出走 DropdownMenu 或獨立 Button。Tabs 是「切平行內容視圖」。
207
+
208
+ ### ❌ Accordion 內巢狀 Accordion
209
+
210
+ ```tsx
211
+ <Accordion>
212
+ <AccordionItem>
213
+ <AccordionContent>
214
+ <Accordion>...</Accordion> {/* ❌ */}
215
+ </AccordionContent>
216
+ </AccordionItem>
217
+ </Accordion>
218
+ ```
219
+
220
+ **正解**:改用 TreeView(有階層語意)或 flatten。
221
+
222
+ ### ❌ Carousel 當資料切換器用
223
+
224
+ ```tsx
225
+ <Carousel>
226
+ <CarouselItem>總覽</CarouselItem>
227
+ <CarouselItem>成員</CarouselItem>
228
+ <CarouselItem>設定</CarouselItem>
229
+ </Carousel>
230
+ ```
231
+
232
+ **正解**:`<Tabs>`。Carousel 是輪播同類內容(圖片組 / testimonial),不是命名視圖切換。
233
+
234
+ ---
235
+
236
+ ## Coachmark / Dialog / Popover 用錯場景
237
+
238
+ ### ❌ 確認破壞性 action 用 Coachmark
239
+
240
+ ```tsx
241
+ <Coachmark title="確定刪除?" onNext={del}>
242
+ <Button variant="primary" danger>刪除</Button>
243
+ </Coachmark>
244
+ ```
245
+
246
+ **正解**:`<Dialog>`。Coachmark 是 non-modal onboarding(使用者可忽略),Dialog 是 modal 阻斷(必須處理)。
247
+
248
+ ### ❌ 錯誤訊息用 Coachmark
249
+
250
+ ```tsx
251
+ <Coachmark title="載入失敗" description="網路異常" />
252
+ ```
253
+
254
+ **正解**:`<Alert variant="error">` 或 `<Notice>` (非浮層)/ Toast(非阻斷)。Coachmark 是主動推送功能介紹,不是錯誤回報。
255
+
256
+ ---
257
+
258
+ ## ScrollArea / Native overflow 混用
259
+
260
+ ### ❌ Consumer 內 DataTable 水平捲動用 native overflow-x-auto
261
+
262
+ ```tsx
263
+ <div className="overflow-x-auto">
264
+ <DataTable columns={...} data={...} />
265
+ </div>
266
+ ```
267
+
268
+ **正解**:`<ScrollArea orientation="horizontal">` 包(跨 OS 一致)。
269
+
270
+ ```tsx
271
+ <ScrollArea>
272
+ <DataTable columns={...} data={...} />
273
+ <ScrollBar orientation="horizontal" />
274
+ </ScrollArea>
275
+ ```
276
+
277
+ ---
278
+
279
+ ## AspectRatio / 硬寫 aspect-* 混用
280
+
281
+ ### ❌ media 容器硬寫 `aspect-video`
282
+
283
+ ```tsx
284
+ <div className="aspect-video bg-muted">
285
+ <img src={url} />
286
+ </div>
287
+ ```
288
+
289
+ **正解**:
290
+
291
+ ```tsx
292
+ <AspectRatio ratio={16 / 9} className="bg-muted">
293
+ <img src={url} className="w-full h-full object-cover" />
294
+ </AspectRatio>
295
+ ```
296
+
297
+ **理由**:`AspectRatio` 是 SSR-safe padding-bottom 方案,跨 OS / 未載入時穩定。硬寫 class 在某些邊緣瀏覽器失效。
298
+
299
+ ---
300
+
301
+ ## 色彩誤用
302
+
303
+ ### ❌ primary 當狀態色用(Mindset #1 違反)
304
+
305
+ ```tsx
306
+ <ProgressBar className="bg-primary" value={60} /> {/* ❌ 除非就是進度 */}
307
+ <Tag className="bg-primary">進行中</Tag> {/* ❌ 應用 info */}
308
+ ```
309
+
310
+ **正解**:進行中用 info,操作入口用 primary。
311
+
312
+ ```tsx
313
+ <Tag className="bg-info-subtle text-info-text">進行中</Tag>
314
+ <Button variant="primary">開始</Button>
315
+ ```
316
+
317
+ ### ❌ 硬寫 Tailwind 預設色
318
+
319
+ ```tsx
320
+ <div className="text-red-500 bg-blue-100"> // ❌
321
+ ```
322
+
323
+ **正解**:改 semantic token(text-error / bg-info-subtle)。
324
+
325
+ ---
326
+
327
+ ## 此清單如何擴充
328
+
329
+ 每次 audit 發現新 misuse pattern,append 到本檔。保留 negative example + 正解 + 理由 3 段格式。
@@ -0,0 +1,159 @@
1
+ # Report Template — P0/P1/P2 分類 + 報告格式
2
+
3
+ ---
4
+
5
+ ## Severity 分類
6
+
7
+ ### P0 — 必修(無爭議 bug)
8
+
9
+ 自動 bug / 違反明確 DS 規則 / a11y 必要項缺失:
10
+
11
+ - Token 硬寫 hex / rgb / shadcn alias
12
+ - Tailwind default shadow(shadow-sm / md / lg)
13
+ - Tailwind v4 `[--foo]` shorthand
14
+ - icon-only 無 aria-label
15
+ - Dialog / Modal 無 DialogTitle
16
+ - 非 button 綁 onClick(a11y 破壞)
17
+ - 巢狀浮層 / 巢狀 Modal(HTML invalid 或 UX 破壞)
18
+ - node_modules/@qijenchen/design-system/ds-canonical/references/ui-dev-rules.md「同 flex 列互動 slot 幾何鐵律」違反
19
+
20
+ **處理**: AI 可直接修(surgical fix),commit 時 user 一併 review。
21
+
22
+ ### P1 — 批次修 + review
23
+
24
+ 設計原則違反 / 元件誤用 / 可改善但無立即 bug:
25
+
26
+ - Layout primitive 未消費(自 roll Empty / item-layout 等)
27
+ - 硬寫 px 值當應用 token
28
+ - placeholder 文案(Option A/B/C / Lorem ipsum)
29
+ - Primary Button 堆疊
30
+ - 巢狀 Accordion / Tabs / Carousel
31
+ - native overflow 未用 ScrollArea(跨 OS 跑版潛在風險)
32
+ - 硬寫 aspect-* class 未用 AspectRatio
33
+
34
+ **處理**: 批次 fix,每 Dim 一個 commit,由 user review。
35
+
36
+ ### P2 — 需討論
37
+
38
+ scope / 設計決策 / 業務判斷:
39
+
40
+ - cva defaultVariants 三方漂移(可能 intent)
41
+ - Rule B 邊界案例覆蓋不足(scope 決策)
42
+ - 新元件 promotion 判斷
43
+ - 歷史 code 風格差異(rename / refactor 決策)
44
+ - TODO 留白(規格未定)
45
+
46
+ **處理**: 不自動修,由 user 逐項決策。
47
+
48
+ ---
49
+
50
+ ## Report 格式範本
51
+
52
+ ```markdown
53
+ # Product UI Audit Report
54
+
55
+ **Scope**: `src/app/features/checkout/` (23 files)
56
+ **Date**: 2026-04-19
57
+ **Dimensions audited**: 6 (Token / Layout primitive / Component / Mindset / Geometry / A11y)
58
+
59
+ ## Summary
60
+
61
+ | Dim | Total findings | P0 | P1 | P2 |
62
+ |-----|---------------|-----|-----|-----|
63
+ | 1 Token | 3 | 2 | 1 | 0 |
64
+ | 2 Layout primitive | 5 | 0 | 4 | 1 |
65
+ | 3 Component | 2 | 1 | 1 | 0 |
66
+ | 4 Mindset | 4 | 0 | 3 | 1 |
67
+ | 5 Geometry | 1 | 1 | 0 | 0 |
68
+ | 6 A11y | 2 | 2 | 0 | 0 |
69
+ | **Total** | **17** | **6** | **9** | **2** |
70
+
71
+ ## Findings Detail
72
+
73
+ ### P0(必修 6 項)
74
+
75
+ | # | Dim | File:Line | Finding | Fix |
76
+ |---|-----|-----------|---------|-----|
77
+ | 1 | 1 Token | src/app/checkout/PaymentForm.tsx:87 | 硬寫 `#3b82f6` | 改 `var(--primary)` |
78
+ | 2 | 1 Token | src/app/checkout/Summary.tsx:42 | `shadow-md` | 改 `shadow-[var(--elevation-200)]` |
79
+ | 3 | 3 Component | src/app/checkout/PromoButton.tsx:12 | iconOnly Button 無 aria-label | 加 `aria-label="套用折扣碼"` |
80
+ | 4 | 5 Geometry | src/app/checkout/Actions.tsx:55 | 同 flex 行 Button sm(28)+ICon-only Primary(24)box 不一致 | 統一尺寸,或移 icon 入 Button's startIcon |
81
+ | 5 | 6 A11y | src/app/checkout/ProgressNav.tsx:23 | `<div onClick=...>` | 改 `<button>` 或加 `role="button" tabIndex={0} onKeyDown={...}` |
82
+ | 6 | 6 A11y | src/app/checkout/ConfirmModal.tsx:8 | Dialog 無 DialogTitle | 加 `<DialogTitle>確認結帳</DialogTitle>` |
83
+
84
+ ### P1(批次修 9 項)
85
+
86
+ {以 Dim 分組,per-Dim table}
87
+
88
+ ### P2(需討論 2 項)
89
+
90
+ | # | Dim | File:Line | Finding | 為何需討論 |
91
+ |---|-----|-----------|---------|---------|
92
+ | 16 | 2 Layout | src/app/checkout/EmptyCart.tsx:30 | 自 roll icon+title+desc+CTA structure | Consumer 若有品牌化 requirement 可能需 override Empty;需 user 確認 design intent |
93
+ | 17 | 4 Mindset | src/app/checkout/AmountInput.tsx:15 | Input typography 用 `text-[15px]` | 業務要求此欄位字體稍大,需評估 DS 是否加 variant 或 case-by-case 接受 |
94
+
95
+ ## 建議
96
+
97
+ **先修 P0 6 項**(1 個 commit):無爭議 bug,改完即世界級 baseline。
98
+ **再批次修 P1**(建議按 Dim 分 commit,4 commits):
99
+ 1. Token(Dim 1,1 項)
100
+ 2. Layout primitive(Dim 2,4 項)— 最大 batch
101
+ 3. Component(Dim 3,1 項)
102
+ 4. Mindset(Dim 4,3 項)
103
+
104
+ **最後討論 P2**(stakeholder 共同決策)。
105
+
106
+ ## Next
107
+
108
+ 等待 user Checkpoint 決策:
109
+ - (a) AI 直接修 P0,batch 修 P1,P2 逐項討論
110
+ - (b) 全部 findings 先給 user 自己看,AI 等候指令
111
+ - (c) 只修 P0,其他 park 到下個 sprint
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Triage Checkpoint 範本
117
+
118
+ audit 完,**不可**直接開始修。先 triage 問 user:
119
+
120
+ ```
121
+ 🔍 Product UI Audit Report
122
+
123
+ Scope: {scope}
124
+ Total findings: {N}
125
+
126
+ P0(必修,無爭議){N0 個} — token 違反 / a11y 必要缺 / 幾何鐵律違反
127
+ P1(批次修 + review){N1 個} — layout primitive 消費 / placeholder 文案 / Button 堆疊
128
+ P2(需討論){N2 個} — scope / 設計決策 / 業務判斷
129
+
130
+ 建議順序:
131
+ 1. 先修 P0(1 commit,surgical fix)
132
+ 2. 再批次修 P1(每 Dim 一個 commit,共 {N_dims} commits)
133
+ 3. P2 逐項討論
134
+
135
+ 你要:
136
+ (a) 按建議順序執行(我開始修 P0)
137
+ (b) 先讓我完整看 findings 再決定
138
+ (c) 跳過 P2,只修 P0+P1
139
+ (d) 縮窄 scope 到 {sub-folder}
140
+ ```
141
+
142
+ 絕對不可:AI 自行決定修哪些,必過 triage。
143
+
144
+ ---
145
+
146
+ ## 合法例外聲明範本
147
+
148
+ 若 audit hit 被判定為合法例外(per CLAUDE.md 或 spec documented),在 report 中明文標示:
149
+
150
+ ```markdown
151
+ ### Documented exceptions(非 findings,供參考)
152
+
153
+ | File:Line | Pattern | 例外理由 |
154
+ |-----------|---------|---------|
155
+ | Avatar.tsx:46 | `text: '#fff'` | cva 適用範圍例外(style prop 驅動 object map),per CLAUDE.md `cva 適用範圍` |
156
+ | Rating.spec.md:73 | `bg-warning` 黃星 | 世界級 convention(Amazon / Yelp / Google),documented |
157
+ ```
158
+
159
+ 讓 user 知道 AI 有注意到但判斷為合法 — 防被誤解為遺漏。
@@ -0,0 +1,177 @@
1
+ ---
2
+ name: propose-options
3
+ description: Auto-invoke when listing options / 建議 / 候選方案. Forces inline 7-Q principle check(M8 benchmark / M17 SSOT / Rule-of-3 / M10 subsumption)per option BEFORE listing. Failures filtered or labeled. Codifies「verify before propose」runtime discipline.
4
+ ---
5
+
6
+ # /propose-options — Propose-time 7-Q Gate
7
+
8
+ **目的**:Claude 對 user 提建議 / 列 option list 時,**先跑 7 題原則自檢**,通過才寫進回覆。Reject 的不列 OR 列出時標 fail 原因。
9
+
10
+ **對齊**:
11
+ - CLAUDE.md mindset #1(不取巧)+ #2(消費既有)+ #5(猶豫就問)+ #6(meta 抽象)
12
+ - M8 benchmark / M17 SSOT / M12 binary rule / 治理「加規則前 3 題」
13
+ - 本 skill 是上述 meta 的**propose-time 落地** — meta 寫成文字不夠,要 mechanical workflow 釘住
14
+
15
+ ## When to invoke
16
+
17
+ **強制 invoke** 在以下情境(不靠 user 提醒):
18
+ - 寫「Option A / B / C」「選 A / B」「3 個方向」 類列表
19
+ - 寫「建議做」「該做」「提議」 類 verb
20
+ - 寫「c. d. e.」 候選清單(像本 conv 我給 c hook + d M18 那種)
21
+ - 任何「if you sign-off, I'll do X」 提案
22
+
23
+ **不 invoke**:
24
+ - User 已明示要做 X(只是 execute,不 propose)
25
+ - 純資訊回答(描述現況,不選擇)
26
+ - Bug fix 的 surgical solution(無 option,直接修)
27
+
28
+ ---
29
+
30
+ ## Workflow(強制 7 題,缺一就 reject 此 option)
31
+
32
+ 每個 candidate option 過以下 7 題,inline 寫進回覆:
33
+
34
+ ### Q0 — **Pre-ASK self-verify problem 真存在**(2026-05-18 加,absorbs Sheet/inline-action/SurfaceBody 三題誤判事件)
35
+
36
+ **問**:propose 給 user 拍板前,是否已**grep DS-wide + Read 相關 spec.md / tsx + Read consumer usage** 確認 problem **真存在**?
37
+
38
+ **為何**:M18 / M23 / M29 都管「決策過程紀律」,但**propose 給 user 前的「problem 真存在?」基本判斷**沒 codify。本 session 我 propose 3 題(Sheet 補 / 5 元件 migrate inline-action / 5 元件 migrate SurfaceBody)**全部不是真 problem** — Sheet spec 已完整、inline-action 已全消費、SurfaceBody 有意設計不該動 — 但我 propose 給 user 拍板浪費 user 時間 + 動搖 user 信任。
39
+
40
+ **強制檢查**:
41
+ 1. **grep 既有 code DS-wide** — 「該 migrate 的 X 元件」真沒消費 primitive?(`rg "<primitive>" node_modules/@qijenchen/design-system/src/components/<X>`)
42
+ 2. **Read 相關 spec.md** — spec 有沒有明文 codify 該設計是有意 / 例外 / 合法分支?(本 session 例:Tag inline-action colored host 例外是 spec L52-54 明寫的)
43
+ 3. **Read consumer usage** — 該 pattern 已在 N 處 work fine?N ≥ 3 → 該 pattern 是 working canonical,不是 problem
44
+ 4. **反問**:「如果 user 答 A,我會做什麼?該動 K 個 file?那 K 個 file 真有問題嗎?還是我假設的?」
45
+
46
+ **Fail criteria**(任一命中 → reject propose,不丟給 user):
47
+ - 沒 grep 既有就斷言「N 元件缺 X」
48
+ - 沒讀 spec 就斷言「現況違反 canonical」
49
+ - 「我推 A 因 X 比較統一」但 X 已是合法分支(spec 明文)
50
+ - propose 是 mass-migration 但沒列具體哪 K file file:line 需動
51
+
52
+ **Pass criteria**(全過才能 propose):
53
+ - ✅ 列具體 file:line 證據 problem 存在
54
+ - ✅ 列 spec.md 段落 cite 證明「現況違反 spec」
55
+ - ✅ counter-example scan 跑過:DS 其他元件用一樣 pattern → 反證「這不是 problem」
56
+ - ✅ 給 user 的 option list 含「C. 不動(理由)」且 C 經 grep verify 不是 cheap escape
57
+
58
+ **例**:
59
+ - ✅ "grep 結果 Input/NumberInput/LinkInput 3 file 都未消費 ItemInlineAction(file:line)+ spec.md L60 表格列為 expected consumer → 真 gap"
60
+ - ❌ "5 元件應該 migrate"(沒 grep / 沒 cite spec / 不知道 K 元件已 migrate / 是 colored host 合法例外)
61
+
62
+ **對應 hook**:`check_propose_pre_grep_verify.sh`(2026-05-18 加,Edit/Write `*.md` 內含「propose」/「請拍板」/「決策」keyword 但近 N turn 無 grep/Read tool call → P1 warn)
63
+
64
+ ### Q1 — M8 World-class benchmark
65
+ **問**:本 option ≥ 3 家 world-class DS / framework / canonical 有對照嗎?
66
+ **列**:具體實作名 / API 指向 / docs URL
67
+ **Fail**:< 3 家對照 → option 未成熟,不該 propose
68
+ **例**:
69
+ - ✅ "Polaris IconButton padding-free / Atlassian button-iconOnly p:0 / Material UI MuiSvgIcon flex-shrink:0"
70
+ - ❌ "感覺合理 / 可能對 / 沒查"
71
+
72
+ ### Q1' — **M23 DS internal canonical 優先 grep**(2026-05-03 加,chevron 事件後)
73
+ **先 grep DS 既有 token / variant / pattern 命中?有 → 必對齊,Q1 外部 benchmark 只是輔證。**
74
+ **問**:propose 的 visual decision(color / size / spacing / typography / state)是否已 grep `node_modules/@qijenchen/design-system/src/tokens/` + 近親 component spec/tsx 確認沒命中既有?
75
+ **Fail**:跳過 grep 直接搬 world-class → M23 違反(本 conv chevron 用 Ant 5 家 muted 覆蓋 DS 內 icon-only Button = neutral-9 canonical → user 4 輪糾正)
76
+ **例**:
77
+ - ✅ "grep `text-foreground` 已是 icon-only Button 預設(neutral-9 / 85%)→ 對齊;Ant cite 為輔證"
78
+ - ❌ "Ant / Material muted → 直接套(沒 grep 內部 canonical)"
79
+
80
+ ### Q2 — M17 SSOT 必可傳播
81
+ **問**:本 option 動到的 canonical 有真正可執行 SSOT 嗎(token / primitive / utility)?還是只在 markdown 文字?
82
+ **Fail**:只增加 markdown 文字、沒提供 mechanical enforcement → 假 SSOT
83
+ **例**:
84
+ - ✅ "新 utility class `ICON_ONLY_BASE` 共用,2 host import"
85
+ - ❌ "spec 寫一行 rule,未來誰記得就好"
86
+
87
+ ### Q3 — Rule-of-3 SSOT placement
88
+ **問**:本概念在現有 home 已 ≥ 3 處出現?該選 SSOT,其他 pointer。新加的話,SSOT 該住哪 home?
89
+ **Fail**:concept 已 ≥ 3 處仍要新增 home / 重複描述 → 違 Rule-of-3
90
+ **例**:
91
+ - ✅ "uiSize.spec.md 是 SSOT,button.spec.md / segmented-control.spec.md 1 行 pointer"
92
+ - ❌ "每個 spec 各自寫一份"
93
+
94
+ ### Q4 — M10 下游吸收
95
+ **問**:本 option 加入後,既有哪些 rule / memory / bug case 被吸收可刪?
96
+ **Fail**:純 append 沒 retire,違反「上游加 = 下游減」 + 治理 anti-bloat
97
+ **例**:
98
+ - ✅ "M18 加,M12 部分 overlap 但 scope 不同共存(說明)"
99
+ - ❌ "新加 M18,既有 M-row 全保留(沒檢查)"
100
+
101
+ ### Q5 — Issue list 100% mapped(2026-05-05 anti-drift,user trigger 第 5 次後新增)
102
+ **問**:plan iteration / option list 改版時,user 提的**所有** raised issue 是否 100% mapped 到本版的 step / option / 評估?**未 mapped 的逐條 explicit 標**:`done` / `folded into Step X` / `informational(無實作)` / `dropped(原因)` / `pending`。
103
+ **Fail**:silent drop / 沒 mapping table / fold 進 step 沒 trace
104
+ **例**:
105
+ - ✅ "Issue 1-14 列 mapping table,Issue 3+13 標 informational,其他 11 條 mapped"
106
+ - ❌ "改版只列新 Step,沒 walk-through user 之前提的 issue list"
107
+
108
+ ---
109
+
110
+ ## Workflow Output Format
111
+
112
+ 對 user 回覆中的 option list 必含 **inline 7-Q 表 + Issue mapping**(plan iteration 場景):
113
+
114
+ ```markdown
115
+ | 選項 | M23 DS grep | M8 benchmark | M17 SSOT | Rule-of-3 | M10 下游 | Issue cover | 結論 |
116
+ |---|---|---|---|---|---|---|---|
117
+ | A | DS 已有 X token,對齊 | Polaris/Atlassian/Material 輔證 | 抽 utility 共用 | 0 處 SSOT 新增 OK | 可刪 X 條冗餘 | covers 8/14 | **PASS,推薦** |
118
+ | B | 沒 grep | 只查 1 家 | 純 markdown rule | 已 3 處,無新 SSOT 動 | 純 append 沒 retire | covers 4/14 | **REJECT(M23+M8 雙 fail + Q5 不全)** |
119
+ ```
120
+
121
+ **Plan iteration 必含 Issue ↔ Step 完整 mapping table**(不可只列新 step 表,user 看不到原 issue trace):
122
+ ```markdown
123
+ | # | Issue (按 user 提出順序) | 處理 |
124
+ |---|---|---|
125
+ | 1 | <user 原文 issue> | Step X / informational / dropped(reason) |
126
+ | ... | ... | ... |
127
+ ```
128
+
129
+ **所有 fail 過 7-Q 的 option 必明示 reject + 原因**,不只 list 不過的。User 看見 reject 過程才能信 propose 過原則。
130
+
131
+ ---
132
+
133
+ ## Edge cases
134
+
135
+ ### 緊急 / surgical bug fix
136
+ 不需走全 7 題(沒 option list,直接修)。但 commit message 仍應簡述「修法已知 root cause + 不取巧」(對齊 mindset #1)。
137
+
138
+ ### Option 內含 sub-option(nested)
139
+ 每層各自跑 7 題。Skill 不限深度但實作上 ≥ 3 層 nested 已是設計問題,user 該停下重整。
140
+
141
+ ### User 已明示要 X(非 propose)
142
+ 不跑 skill。直接執行。
143
+
144
+ ---
145
+
146
+ ## 為什麼這 skill 必要(本 session 教訓)
147
+
148
+ User 已就「為什麼會給錯誤建議」糾正 ≥ 3 次:
149
+ - session 初:G6/G7/G8 推力,我自己沒 dogfood test → 第 3 次問才補
150
+ - 中:c hook + d M18-inner-area propose,**user sign-off 前剛好我自己覺察跑 7-Q 才撤回**
151
+ - 末:user 直接質問「為什麼會給錯誤建議?如果我答應了會直接執行嗎?」(本 skill 的觸發)
152
+
153
+ **Infra G6/G7/G8 是 post-edit / session-start 防線,沒 propose-time gate**。Claude Code event model 沒 OnAssistantMessage hook,**只能靠 model-runtime 紀律 + skill self-invoke**。本 skill 就是 mechanical 補位 — invoke 時讀本檔,7-Q 表格自然寫進回覆。
154
+
155
+ ---
156
+
157
+ ## Self-improvement capture
158
+
159
+ 每次 invoke 完,session 結束前自問:
160
+ - (a) 是否每個 option 真跑了 7-Q 還是糊弄填表?
161
+ - (b) 是否有 reject option 曾被 list?(reject 不該被列出)
162
+ - (c) 是否 user 仍質疑 propose 品質?(若是 → 7-Q 沒抓到的 gap → 加 Q5)
163
+
164
+ 回填到本 SKILL.md 或 CLAUDE.md M18(若需 escalate)。
165
+
166
+ ---
167
+
168
+ ## 與其他 skill 對位
169
+
170
+ | Skill | scope |
171
+ |---|---|
172
+ | `pre_write_subsumption_check.sh`(hook)| Edit/Write 已發生時 |
173
+ | `post_edit_canonical_interrogate.sh`(retired/未實作 — mindset enforcement)| 寫完 canonical 後 3 題 |
174
+ | `check_governance_compliance.sh`(retired/未實作 — 靠 `check_propose_pre_grep_verify.sh` + 加 hook 前 3 題)| 寫新 hook 7 題 |
175
+ | **本 skill** `/propose-options` | **propose-time(寫進 user 回覆前)7 題** |
176
+
177
+ 4 個正交 — propose 前 / write 前 / write 中 / write 後 全 cover。