@qijenchen/design-system 0.1.0-beta.82 → 0.1.0-beta.84

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 (612) hide show
  1. package/CLAUDE.md +8 -8
  2. package/README.md +3 -2
  3. package/dist/components/Alert/alert.js.map +1 -1
  4. package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
  5. package/dist/components/AppShell/app-shell.d.ts +1 -1
  6. package/dist/components/AppShell/app-shell.d.ts.map +1 -1
  7. package/dist/components/AppShell/app-shell.js +22 -2
  8. package/dist/components/AppShell/app-shell.js.map +1 -1
  9. package/dist/components/Avatar/avatar.d.ts.map +1 -1
  10. package/dist/components/Avatar/avatar.js +4 -4
  11. package/dist/components/Avatar/avatar.js.map +1 -1
  12. package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
  13. package/dist/components/Breadcrumb/breadcrumb.js +1 -1
  14. package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
  15. package/dist/components/Button/button.d.ts +2 -2
  16. package/dist/components/Button/button.d.ts.map +1 -1
  17. package/dist/components/Button/button.js +12 -3
  18. package/dist/components/Button/button.js.map +1 -1
  19. package/dist/components/Calendar/calendar.d.ts +13 -5
  20. package/dist/components/Calendar/calendar.d.ts.map +1 -1
  21. package/dist/components/Calendar/calendar.js +7 -1
  22. package/dist/components/Calendar/calendar.js.map +1 -1
  23. package/dist/components/Carousel/carousel.d.ts.map +1 -1
  24. package/dist/components/Carousel/carousel.js +8 -3
  25. package/dist/components/Carousel/carousel.js.map +1 -1
  26. package/dist/components/Chart/chart.d.ts.map +1 -1
  27. package/dist/components/Chart/chart.js +1 -0
  28. package/dist/components/Chart/chart.js.map +1 -1
  29. package/dist/components/Checkbox/checkbox.d.ts +1 -1
  30. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  31. package/dist/components/Checkbox/checkbox.js +8 -4
  32. package/dist/components/Checkbox/checkbox.js.map +1 -1
  33. package/dist/components/Chip/chip.d.ts +1 -1
  34. package/dist/components/Chip/chip.d.ts.map +1 -1
  35. package/dist/components/Chip/chip.js.map +1 -1
  36. package/dist/components/Coachmark/coachmark.d.ts +10 -3
  37. package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
  38. package/dist/components/Coachmark/coachmark.js.map +1 -1
  39. package/dist/components/Combobox/combobox.d.ts +5 -1
  40. package/dist/components/Combobox/combobox.d.ts.map +1 -1
  41. package/dist/components/Combobox/combobox.js +30 -13
  42. package/dist/components/Combobox/combobox.js.map +1 -1
  43. package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
  44. package/dist/components/DataTable/cell-registry.js +53 -62
  45. package/dist/components/DataTable/cell-registry.js.map +1 -1
  46. package/dist/components/DataTable/column-types.d.ts +10 -4
  47. package/dist/components/DataTable/column-types.d.ts.map +1 -1
  48. package/dist/components/DataTable/column-types.js.map +1 -1
  49. package/dist/components/DataTable/data-table-column-visibility-panel.d.ts +1 -1
  50. package/dist/components/DataTable/data-table-column-visibility-panel.js +183 -0
  51. package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -0
  52. package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
  53. package/dist/components/DataTable/data-table-filter-panel.js +607 -0
  54. package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
  55. package/dist/components/DataTable/data-table-interaction-layer.d.ts +11 -15
  56. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
  57. package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
  58. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  59. package/dist/components/DataTable/data-table-sort-manager.js +140 -0
  60. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
  61. package/dist/components/DataTable/data-table.d.ts +5 -6
  62. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  63. package/dist/components/DataTable/data-table.js +36 -15
  64. package/dist/components/DataTable/data-table.js.map +1 -1
  65. package/dist/components/DataTable/filter-operators.js +140 -0
  66. package/dist/components/DataTable/filter-operators.js.map +1 -0
  67. package/dist/components/DataTable/filter-tree.js +312 -0
  68. package/dist/components/DataTable/filter-tree.js.map +1 -0
  69. package/dist/components/DataTable/index.d.ts +3 -0
  70. package/dist/components/DataTable/index.d.ts.map +1 -1
  71. package/dist/components/DataTable/index.js +12 -1
  72. package/dist/components/DataTable/index.js.map +1 -1
  73. package/dist/components/DataTable/lib/column-meta.js +25 -0
  74. package/dist/components/DataTable/lib/column-meta.js.map +1 -0
  75. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  76. package/dist/components/DateGrid/date-grid.js +3 -1
  77. package/dist/components/DateGrid/date-grid.js.map +1 -1
  78. package/dist/components/DatePicker/date-picker.d.ts +7 -1
  79. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  80. package/dist/components/DatePicker/date-picker.js +105 -74
  81. package/dist/components/DatePicker/date-picker.js.map +1 -1
  82. package/dist/components/Dialog/dialog.d.ts +20 -3
  83. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  84. package/dist/components/Dialog/dialog.js +38 -20
  85. package/dist/components/Dialog/dialog.js.map +1 -1
  86. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  87. package/dist/components/DropdownMenu/dropdown-menu.js +3 -1
  88. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  89. package/dist/components/Field/field-context.d.ts +45 -5
  90. package/dist/components/Field/field-context.d.ts.map +1 -1
  91. package/dist/components/Field/field-context.js +19 -0
  92. package/dist/components/Field/field-context.js.map +1 -1
  93. package/dist/components/Field/field-edit-keys.d.ts +21 -0
  94. package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
  95. package/dist/components/Field/field-edit-keys.js +19 -0
  96. package/dist/components/Field/field-edit-keys.js.map +1 -0
  97. package/dist/components/Field/field-types.d.ts +20 -1
  98. package/dist/components/Field/field-types.d.ts.map +1 -1
  99. package/dist/components/Field/field-types.js.map +1 -1
  100. package/dist/components/Field/field-wrapper.d.ts +3 -2
  101. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  102. package/dist/components/Field/field-wrapper.js +38 -39
  103. package/dist/components/Field/field-wrapper.js.map +1 -1
  104. package/dist/components/Field/field.d.ts +2 -1
  105. package/dist/components/Field/field.d.ts.map +1 -1
  106. package/dist/components/Field/field.js.map +1 -1
  107. package/dist/components/FieldControlGroup/field-control-group.d.ts +1 -1
  108. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
  109. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  110. package/dist/components/FileItem/file-item.js +1 -1
  111. package/dist/components/FileItem/file-item.js.map +1 -1
  112. package/dist/components/FileUpload/file-upload.d.ts +1 -1
  113. package/dist/components/FileUpload/file-upload.js.map +1 -1
  114. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  115. package/dist/components/FileViewer/file-viewer.js +7 -2
  116. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  117. package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
  118. package/dist/components/FileViewer/image-renderer.js +22 -1
  119. package/dist/components/FileViewer/image-renderer.js.map +1 -1
  120. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  121. package/dist/components/HoverCard/hover-card.js +5 -3
  122. package/dist/components/HoverCard/hover-card.js.map +1 -1
  123. package/dist/components/InlineEdit/index.d.ts +2 -0
  124. package/dist/components/InlineEdit/index.d.ts.map +1 -0
  125. package/dist/components/InlineEdit/index.js +5 -0
  126. package/dist/components/InlineEdit/index.js.map +1 -0
  127. package/dist/components/InlineEdit/inline-edit.d.ts +59 -0
  128. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
  129. package/dist/components/InlineEdit/inline-edit.js +164 -0
  130. package/dist/components/InlineEdit/inline-edit.js.map +1 -0
  131. package/dist/components/Input/input.d.ts +6 -11
  132. package/dist/components/Input/input.d.ts.map +1 -1
  133. package/dist/components/Input/input.js +43 -13
  134. package/dist/components/Input/input.js.map +1 -1
  135. package/dist/components/LinkInput/link-input.d.ts +2 -2
  136. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  137. package/dist/components/LinkInput/link-input.js +6 -5
  138. package/dist/components/LinkInput/link-input.js.map +1 -1
  139. package/dist/components/Menu/menu-item.d.ts +14 -2
  140. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  141. package/dist/components/Menu/menu-item.js +25 -3
  142. package/dist/components/Menu/menu-item.js.map +1 -1
  143. package/dist/components/NumberInput/number-input.d.ts +3 -3
  144. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  145. package/dist/components/NumberInput/number-input.js +6 -5
  146. package/dist/components/NumberInput/number-input.js.map +1 -1
  147. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  148. package/dist/components/OverflowIndicator/overflow-indicator.js +2 -6
  149. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  150. package/dist/components/Pagination/pagination.js +1 -1
  151. package/dist/components/Pagination/pagination.js.map +1 -1
  152. package/dist/components/PeoplePicker/index.js +7 -1
  153. package/dist/components/PeoplePicker/index.js.map +1 -1
  154. package/dist/components/PeoplePicker/people-picker.d.ts +9 -2
  155. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  156. package/dist/components/PeoplePicker/people-picker.js +23 -10
  157. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  158. package/dist/components/PeoplePicker/person-display.d.ts +6 -3
  159. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  160. package/dist/components/PeoplePicker/person-display.js +19 -14
  161. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  162. package/dist/components/Popover/popover.d.ts.map +1 -1
  163. package/dist/components/Popover/popover.js +3 -1
  164. package/dist/components/Popover/popover.js.map +1 -1
  165. package/dist/components/ProfileCard/profile-card.d.ts +2 -2
  166. package/dist/components/ProfileCard/profile-card.js +3 -3
  167. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  168. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  169. package/dist/components/RadioGroup/radio-group.js +15 -9
  170. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  171. package/dist/components/ScrollArea/scroll-area.d.ts +11 -1
  172. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
  173. package/dist/components/ScrollArea/scroll-area.js +6 -3
  174. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  175. package/dist/components/Select/select.d.ts +46 -5
  176. package/dist/components/Select/select.d.ts.map +1 -1
  177. package/dist/components/Select/select.js +109 -28
  178. package/dist/components/Select/select.js.map +1 -1
  179. package/dist/components/SelectMenu/select-menu.d.ts +3 -1
  180. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  181. package/dist/components/SelectMenu/select-menu.js +8 -1
  182. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  183. package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
  184. package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
  185. package/dist/components/SelectionControl/boolean-value.js +23 -0
  186. package/dist/components/SelectionControl/boolean-value.js.map +1 -0
  187. package/dist/components/SelectionControl/index.d.ts +1 -0
  188. package/dist/components/SelectionControl/index.d.ts.map +1 -1
  189. package/dist/components/SelectionControl/index.js +2 -0
  190. package/dist/components/SelectionControl/index.js.map +1 -1
  191. package/dist/components/Sheet/index.js +2 -1
  192. package/dist/components/Sheet/sheet.d.ts +7 -1
  193. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  194. package/dist/components/Sheet/sheet.js +5 -2
  195. package/dist/components/Sheet/sheet.js.map +1 -1
  196. package/dist/components/Sidebar/sidebar.d.ts +9 -4
  197. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  198. package/dist/components/Sidebar/sidebar.js +8 -10
  199. package/dist/components/Sidebar/sidebar.js.map +1 -1
  200. package/dist/components/Slider/slider.d.ts.map +1 -1
  201. package/dist/components/Slider/slider.js.map +1 -1
  202. package/dist/components/Switch/switch.d.ts +6 -6
  203. package/dist/components/Switch/switch.d.ts.map +1 -1
  204. package/dist/components/Switch/switch.js +3 -2
  205. package/dist/components/Switch/switch.js.map +1 -1
  206. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  207. package/dist/components/Tabs/tabs.js +15 -1
  208. package/dist/components/Tabs/tabs.js.map +1 -1
  209. package/dist/components/Textarea/textarea.d.ts +2 -2
  210. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  211. package/dist/components/Textarea/textarea.js +50 -42
  212. package/dist/components/Textarea/textarea.js.map +1 -1
  213. package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
  214. package/dist/components/TimePicker/time-columns.js +42 -38
  215. package/dist/components/TimePicker/time-columns.js.map +1 -1
  216. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  217. package/dist/components/TimePicker/time-picker.js +8 -6
  218. package/dist/components/TimePicker/time-picker.js.map +1 -1
  219. package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
  220. package/dist/components/Tooltip/tooltip.js +7 -5
  221. package/dist/components/Tooltip/tooltip.js.map +1 -1
  222. package/dist/components/TreeView/tree-view.d.ts +56 -1
  223. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  224. package/dist/components/TreeView/tree-view.js +211 -12
  225. package/dist/components/TreeView/tree-view.js.map +1 -1
  226. package/dist/index.d.ts +115 -58
  227. package/dist/index.d.ts.map +1 -1
  228. package/dist/index.js +93 -108
  229. package/dist/index.js.map +1 -1
  230. package/dist/patterns/element-anatomy/item-anatomy.d.ts +7 -6
  231. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  232. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  233. package/dist/tokens/categorical-color.js +15 -0
  234. package/dist/tokens/categorical-color.js.map +1 -1
  235. package/dist/tokens/motion/motion.d.ts +7 -6
  236. package/dist/tokens/motion/motion.d.ts.map +1 -1
  237. package/dist/tokens/motion/motion.js +6 -6
  238. package/dist/tokens/motion/motion.js.map +1 -1
  239. package/dist/tokens/motion/overlay-motion.d.ts +19 -0
  240. package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
  241. package/dist/tokens/motion/overlay-motion.js +9 -0
  242. package/dist/tokens/motion/overlay-motion.js.map +1 -0
  243. package/dist/tokens/uiSize/icon-size.js +5 -0
  244. package/dist/tokens/uiSize/icon-size.js.map +1 -0
  245. package/ds-canonical/fork/governance.lock +37 -19
  246. package/ds-canonical/fork/hooks/_log-fire.sh +46 -0
  247. package/ds-canonical/fork/hooks/block_prototype_imports.py +15 -4
  248. package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +145 -13
  249. package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +17 -5
  250. package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +47 -0
  251. package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +27 -0
  252. package/ds-canonical/fork/hooks/check_field_family_invariants.sh +61 -1
  253. package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +28 -4
  254. package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +36 -0
  255. package/ds-canonical/fork/hooks/check_story_determinism.sh +39 -0
  256. package/ds-canonical/fork/hooks/check_story_invariants.sh +119 -0
  257. package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  258. package/ds-canonical/fork/manifest.json +20 -0
  259. package/ds-canonical/fork/preamble.md +22 -18
  260. package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +9 -3
  261. package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
  262. package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +7 -0
  263. package/ds-canonical/fork/skills/performance-audit/SKILL.md +4 -2
  264. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
  265. package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
  266. package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
  267. package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
  268. package/ds-canonical/fork/skills/visual-audit/SKILL.md +10 -2
  269. package/ds-canonical/hooks/README.md +1 -1
  270. package/ds-canonical/hooks/block_prototype_imports.py +15 -4
  271. package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
  272. package/ds-canonical/hooks/check_benchmark_citation.sh +5 -3
  273. package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
  274. package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
  275. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +17 -5
  276. package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
  277. package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
  278. package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
  279. package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
  280. package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
  281. package/ds-canonical/hooks/check_opacity_token_usage.sh +36 -0
  282. package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
  283. package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
  284. package/ds-canonical/hooks/check_propose_without_benchmark.sh +6 -2
  285. package/ds-canonical/hooks/check_ssot_header_declaration.sh +55 -0
  286. package/ds-canonical/hooks/check_story_determinism.sh +39 -0
  287. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
  288. package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  289. package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
  290. package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
  291. package/ds-canonical/hooks/stop_self_audit.sh +31 -0
  292. package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
  293. package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
  294. package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +3 -3
  295. package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
  296. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
  297. package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
  298. package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
  299. package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
  300. package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
  301. package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +3 -1
  302. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +41 -2
  303. package/ds-canonical/hooks/tests/test_check_ssot_header_declaration.sh +72 -0
  304. package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
  305. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
  306. package/ds-canonical/references/build-ui-canonicals.md +2 -1
  307. package/ds-canonical/references/failure-class-registry.json +145 -0
  308. package/ds-canonical/references/governance-audit-coverage.md +33 -0
  309. package/ds-canonical/references/item-anatomy-recipe.md +2 -2
  310. package/ds-canonical/references/scenario-definition.md +6 -9
  311. package/ds-canonical/references/ssot-consultation.md +2 -2
  312. package/ds-canonical/references/ssot-index.md +5 -4
  313. package/ds-canonical/references/story-baseline-registry.json +8 -2
  314. package/ds-canonical/references/structural-token-retention.md +6 -9
  315. package/ds-canonical/rules/meta-patterns.md +8 -8
  316. package/ds-canonical/rules/self-verify.md +4 -3
  317. package/ds-canonical/rules/spec-rules.md +1 -1
  318. package/ds-canonical/rules/story-rules.md +2 -2
  319. package/ds-canonical/rules/ui-development.md +4 -2
  320. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +9 -3
  321. package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
  322. package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
  323. package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
  324. package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
  325. package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
  326. package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
  327. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +57 -68
  328. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
  329. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
  330. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
  331. package/ds-canonical/skills/delivery-handoff/SKILL.md +5 -0
  332. package/ds-canonical/skills/design-system-audit/SKILL.md +27 -26
  333. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
  334. package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
  335. package/ds-canonical/skills/governance-health/SKILL.md +2 -1
  336. package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
  337. package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
  338. package/ds-canonical/skills/new-component/SKILL.md +7 -5
  339. package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
  340. package/ds-canonical/skills/performance-audit/SKILL.md +2 -2
  341. package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
  342. package/ds-canonical/skills/propose-options/SKILL.md +3 -3
  343. package/ds-canonical/skills/prototype/SKILL.md +1 -1
  344. package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
  345. package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
  346. package/ds-canonical/skills/story-writing/SKILL.md +3 -3
  347. package/ds-canonical/skills/visual-audit/SKILL.md +10 -2
  348. package/ds-story-manifest.json +29 -20
  349. package/llms-full.txt +22 -1
  350. package/llms.txt +5 -4
  351. package/package.json +7 -3
  352. package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
  353. package/src/components/Accordion/accordion.stories.tsx +16 -1
  354. package/src/components/Alert/alert.principles.stories.tsx +1 -1
  355. package/src/components/Alert/alert.spec.md +8 -10
  356. package/src/components/Alert/alert.stories.tsx +28 -28
  357. package/src/components/Alert/alert.tsx +1 -1
  358. package/src/components/AppShell/_demo-helpers.tsx +6 -3
  359. package/src/components/AppShell/app-shell.spec.md +4 -4
  360. package/src/components/AppShell/app-shell.tsx +28 -2
  361. package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
  362. package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
  363. package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
  364. package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
  365. package/src/components/Avatar/avatar.spec.md +2 -2
  366. package/src/components/Avatar/avatar.stories.tsx +8 -6
  367. package/src/components/Avatar/avatar.tsx +13 -5
  368. package/src/components/Badge/badge.principles.stories.tsx +1 -1
  369. package/src/components/Badge/badge.spec.md +2 -0
  370. package/src/components/Badge/badge.stories.tsx +4 -2
  371. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
  372. package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
  373. package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
  374. package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
  375. package/src/components/Button/button.principles.stories.tsx +1 -1
  376. package/src/components/Button/button.spec.md +2 -2
  377. package/src/components/Button/button.tsx +18 -3
  378. package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
  379. package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
  380. package/src/components/Calendar/calendar.spec.md +5 -4
  381. package/src/components/Calendar/calendar.stories.tsx +7 -4
  382. package/src/components/Calendar/calendar.tsx +26 -7
  383. package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
  384. package/src/components/Carousel/carousel.spec.md +2 -2
  385. package/src/components/Carousel/carousel.tsx +11 -3
  386. package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
  387. package/src/components/Chart/chart.principles.stories.tsx +1 -1
  388. package/src/components/Chart/chart.stories.tsx +2 -8
  389. package/src/components/Chart/chart.tsx +3 -0
  390. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
  391. package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
  392. package/src/components/Checkbox/checkbox.spec.md +11 -26
  393. package/src/components/Checkbox/checkbox.stories.tsx +11 -8
  394. package/src/components/Checkbox/checkbox.tsx +18 -13
  395. package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
  396. package/src/components/Chip/chip.principles.stories.tsx +1 -1
  397. package/src/components/Chip/chip.spec.md +5 -4
  398. package/src/components/Chip/chip.tsx +5 -1
  399. package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
  400. package/src/components/CircularProgress/circular-progress.spec.md +3 -3
  401. package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
  402. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
  403. package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
  404. package/src/components/Coachmark/coachmark.spec.md +5 -5
  405. package/src/components/Coachmark/coachmark.stories.tsx +3 -1
  406. package/src/components/Coachmark/coachmark.tsx +10 -3
  407. package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
  408. package/src/components/Combobox/combobox.tsx +53 -19
  409. package/src/components/Command/command.anatomy.stories.tsx +2 -2
  410. package/src/components/Command/command.principles.stories.tsx +1 -1
  411. package/src/components/Command/command.stories.tsx +42 -10
  412. package/src/components/DataTable/cell-registry.tsx +86 -63
  413. package/src/components/DataTable/column-types.ts +10 -1
  414. package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
  415. package/src/components/DataTable/data-table-filter-panel.tsx +4 -1
  416. package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
  417. package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
  418. package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
  419. package/src/components/DataTable/data-table.spec.md +32 -12
  420. package/src/components/DataTable/data-table.stories.tsx +16 -17
  421. package/src/components/DataTable/data-table.tsx +103 -60
  422. package/src/components/DataTable/index.ts +3 -0
  423. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
  424. package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
  425. package/src/components/DateGrid/date-grid.spec.md +1 -1
  426. package/src/components/DateGrid/date-grid.tsx +3 -1
  427. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
  428. package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
  429. package/src/components/DatePicker/date-picker.spec.md +3 -3
  430. package/src/components/DatePicker/date-picker.stories.tsx +4 -5
  431. package/src/components/DatePicker/date-picker.tsx +99 -45
  432. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
  433. package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
  434. package/src/components/DescriptionList/description-list.spec.md +3 -3
  435. package/src/components/DescriptionList/description-list.stories.tsx +7 -6
  436. package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
  437. package/src/components/Dialog/dialog.spec.md +9 -0
  438. package/src/components/Dialog/dialog.stories.tsx +66 -5
  439. package/src/components/Dialog/dialog.tsx +60 -25
  440. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
  441. package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
  442. package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
  443. package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
  444. package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
  445. package/src/components/Empty/empty.spec.md +2 -2
  446. package/src/components/Field/field-context.ts +69 -5
  447. package/src/components/Field/field-controls.spec.md +62 -8
  448. package/src/components/Field/field-edit-keys.ts +66 -0
  449. package/src/components/Field/field-types.ts +58 -9
  450. package/src/components/Field/field-wrapper.tsx +50 -42
  451. package/src/components/Field/field.anatomy.stories.tsx +9 -6
  452. package/src/components/Field/field.spec.md +1 -1
  453. package/src/components/Field/field.stories.tsx +1 -1
  454. package/src/components/Field/field.tsx +2 -1
  455. package/src/components/Field/form-validation.spec.md +3 -3
  456. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
  457. package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
  458. package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
  459. package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
  460. package/src/components/FileItem/file-item.spec.md +14 -8
  461. package/src/components/FileItem/file-item.stories.tsx +36 -25
  462. package/src/components/FileItem/file-item.tsx +8 -6
  463. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
  464. package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
  465. package/src/components/FileUpload/file-upload.spec.md +1 -1
  466. package/src/components/FileUpload/file-upload.tsx +1 -1
  467. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
  468. package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
  469. package/src/components/FileViewer/file-viewer.spec.md +30 -12
  470. package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
  471. package/src/components/FileViewer/file-viewer.tsx +12 -4
  472. package/src/components/FileViewer/image-renderer.tsx +35 -7
  473. package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
  474. package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
  475. package/src/components/HoverCard/hover-card.spec.md +5 -5
  476. package/src/components/HoverCard/hover-card.stories.tsx +16 -16
  477. package/src/components/HoverCard/hover-card.tsx +5 -3
  478. package/src/components/InlineEdit/index.ts +5 -0
  479. package/src/components/InlineEdit/inline-edit.spec.md +149 -0
  480. package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
  481. package/src/components/InlineEdit/inline-edit.tsx +287 -0
  482. package/src/components/Input/input.anatomy.stories.tsx +8 -7
  483. package/src/components/Input/input.principles.stories.tsx +2 -12
  484. package/src/components/Input/input.spec.md +13 -18
  485. package/src/components/Input/input.tsx +69 -22
  486. package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
  487. package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
  488. package/src/components/LinkInput/link-input.tsx +11 -10
  489. package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
  490. package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
  491. package/src/components/Menu/menu-item.spec.md +22 -15
  492. package/src/components/Menu/menu-item.stories.tsx +39 -11
  493. package/src/components/Menu/menu-item.tsx +38 -4
  494. package/src/components/Notice/notice.principles.stories.tsx +1 -1
  495. package/src/components/Notice/notice.spec.md +16 -3
  496. package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
  497. package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
  498. package/src/components/NumberInput/number-input.spec.md +4 -4
  499. package/src/components/NumberInput/number-input.tsx +19 -12
  500. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
  501. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
  502. package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
  503. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
  504. package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
  505. package/src/components/Pagination/pagination.spec.md +1 -1
  506. package/src/components/Pagination/pagination.stories.tsx +2 -6
  507. package/src/components/Pagination/pagination.tsx +1 -1
  508. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
  509. package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
  510. package/src/components/PeoplePicker/people-picker.spec.md +6 -6
  511. package/src/components/PeoplePicker/people-picker.tsx +56 -16
  512. package/src/components/PeoplePicker/person-display.tsx +32 -16
  513. package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
  514. package/src/components/Popover/popover.tsx +3 -1
  515. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
  516. package/src/components/ProfileCard/profile-card.spec.md +3 -3
  517. package/src/components/ProfileCard/profile-card.tsx +6 -6
  518. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
  519. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
  520. package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
  521. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
  522. package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
  523. package/src/components/RadioGroup/radio-group.tsx +41 -15
  524. package/src/components/Rating/rating.spec.md +11 -3
  525. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  526. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
  527. package/src/components/ScrollArea/scroll-area.spec.md +7 -3
  528. package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
  529. package/src/components/ScrollArea/scroll-area.tsx +17 -4
  530. package/src/components/Select/select.anatomy.stories.tsx +3 -3
  531. package/src/components/Select/select.spec.md +27 -17
  532. package/src/components/Select/select.stories.tsx +33 -0
  533. package/src/components/Select/select.tsx +190 -36
  534. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
  535. package/src/components/SelectMenu/select-menu.spec.md +15 -7
  536. package/src/components/SelectMenu/select-menu.tsx +16 -3
  537. package/src/components/SelectionControl/boolean-value.tsx +39 -0
  538. package/src/components/SelectionControl/index.ts +1 -0
  539. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
  540. package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
  541. package/src/components/SelectionControl/selection-item.spec.md +3 -3
  542. package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
  543. package/src/components/Separator/separator.spec.md +2 -2
  544. package/src/components/Separator/separator.stories.tsx +6 -27
  545. package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
  546. package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
  547. package/src/components/Sheet/sheet.spec.md +2 -2
  548. package/src/components/Sheet/sheet.tsx +9 -5
  549. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
  550. package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
  551. package/src/components/Sidebar/sidebar.spec.md +13 -15
  552. package/src/components/Sidebar/sidebar.stories.tsx +8 -7
  553. package/src/components/Sidebar/sidebar.tsx +37 -25
  554. package/src/components/Skeleton/skeleton.stories.tsx +4 -11
  555. package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
  556. package/src/components/Slider/slider.principles.stories.tsx +2 -2
  557. package/src/components/Slider/slider.spec.md +5 -5
  558. package/src/components/Slider/slider.tsx +3 -1
  559. package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
  560. package/src/components/Steps/steps.principles.stories.tsx +1 -1
  561. package/src/components/Steps/steps.spec.md +1 -1
  562. package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
  563. package/src/components/Switch/switch.principles.stories.tsx +4 -4
  564. package/src/components/Switch/switch.spec.md +8 -8
  565. package/src/components/Switch/switch.stories.tsx +9 -24
  566. package/src/components/Switch/switch.tsx +17 -13
  567. package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
  568. package/src/components/Tabs/tabs.spec.md +1 -1
  569. package/src/components/Tabs/tabs.tsx +21 -1
  570. package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
  571. package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
  572. package/src/components/Textarea/textarea.spec.md +4 -4
  573. package/src/components/Textarea/textarea.tsx +72 -46
  574. package/src/components/TimePicker/time-columns.tsx +6 -2
  575. package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
  576. package/src/components/TimePicker/time-picker.spec.md +3 -3
  577. package/src/components/TimePicker/time-picker.tsx +16 -10
  578. package/src/components/Toast/toast.stories.tsx +7 -4
  579. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
  580. package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
  581. package/src/components/Tooltip/tooltip.spec.md +1 -1
  582. package/src/components/Tooltip/tooltip.stories.tsx +4 -39
  583. package/src/components/Tooltip/tooltip.tsx +8 -6
  584. package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
  585. package/src/components/TreeView/tree-view.spec.md +42 -11
  586. package/src/components/TreeView/tree-view.stories.tsx +1 -0
  587. package/src/components/TreeView/tree-view.tsx +322 -17
  588. package/src/index.ts +584 -60
  589. package/src/patterns/action-bar/action-bar.spec.md +9 -0
  590. package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
  591. package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
  592. package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
  593. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
  594. package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
  595. package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
  596. package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
  597. package/src/styles/tokens.css +3 -0
  598. package/src/tokens/README.md +1 -1
  599. package/src/tokens/color/color.spec.md +3 -3
  600. package/src/tokens/color/color.stories.tsx +3 -3
  601. package/src/tokens/density/density.stories.tsx +16 -3
  602. package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
  603. package/src/tokens/motion/motion.css +33 -21
  604. package/src/tokens/motion/motion.spec.md +32 -15
  605. package/src/tokens/motion/motion.stories.tsx +58 -5
  606. package/src/tokens/motion/motion.ts +7 -6
  607. package/src/tokens/motion/overlay-motion.ts +26 -0
  608. package/src/tokens/orphan-tokens.spec.md +4 -4
  609. package/src/tokens/token-system.spec.md +1 -0
  610. package/src/tokens/uiSize/uiSize.spec.md +1 -1
  611. package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
  612. package/src/tokens/utility-registry.json +160 -23
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # Hook(PreToolUse Edit/Write/MultiEdit):spec.md / .tsx in packages/design-system/src/
5
5
  # 含 world-class benchmark claim(Ant / Material / Polaris ...)必附 inline citation
6
- # (URL / GitHub #L / snapshots/ / @benchmark-unverified)。違 P1 soft warn(exit 1)。
6
+ # (URL / GitHub #L / snapshots/ / @benchmark-unverified)。違 P0 BLOCKER(exit 2,2026-07-07 方向 2 升級;escape marker 既有)。
7
7
  # 整檔 escape:前 5 行含 @benchmark-citation-allow: 或 @benchmark-unverified-blanket:。
8
8
 
9
9
  set -u
@@ -45,10 +45,10 @@ expect_pass_silent() {
45
45
 
46
46
  expect_warn() {
47
47
  local name="$1"; local needle="$2"
48
- if [ "$EXIT" = "1" ] && echo "$STDERR_TEXT" | grep -qF "$needle"; then
48
+ if [ "$EXIT" = "2" ] && echo "$STDERR_TEXT" | grep -qF "$needle"; then
49
49
  echo " PASS $name"; PASS=$((PASS+1))
50
50
  else
51
- echo " FAIL $name (expected exit=1 + needle '$needle', got exit $EXIT)"
51
+ echo " FAIL $name (expected exit=2 + needle '$needle', got exit $EXIT)"
52
52
  echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
53
53
  FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
54
54
  fi
@@ -8,8 +8,9 @@
8
8
  # · bare mention(`ls .../codex` / `mycodex exec` / git commit msg 含 "codex")→ silent
9
9
  # · `--help` / `--version` 等 introspection flag → silent
10
10
  # - 命中 codex exec/review → 擷取 brief content(cat-pipe / $(cat) / stdin `<` / inline arg)
11
- # - Brief 必含 4 invariant keyword,缺任一 → exit 2 BLOCKER:
11
+ # - Brief 必含 7 invariant keyword,缺任一 → exit 2 BLOCKER:
12
12
  # 1️⃣ 全盤閱讀 2️⃣ Triple-verify 3️⃣ 禁抽樣 4️⃣ 禁列檔
13
+ # 5️⃣ 輸入對等(A.0 鏡射錨點) 6️⃣ 判準對等(audit-prompts rubric) 7️⃣ A.1b(per-component claim-vs-code)
13
14
  # - Escape:brief 含 `@codex-brief-invariant-skip:` → silent exit 0
14
15
  #
15
16
  # Positive(should BLOCK exit 2):缺 invariant 的 brief。
@@ -48,6 +49,9 @@ cat > "$GOOD_BRIEF" <<'EOF'
48
49
  2. triple-verify per finding(grep + Read + canonical exception check)
49
50
  3. 禁抽樣 — DS-wide ALL files,sub-agent sampled = reject
50
51
  4. 禁列檔 — 只讀 12 file,直接出 verdict
52
+ 5. 閱讀清單鏡射 A.0:CLAUDE.md + .claude/rules/meta-patterns.md 等 5 rules + 4 references + 全 spec.md + memory MEMORY.md index
53
+ 6. 判準對等:codex 讀 design-system-audit/references/audit-prompts.md 每 dim rubric,逐 dim 套用
54
+ 7. A.1b per-component claim-vs-code 對抗驗證:讀每元件 .tsx + wrap lib 逐句驗宣稱
51
55
  EOF
52
56
 
53
57
  # Partial brief:缺 invariant 3(禁抽樣);其餘 3 個 keyword 齊
@@ -146,7 +150,7 @@ run_hook "git commit -m \"${CX} collab notes\""
146
150
  expect_pass_silent "5. git commit msg 含 codex,無 exec/review → silent"
147
151
 
148
152
  # 6. inline codex exec WITH all 4 invariants → silent
149
- GOOD_INLINE="${CX} exec \"全盤閱讀全部 source。triple-verify per finding。禁抽樣 DS-wide ALL files。禁列檔 只讀 10 file 直接出 verdict。\""
153
+ GOOD_INLINE="${CX} exec \"全盤閱讀全部 source(鏡射 A.0:meta-patterns rules + memory MEMORY.md index)。triple-verify per finding。禁抽樣 DS-wide ALL files。禁列檔 只讀 10 file 直接出 verdict。判準對等:讀 audit-prompts.md 逐 dim rubric。A.1b per-component claim-vs-code 對抗驗證讀 .tsx 逐句驗宣稱。\""
150
154
  run_hook "$GOOD_INLINE"
151
155
  expect_pass_silent "6. inline brief 全 4 invariant → silent"
152
156
 
@@ -158,6 +162,43 @@ expect_pass_silent "7. cat-pipe full-brief file → silent"
158
162
  run_hook "${CX} exec \"\$(cat $GOOD_BRIEF)\""
159
163
  expect_pass_silent "8. \$(cat) full-brief file → silent"
160
164
 
165
+ # 8b. 4 invariant 齊但缺輸入對等錨點(泛 glob 閱讀清單)→ BLOCK(2026-07-10 5️⃣)
166
+ NOPARITY_BRIEF="$TMP_DIR/noparity-brief.md"
167
+ cat > "$NOPARITY_BRIEF" <<'EOF'
168
+ # Codex deep-audit brief
169
+ 1. 全盤閱讀全部 source(.claude/rules/* 泛 glob,禁憑記憶)
170
+ 2. triple-verify per finding(grep + Read + canonical exception check)
171
+ 3. 禁抽樣 — DS-wide ALL files,sub-agent sampled = reject
172
+ 4. 禁列檔 — 只讀 12 file,直接出 verdict
173
+ EOF
174
+ run_hook "cat $NOPARITY_BRIEF | ${CX} exec"
175
+ expect_block "8b. 缺輸入對等錨點(泛 glob)→ BLOCK" "5️⃣"
176
+
177
+ # 8c. 5 invariant 齊但缺判準對等(audit-prompts)→ 6️⃣ BLOCK(2026-07-10)
178
+ NORUBRIC_BRIEF="$TMP_DIR/norubric-brief.md"
179
+ cat > "$NORUBRIC_BRIEF" <<'EOF'
180
+ # Codex deep-audit brief
181
+ 1. 全盤閱讀全部 source(.claude/rules/meta-patterns.md + memory MEMORY.md,禁憑記憶)
182
+ 2. triple-verify per finding(grep + Read + canonical exception check)
183
+ 3. 禁抽樣 — DS-wide ALL files,sub-agent sampled = reject
184
+ 4. 禁列檔 — 只讀 12 file,直接出 verdict
185
+ EOF
186
+ run_hook "cat $NORUBRIC_BRIEF | ${CX} exec"
187
+ expect_block "8c. 缺判準對等(無 audit-prompts)→ BLOCK" "6️⃣"
188
+
189
+ # 8d. 1️⃣-6️⃣ 齊但缺 A.1b(per-component claim-vs-code)→ 7️⃣ BLOCK(2026-07-10)
190
+ NOA1B_BRIEF="$TMP_DIR/noa1b-brief.md"
191
+ cat > "$NOA1B_BRIEF" <<'EOF'
192
+ # Codex deep-audit brief
193
+ 1. 全盤閱讀全部 source(.claude/rules/meta-patterns.md + memory MEMORY.md,禁憑記憶)
194
+ 2. triple-verify per finding(grep + Read + canonical exception check)
195
+ 3. 禁抽樣 — DS-wide ALL files,sub-agent sampled = reject
196
+ 4. 禁列檔 — 只讀 12 file,直接出 verdict
197
+ 5. 判準對等:讀 design-system-audit/references/audit-prompts.md 每 dim rubric,逐 dim 套用
198
+ EOF
199
+ run_hook "cat $NOA1B_BRIEF | ${CX} exec"
200
+ expect_block "8d. 缺 A.1b(per-component claim-vs-code)→ 7️⃣ BLOCK" "7️⃣"
201
+
161
202
  # 9. stdin redirect full brief → silent
162
203
  run_hook "${CX} exec < $GOOD_BRIEF"
163
204
  expect_pass_silent "9. stdin redirect full-brief file → silent"
@@ -230,6 +230,118 @@ expect_silent "25. P8 nearmiss shadow-[var(--elevation-100)] → silent"
230
230
  run_hook "$PROD_TSX" 'export const C = () => <div className="max-w-[600px] grid-cols-[1fr_2fr]">x</div>'
231
231
  expect_silent "26. P8 nearmiss max-w-[600px]/grid-cols-[...](非色字 shadow)→ silent"
232
232
 
233
+ # ── 手刻 menu-item 可點列(2026-07-10 WM TypeSettingsDialog 左 rail 錨例)──
234
+ # 27. POSITIVE:手刻 button + hover:bg-neutral-hover + bg-neutral-selected 成對 → BLOCK
235
+ run_hook "$PROD_TSX" 'const cls = `flex w-full items-center gap-2 rounded-md hover:bg-neutral-hover ${sel ? "bg-neutral-selected" : ""}`; export const C = () => <button type="button" className={cls}>Task</button>'
236
+ expect_block "27. 手刻 nav row(hover+selected 成對)→ BLOCK"
237
+
238
+ # 28. NEGATIVE:同簽名 token 出現但已消費 <MenuItem>(正道)→ silent
239
+ run_hook "$PROD_TSX" 'export const C = () => <MenuItem size="sm" selected startContent={<Badge/>}>Task</MenuItem> /* hover:bg-neutral-hover bg-neutral-selected */'
240
+ expect_silent "28. 消費 <MenuItem> → silent"
241
+
242
+ # 29. NEGATIVE:只有 hover 無 selected(單純 hover row,非 menu-item family 簽名)→ silent
243
+ run_hook "$PROD_TSX" 'export const C = () => <button className="hover:bg-neutral-hover">row</button>'
244
+ expect_silent "29. 只 hover 無 selected → silent"
245
+
246
+ # 30. NEGATIVE:escape marker → silent
247
+ run_hook "$PROD_TSX" 'export const C = () => <div className="hover:bg-neutral-hover bg-neutral-selected">x</div> // @nav-row-handcraft-ok: calendar cell 非 menu 語義'
248
+ expect_silent "30. @nav-row-handcraft-ok escape → silent"
249
+
250
+ # ── 2026-07-10 批次 A(治理覆蓋 matrix 收官)──
251
+ # 31. C5 POSITIVE:亮色底 + text-white 對比配對違規 → BLOCK
252
+ run_hook "$PROD_TSX" 'export const T = () => <span className="bg-[var(--color-amber-6)] text-white size-4">A</span>'
253
+ expect_block "31. C5 亮色底+text-white 配對 → BLOCK"
254
+
255
+ # 32. C5 NEGATIVE:CAT_SOLID 正道(深字桶自帶 on-emphasis-dark)→ silent
256
+ run_hook "$PROD_TSX" 'export const T = () => <span className={`size-4 ${CAT_SOLID[hue]}`}>A</span>'
257
+ expect_silent "32. C5 消費 CAT_SOLID → silent"
258
+
259
+ # 33. C18 POSITIVE:children 計數括號串接 → BLOCK
260
+ run_hook "$PROD_TSX" 'export const H = () => <span>{group.label} ({items.length})</span>'
261
+ expect_block "33. C18 {label} ({count}) 串接 → BLOCK"
262
+
263
+ # 34. C18 NEGATIVE:aria-label 字串層(attr 非 children)→ silent
264
+ run_hook "$PROD_TSX" 'export const H = () => <span aria-label={`${label} (${count})`}>{label}</span>'
265
+ expect_silent "34. C18 aria-label 括號形 → silent"
266
+
267
+ # 35. C17 POSITIVE:vertical Separator 無 mx → BLOCK
268
+ run_hook "$PROD_TSX" 'export const B = () => <><Button>A</Button><Separator orientation="vertical" className="h-6" /><Button>B</Button></>'
269
+ expect_block "35. C17 vertical Separator 無 mx → BLOCK"
270
+
271
+ # 36. C17 NEGATIVE:h-6 mx-1 canonical → silent
272
+ run_hook "$PROD_TSX" 'export const B = () => <><Button>A</Button><Separator orientation="vertical" className="h-6 mx-1" /><Button>B</Button></>'
273
+ expect_silent "36. C17 h-6 mx-1 canonical → silent"
274
+
275
+ # 37. C20 POSITIVE:手刻 underline 連結字 → BLOCK
276
+ run_hook "$PROD_TSX" 'export const D = () => <span className="text-primary underline">upload</span>'
277
+ expect_block "37. C20 裸 underline 連結 → BLOCK"
278
+
279
+ # 38. C20 NEGATIVE:no-underline(合規移除底線)→ silent
280
+ run_hook "$PROD_TSX" 'export const D = () => <a className="no-underline text-primary">upload</a>'
281
+ expect_silent "38. C20 no-underline → silent"
282
+
283
+ # 39. C10 POSITIVE:spacer 把 Search 推最右 → BLOCK
284
+ run_hook "$PROD_TSX" 'export const T = () => <div><Button>Add</Button><span className="flex-1" /><Input placeholder="Search employees" /></div>'
285
+ expect_block "39. C10 業務 search 被推最右 → BLOCK"
286
+
287
+ # 40. C10 NEGATIVE:search 在業務層(無 spacer 前置)→ silent
288
+ run_hook "$PROD_TSX" 'export const T = () => <div><Button>Add</Button><Input placeholder="Search employees" /><span className="flex-1" /></div>'
289
+ expect_silent "40. C10 search 歸業務層 → silent"
290
+
291
+ # 41. C11 POSITIVE:DialogHeader 手放 X(雙 X)→ BLOCK
292
+ run_hook "$PROD_TSX" 'export const D = () => <DialogHeader><DialogTitle>Edit</DialogTitle><Button iconOnly startIcon={X} aria-label="Close" /></DialogHeader>'
293
+ expect_block "41. C11 DialogHeader 雙 X → BLOCK"
294
+
295
+ # 42. C11 NEGATIVE:header 操作走 actions slot → silent
296
+ run_hook "$PROD_TSX" 'export const D = () => <DialogHeader actions={<Button iconOnly startIcon={X} aria-label="Prev" />}><DialogTitle>Edit</DialogTitle></DialogHeader>'
297
+ expect_silent "42. C11 actions slot → silent"
298
+
299
+ # 43. C12 POSITIVE:Select 硬寬 w-36 → BLOCK
300
+ run_hook "$PROD_TSX" 'export const F = () => <Select className="w-36" options={opts} />'
301
+ expect_block "43. C12 Select 硬寬 w-36 → BLOCK"
302
+
303
+ # 44. C12 NEGATIVE:width="hug" 語義軸 → silent
304
+ run_hook "$PROD_TSX" 'export const F = () => <Select width="hug" options={opts} />'
305
+ expect_silent "44. C12 width=hug → silent"
306
+
307
+ # 45. named-import 除鏽 POSITIVE:無 DS. 前綴的 LinkInput placeholder-only 也要抓 → BLOCK
308
+ run_hook "$PROD_TSX" 'export const L = () => <LinkInput placeholder="https://" />'
309
+ expect_block "45. named-import <LinkInput placeholder-only → BLOCK(除鏽)"
310
+
311
+ # ── C19 兩欄 dialog 共用捲軸(2026-07-10 user 拍板組合 canonical)──
312
+ # 46. POSITIVE:兩欄(border-l)+ 只有 1 個 ScrollArea = 共用捲軸 → BLOCK
313
+ run_hook "$PROD_TSX" 'export const D = () => <DialogBody><ScrollArea><div className="flex"><div>main</div><aside className="border-l">meta</aside></div></ScrollArea></DialogBody>'
314
+ expect_block "46. C19 兩欄共用單一 ScrollArea → BLOCK"
315
+
316
+ # 47. NEGATIVE:各欄自帶 ScrollArea(組合 canonical)→ silent
317
+ run_hook "$PROD_TSX" 'export const D = () => <DialogBody><div className="flex"><ScrollArea>main</ScrollArea><aside className="border-l"><ScrollArea>meta</ScrollArea></aside></div></DialogBody>'
318
+ expect_silent "47. C19 各欄自帶 ScrollArea → silent"
319
+
320
+ # 48. NEGATIVE:escape → silent
321
+ run_hook "$PROD_TSX" 'export const D = () => <DialogBody><div className="flex border-l">x</div></DialogBody> // @two-pane-dialog-ok: 非兩欄,版面裝飾線'
322
+ expect_silent "48. C19 @two-pane-dialog-ok escape → silent"
323
+
324
+ # ── C7 SelectMenu 直用 + C13 手刻 section header(2026-07-10 收官)──
325
+ # 49. C7 POSITIVE:<SelectMenu> 直用 → BLOCK
326
+ run_hook "$PROD_TSX" 'export const M = () => <SelectMenu options={opts} onSelect={pick} />'
327
+ expect_block "49. C7 <SelectMenu> 直用 → BLOCK"
328
+
329
+ # 50. C7 NEGATIVE:<Select>(正道)→ silent
330
+ run_hook "$PROD_TSX" 'export const M = () => <Select options={opts} onChange={pick} />'
331
+ expect_silent "50. C7 <Select> 正道 → silent"
332
+
333
+ # 51. C13 POSITIVE:手刻可收合標題列(Chevron + justify-between + button)→ BLOCK
334
+ run_hook "$PROD_TSX" 'export const H = () => <button onClick={toggle} className="flex w-full items-center justify-between"><span>Description</span><ChevronDown className="size-4" /></button>'
335
+ expect_block "51. C13 手刻可收合標題列 → BLOCK"
336
+
337
+ # 52. C13 NEGATIVE:共用 SectionHeader 元件(正道)→ silent
338
+ run_hook "$PROD_TSX" 'export const H = () => <SectionHeader title="Description" collapsed={c} onToggle={toggle} />'
339
+ expect_silent "52. C13 共用 SectionHeader → silent"
340
+
341
+ # 53. C13 NEGATIVE:escape(非 section 標題語義)→ silent
342
+ run_hook "$PROD_TSX" 'export const P = () => <button onClick={next} className="flex justify-between">next<ChevronRight /></button> // @section-header-ok: 分頁導航非 section 標題'
343
+ expect_silent "53. C13 @section-header-ok escape → silent"
344
+
233
345
  echo ""
234
346
  echo "=== Summary ==="
235
347
  echo "Passed: $PASS / $((PASS + FAIL))"
@@ -161,12 +161,19 @@ expect_pass_silent "N4. DS internal stories → excluded silent"
161
161
  run_hook "Read" "$CONSUMER_STORY" "$CONTENT_VIOLATION"
162
162
  expect_pass_silent "N5. tool=Read → silent"
163
163
 
164
- # N6. over-broad guard A:bare <Dialog>(no DS. namespace prefix)→ silent
164
+ # N6. over-broad guard A:bare <Dialog>(no DS. namespace prefix)from consumer-local import → silent
165
165
  # consumer 用自己的 local Dialog,不是高風險 DS primitive → 不該 fire
166
166
  CONTENT_BARE='import { Dialog } from "./local-dialog";
167
167
  export const Basic = () => <Dialog open>hi</Dialog>;'
168
168
  run_hook "Write" "$CONSUMER_STORY" "$CONTENT_BARE"
169
- expect_pass_silent "N6. bare <Dialog> (no DS. prefix) → silent (over-broad guard)"
169
+ expect_pass_silent "N6. bare <Dialog> (local import) → silent (over-broad guard)"
170
+
171
+ # P5. named-import 除鏽 POSITIVE(2026-07-10):bare <Dialog> 但由 DS package named-import 進來
172
+ # → 是真 DS Dialog(fork 慣用 named import 繞過 <DS.> 前綴)→ 無 marker 必 BLOCK
173
+ CONTENT_NAMED='import { Dialog, Button } from "@qijenchen/design-system";
174
+ export const Basic = () => <Dialog open><Button>ok</Button></Dialog>;'
175
+ run_hook "Write" "$CONSUMER_STORY" "$CONTENT_NAMED"
176
+ expect_block "P5. named-import <Dialog> from DS pkg 無 marker → BLOCK" "CONSUMER-STORY-BASELINE BLOCKER"
170
177
 
171
178
  # N7. over-broad guard B:comment / prose mentioning "Dialog DataTable Sheet" but no JSX usage → silent
172
179
  CONTENT_PROSE='// This story demonstrates a layout. We avoid Dialog and DataTable here.
@@ -0,0 +1,76 @@
1
+ #!/bin/bash
2
+ # test_check_dynamic_tailwind_class.sh — 動態 Tailwind class 哨測試
3
+ # (2026-07-10 補 hook-test-coverage debt;hook 2026-07-09 建,anchor = h-table-row-${size} row 塌)
4
+ set -uo pipefail
5
+ cd "$(dirname "$0")/../../.."
6
+ HOOK=".claude/hooks/check_dynamic_tailwind_class.sh"
7
+ PASS=0; FAIL=0; FAILED_TESTS=""
8
+
9
+ TMP_DIR=$(mktemp -d)
10
+ trap 'rm -rf "$TMP_DIR"' EXIT
11
+ export CLAUDE_PROJECT_DIR="$TMP_DIR"
12
+ mkdir -p "$TMP_DIR/.claude/logs"
13
+
14
+ PROD_TSX="/Users/x/proj/packages/design-system/src/components/DataTable/data-table.tsx"
15
+
16
+ run_hook() {
17
+ local file_path="$1"; local content="$2"
18
+ local payload
19
+ payload=$(jq -n --arg fp "$file_path" --arg c "$content" \
20
+ '{tool_name:"Edit", tool_input:{file_path:$fp, new_string:$c}}')
21
+ STDERR=$(mktemp)
22
+ set +e
23
+ printf '%s' "$payload" | bash "$HOOK" >/dev/null 2>"$STDERR"
24
+ EXIT=$?
25
+ set -e
26
+ STDERR_TEXT=$(cat "$STDERR" 2>/dev/null); rm -f "$STDERR"
27
+ }
28
+
29
+ expect_block() {
30
+ local name="$1"
31
+ if [ "$EXIT" = "2" ]; then echo " PASS $name"; PASS=$((PASS+1))
32
+ else echo " FAIL $name (expected exit=2, got exit=$EXIT)"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"; fi
33
+ }
34
+ expect_silent() {
35
+ local name="$1"
36
+ if [ "$EXIT" = "0" ] && [ -z "$STDERR_TEXT" ]; then echo " PASS $name"; PASS=$((PASS+1))
37
+ else echo " FAIL $name (expected silent exit=0, got exit=$EXIT, stderr=${STDERR_TEXT:+non-empty})"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"; fi
38
+ }
39
+
40
+ # 1. POSITIVE:病根錨例 h-table-row-${size}(class 名含插值)→ BLOCK
41
+ run_hook "$PROD_TSX" 'const cls = `h-table-row-${size} flex`'
42
+ expect_block "1. h-table-row-\${size} → BLOCK"
43
+
44
+ # 2. POSITIVE:間距 utility gap-${g} → BLOCK
45
+ run_hook "$PROD_TSX" 'const cls = `flex gap-${g}`'
46
+ expect_block "2. gap-\${g} → BLOCK"
47
+
48
+ # 3. NEGATIVE:正解 literal map → silent
49
+ run_hook "$PROD_TSX" "const cls = { sm: 'h-table-row-sm', md: 'h-table-row-md', lg: 'h-table-row-lg' }[size]"
50
+ expect_silent "3. literal class 對照表 → silent"
51
+
52
+ # 4. NEGATIVE:arbitrary value 內插值(是值不是 class 名)→ silent
53
+ run_hook "$PROD_TSX" 'const cls = `h-[calc(100%_-_${offset}px)]`'
54
+ expect_silent "4. h-[calc(\${x})] arbitrary → silent"
55
+
56
+ # 5. NEGATIVE:var() 內插值 → silent
57
+ run_hook "$PROD_TSX" 'const cls = `w-[var(--col-${i})]`'
58
+ expect_silent "5. w-[var(--x-\${i})] → silent"
59
+
60
+ # 6. NEGATIVE:色彩 utility 不在 scope(hook 只鎖尺寸/間距)→ silent
61
+ run_hook "$PROD_TSX" 'const cls = `text-${color}`'
62
+ expect_silent "6. text-\${color}(非尺寸間距)→ silent"
63
+
64
+ # 7. NEGATIVE:escape 註解 → silent
65
+ run_hook "$PROD_TSX" 'const cls = `size-${px}` // @dynamic-tailwind-allow: 傳給 canvas 非 class'
66
+ expect_silent "7. @dynamic-tailwind-allow escape → silent"
67
+
68
+ # 8. NEGATIVE:非 production path(tests/)→ silent
69
+ run_hook "/Users/x/proj/scripts/gen-something.mjs" 'const cls = `h-${x}`'
70
+ expect_silent "8. 非 tsx production path → silent"
71
+
72
+ echo ""
73
+ echo "=== Summary ==="
74
+ echo "Passed: $PASS / $((PASS + FAIL))"
75
+ if [ "$FAIL" -gt 0 ]; then printf "Failed:%b\n" "$FAILED_TESTS"; exit 1; fi
76
+ exit 0
@@ -182,6 +182,30 @@ expect_not_block "N8. empty content → not blocked"
182
182
  run_hook_bypass "Write" "$CONSUMER" "content" "$C_3DISTINCT"
183
183
  expect_not_block "N9. CLAUDE_BYPASS_ESCAPE_MARKER_AUDIT=1 override → not blocked"
184
184
 
185
+ # ── R-series:repo 級累計 ratchet(2026-07-08 WM 戰役 R4)──────────────────────
186
+ # 存量 ≥10(apps/** 全 repo)後,只擋「本次 edit 再新增 marker」;無 marker edit 不 brick。
187
+ mkdir -p "$TMP_DIR/apps/work/src"
188
+ for i in 1 2 3 4 5 6; do
189
+ printf '// @ds-misuse-allow: seeded reason %s\n// @layout-space-magic-ok: seeded reason %sb\n' "$i" "$i" \
190
+ > "$TMP_DIR/apps/work/src/seed$i.tsx"
191
+ done
192
+
193
+ # R1. 存量 12 ≥ cap 10 + 本次新增 1 marker → BLOCK(ratchet)
194
+ run_hook "Write" "/repo/apps/work/src/new.tsx" "content" '<div /> // @ds-misuse-allow: one more'
195
+ expect_block "R1. repo 存量 12 ≥ cap + edit 加 marker → blocked (ratchet)" "ESCAPE-MARKER-REPO-RATCHET"
196
+
197
+ # R2. 存量 12 ≥ cap 但本次 edit 無 marker → not blocked(不因存量 brick 無關 edit)
198
+ run_hook "Write" "/repo/apps/work/src/new.tsx" "content" '<div className="flex" />'
199
+ expect_not_block "R2. repo 存量 ≥ cap 但 edit 無 marker → not blocked"
200
+
201
+ # R3. 存量降到 4 < cap + 本次加 1 marker → not blocked
202
+ rm -f "$TMP_DIR/apps/work/src/seed3.tsx" "$TMP_DIR/apps/work/src/seed4.tsx" \
203
+ "$TMP_DIR/apps/work/src/seed5.tsx" "$TMP_DIR/apps/work/src/seed6.tsx"
204
+ run_hook "Write" "/repo/apps/work/src/new.tsx" "content" '<div /> // @ds-misuse-allow: legit case'
205
+ expect_not_block "R3. repo 存量 4 < cap + edit 加 marker → not blocked"
206
+
207
+ rm -rf "$TMP_DIR/apps"
208
+
185
209
  echo ""
186
210
  echo "=== Summary ==="
187
211
  echo "Passed: $PASS / $((PASS + FAIL))"
@@ -1,11 +1,13 @@
1
1
  #!/bin/bash
2
- # Tests for check_field_family_invariants.sh — merged 4 sub-rules(A.1-A.4)
2
+ # Tests for check_field_family_invariants.sh — merged sub-rules(A.1-A.4 + A.6)
3
3
  #
4
- # Coverage(每 sub-rule pass + block 各 1 case,共 12 case):
4
+ # Coverage(每 sub-rule pass + block 各 1 case):
5
5
  # A.1 naked row-mode propagation:pass / block / allowlist
6
6
  # A.2 FieldControlGroup wrapper child:pass / block / allowlist
7
7
  # A.3 Field state ring SSOT:pass / 3 block(shadow inset / outline / per-control open)
8
8
  # A.4 disabled placeholder color:pass / 1 stderr-warn(exit 0)/ allowlist
9
+ # A.6 空值顯示 SSOT(2026-07-08 半形 hyphen):非 owner import EMPTY_DISPLAY block /
10
+ # owner skip / 全形 em dash block / 半形 pass / allowlist
9
11
  # non-target:non-tsx skip / SSOT host skip(field-wrapper.tsx)
10
12
 
11
13
  set -u
@@ -183,6 +185,29 @@ else
183
185
  FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - A.4.3"
184
186
  fi
185
187
 
188
+ echo ""
189
+ echo "=== A.6 空值顯示 SSOT(2026-07-08 半形 hyphen)==="
190
+
191
+ # 17. 非 owner import EMPTY_DISPLAY → BLOCK(應消費 useFieldEmptyDisplay hook 分流)
192
+ run_hook "/r/packages/design-system/src/components/Bad/bad.tsx" "import { EMPTY_DISPLAY } from '@/design-system/components/Field/field-wrapper'"
193
+ expect_exit "A.6.1 非 owner import EMPTY_DISPLAY → BLOCK" 2 "EMPTY_DISPLAY 直引"
194
+
195
+ # 18. owner field-context.ts import EMPTY_DISPLAY → pass(SSOT owner skip)
196
+ run_hook "/r/packages/design-system/src/components/Field/field-context.ts" "import { EMPTY_DISPLAY } from './field-wrapper'"
197
+ expect_exit "A.6.1 owner field-context.ts import → pass" 0
198
+
199
+ # 19. components tsx hardcode 全形 em dash '—' → BLOCK
200
+ run_hook "/r/packages/design-system/src/components/Bad/bad.tsx" "const cls = value ?? '—'"
201
+ expect_exit "A.6.2 hardcode 全形 em dash → BLOCK" 2 "全形 em dash"
202
+
203
+ # 20. 半形 hyphen '-' → pass(非全形,不觸發)
204
+ run_hook "/r/packages/design-system/src/components/Bad/bad.tsx" "const sep = '-'"
205
+ expect_exit "A.6.2 半形 hyphen → pass" 0
206
+
207
+ # 21. allowlist → pass
208
+ run_hook "/r/packages/design-system/src/components/Bad/bad.tsx" "const cls = value ?? '—' // @empty-display-allow: legacy N/A marker"
209
+ expect_exit "A.6 allowlist → pass" 0
210
+
186
211
  echo ""
187
212
  echo "=== Skip cases ==="
188
213
 
@@ -28,7 +28,9 @@ echo "Test 3: fork-user without plugin → inject"
28
28
  TMP=$(mktemp -d); echo '{"dependencies":{"@qijenchen/design-system":"^1"}}' > "$TMP/package.json"
29
29
  # Override HOME/CWD so plugin install detect 一定 fail
30
30
  STDOUT=$(cd "$TMP" && HOME=/tmp/no-plugin echo '{"hook_event_name":"SessionStart"}' | bash "$HOOK")
31
- if echo "$STDOUT" | grep -q "Fork-user plugin not installed"; then
31
+ # 2026-07-07 stale needle:hook 訊息 2026-06 演進為「Fork-user DS 治理鏈未就位」,
32
+ # 舊 needle「Fork-user plugin not installed」永 FAIL(main 既存紅;hook 行為本身正確)。
33
+ if echo "$STDOUT" | grep -q "Fork-user DS 治理鏈未就位"; then
32
34
  echo " PASS"; PASS=$((PASS+1))
33
35
  else
34
36
  echo " FAIL: no inject (output: ${STDOUT:0:200})"; FAIL=$((FAIL+1))
@@ -47,10 +47,22 @@ expect_pass_silent() {
47
47
 
48
48
  expect_warn() {
49
49
  local name="$1"; local needle="$2"
50
- if [ "$EXIT" = "0" ] && echo "$STDERR_TEXT" | grep -qF "$needle"; then
50
+ if [ "$EXIT" = "2" ] && echo "$STDERR_TEXT" | grep -qF "$needle"; then
51
51
  echo " PASS $name"; PASS=$((PASS+1))
52
52
  else
53
- echo " FAIL $name (expected warn '$needle', got exit $EXIT)"
53
+ echo " FAIL $name (expected exit=2 + needle '$needle', got exit $EXIT)"
54
+ echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
55
+ FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
56
+ fi
57
+ }
58
+
59
+ # #71 soft WARN tier(micro_gap / fraction):exit 0(不 block)+ stderr 含 'soft flag'
60
+ expect_soft_flag() {
61
+ local name="$1"
62
+ if [ "$EXIT" = "0" ] && echo "$STDERR_TEXT" | grep -qF "soft flag"; then
63
+ echo " PASS $name"; PASS=$((PASS+1))
64
+ else
65
+ echo " FAIL $name (expected exit=0 + 'soft flag', got exit=$EXIT)"
54
66
  echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
55
67
  FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
56
68
  fi
@@ -101,6 +113,33 @@ const b = "opacity-75"
101
113
  '
102
114
  expect_warn "7. multi opacity-N values → warn" "opacity-25"
103
115
 
116
+ # ── #71 micro_gap / fraction soft WARN tier(2026-07-11 接線)──────────────────
117
+ FP71="/repo/packages/design-system/src/components/Calendar/calendar.tsx"
118
+
119
+ # 8. gap-0.5(micro gap)→ soft flag(exit 0,非 block)
120
+ run_hook "$FP71" 'const a = <div className="gap-0.5" />'
121
+ expect_soft_flag "8. gap-0.5 micro gap → soft WARN(非 block)"
122
+
123
+ # 9. w-1/3(registry fraction)→ soft flag(exit 0)
124
+ run_hook "$FP71" 'const a = <div className="w-1/3" />'
125
+ expect_soft_flag "9. w-1/3 registry fraction → soft WARN"
126
+
127
+ # 10. w-1/2(合法,不在 registry 14 條)→ silent(不誤殺)
128
+ run_hook "$FP71" 'const a = <div className="w-1/2" />'
129
+ expect_pass_silent "10. w-1/2(合法留白)→ silent 不誤殺"
130
+
131
+ # 11. gap-2(合法)→ silent
132
+ run_hook "$FP71" 'const a = <div className="gap-2" />'
133
+ expect_pass_silent "11. gap-2(合法)→ silent"
134
+
135
+ # 12. 硬 violation + gap-0.5 → exit 2(hard block 不被 soft tier 弱化)
136
+ run_hook "$FP71" 'const a = <div className="text-muted-foreground gap-0.5" />'
137
+ expect_warn "12. 硬 violation + gap-0.5 → exit 2 block" "shadcn alias"
138
+
139
+ # 13. gap-0.5 + @token-registry-ok escape → silent
140
+ run_hook "$FP71" 'const a = <div className="gap-0.5" /> // @token-registry-ok: skeleton bone'
141
+ expect_pass_silent "13. gap-0.5 + escape → silent"
142
+
104
143
  echo ""
105
144
  echo "=== Summary ==="
106
145
  echo "Passed: $PASS / $((PASS + FAIL))"
@@ -0,0 +1,72 @@
1
+ #!/bin/bash
2
+ # test_check_ssot_header_declaration.sh — 新建 production tsx 必帶「── 消費的 SSOT ──」段
3
+ # (2026-07-07 治理進化方向 3 洞 a;P0 exit 2;ratchet:只攔 Write 新檔)
4
+
5
+ HOOK="$(cd "$(dirname "$0")/.." && pwd)/check_ssot_header_declaration.sh"
6
+ if [ ! -f "$HOOK" ]; then echo "FATAL: hook not found: $HOOK"; exit 1; fi
7
+
8
+ PASS=0; FAIL=0; FAILED_TESTS=""
9
+
10
+ run_hook() {
11
+ local file_path="$1"; local content="$2"; local tool="${3:-Write}"
12
+ STDERR_TEXT=$(jq -n --arg t "$tool" --arg f "$file_path" --arg c "$content" \
13
+ '{tool_name:$t, tool_input:{file_path:$f, content:$c}}' | bash "$HOOK" 2>&1 >/dev/null)
14
+ EXIT=$?
15
+ }
16
+
17
+ expect_block() {
18
+ local name="$1"
19
+ if [ "$EXIT" = "2" ] && echo "$STDERR_TEXT" | grep -qF "消費的 SSOT"; then
20
+ echo " PASS $name"; PASS=$((PASS+1))
21
+ else
22
+ echo " FAIL $name (expected exit=2, got $EXIT)"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
23
+ fi
24
+ }
25
+ expect_silent() {
26
+ local name="$1"
27
+ if [ "$EXIT" = "0" ]; then
28
+ echo " PASS $name"; PASS=$((PASS+1))
29
+ else
30
+ echo " FAIL $name (expected exit=0, got $EXIT)"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
31
+ fi
32
+ }
33
+
34
+ echo "=== check_ssot_header_declaration tests ==="
35
+
36
+ # 1. 新元件 tsx 無宣告段 → BLOCK
37
+ run_hook "/repo/packages/design-system/src/components/NewThing/new-thing.tsx" 'import * as React from "react"
38
+ export const NewThing = () => <div className="flex border rounded-md px-2" />'
39
+ expect_block "1. 新元件 tsx 無 SSOT 段 → BLOCK"
40
+
41
+ # 2. 有宣告段 → pass
42
+ run_hook "/repo/packages/design-system/src/components/NewThing/new-thing.tsx" '// ── 消費的 SSOT ──
43
+ // - Button(pill layout)/ --layout-space-tight
44
+ import * as React from "react"'
45
+ expect_silent "2. 有「── 消費的 SSOT ──」段 → pass"
46
+
47
+ # 3. escape marker → pass
48
+ run_hook "/repo/packages/design-system/src/components/NewThing/util.tsx" '// @ssot-header-exempt: 純型別 utility,零視覺
49
+ export type X = string'
50
+ expect_silent "3. @ssot-header-exempt escape → pass"
51
+
52
+ # 4. stories 檔 → 豁免
53
+ run_hook "/repo/packages/design-system/src/components/NewThing/new-thing.stories.tsx" 'export default {}'
54
+ expect_silent "4. stories.tsx 豁免"
55
+
56
+ # 5. 非 DS production 路徑 → 豁免
57
+ run_hook "/repo/apps/template/src/App.tsx" 'export const App = () => <div className="flex border px-2" />'
58
+ expect_silent "5. apps/ 路徑豁免"
59
+
60
+ # 6. Edit 工具(存量檔)→ 豁免(ratchet)
61
+ run_hook "/repo/packages/design-system/src/components/Button/button.tsx" 'whatever' "Edit"
62
+ expect_silent "6. Edit(存量 ratchet)豁免"
63
+
64
+ # 7. patterns/ 新檔無宣告 → BLOCK
65
+ run_hook "/repo/packages/design-system/src/patterns/new-pattern/new-pattern.tsx" 'export const P = () => <div className="absolute shadow px-2" />'
66
+ expect_block "7. patterns/ 新檔無 SSOT 段 → BLOCK"
67
+
68
+ echo ""
69
+ echo "=== Summary ==="
70
+ echo "Passed: $PASS / $((PASS+FAIL))"
71
+ if [ "$FAIL" -gt 0 ]; then printf "Failed:%b\n" "$FAILED_TESTS"; exit 1; fi
72
+ exit 0
@@ -0,0 +1,76 @@
1
+ #!/bin/bash
2
+ # test_check_tabs_content_chrome_body_double_gap.sh — overlay-body layout-space 哨測試
3
+ # (2026-07-10 補 hook-test-coverage debt;hook 2026-07-01 建,anchor = 專案設定 Dialog 雙 tight)
4
+ # 注意:本 hook 是 PostToolUse「讀完整檔」型(防 partial-edit 盲區)→ 測試必寫真實 temp 檔,
5
+ # 且路徑必須匹配 scope regex(packages/design-system/src/ 或 /apps/)。
6
+ set -uo pipefail
7
+ cd "$(dirname "$0")/../../.."
8
+ HOOK=".claude/hooks/check_tabs_content_chrome_body_double_gap.sh"
9
+ PASS=0; FAIL=0; FAILED_TESTS=""
10
+
11
+ TMP_DIR=$(mktemp -d)
12
+ trap 'rm -rf "$TMP_DIR"' EXIT
13
+ export CLAUDE_PROJECT_DIR="$TMP_DIR"
14
+ mkdir -p "$TMP_DIR/.claude/logs"
15
+
16
+ # scope 內的真實 temp 檔路徑(hook 讀 disk)
17
+ DS_DIR="$TMP_DIR/packages/design-system/src/components/Dialog"
18
+ mkdir -p "$DS_DIR"
19
+
20
+ run_hook_file() {
21
+ local file_path="$1"; local content="$2"
22
+ mkdir -p "$(dirname "$file_path")"
23
+ printf '%s' "$content" > "$file_path"
24
+ local payload
25
+ payload=$(jq -n --arg fp "$file_path" --arg c "$content" \
26
+ '{tool_name:"Edit", tool_input:{file_path:$fp, new_string:$c}}')
27
+ STDERR=$(mktemp)
28
+ set +e
29
+ printf '%s' "$payload" | bash "$HOOK" >/dev/null 2>"$STDERR"
30
+ EXIT=$?
31
+ set -e
32
+ STDERR_TEXT=$(cat "$STDERR" 2>/dev/null); rm -f "$STDERR"
33
+ rm -f "$file_path"
34
+ }
35
+
36
+ expect_block() {
37
+ local name="$1"
38
+ if [ "$EXIT" = "2" ]; then echo " PASS $name"; PASS=$((PASS+1))
39
+ else echo " FAIL $name (expected exit=2, got exit=$EXIT)"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"; fi
40
+ }
41
+ expect_silent() {
42
+ local name="$1"
43
+ if [ "$EXIT" = "0" ] && [ -z "$STDERR_TEXT" ]; then echo " PASS $name"; PASS=$((PASS+1))
44
+ else echo " FAIL $name (expected silent exit=0, got exit=$EXIT, stderr=${STDERR_TEXT:+non-empty})"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"; fi
45
+ }
46
+
47
+ # 1. POSITIVE(Check 1 錨例):chrome body 內 TabsContent 無 mt-0 → 雙重 gap → BLOCK
48
+ run_hook_file "$DS_DIR/case1.stories.tsx" '<DialogBody><Tabs value={t}><TabsContent value="a"><p>內容</p></TabsContent></Tabs></DialogBody>'
49
+ expect_block "1. DialogBody 內 TabsContent 無 mt-0 → BLOCK"
50
+
51
+ # 2. NEGATIVE:TabsContent 帶 mt-0(ownership 轉移給 body)→ silent
52
+ run_hook_file "$DS_DIR/case2.stories.tsx" '<DialogBody><Tabs value={t}><TabsContent value="a" className="mt-0"><p>內容</p></TabsContent></Tabs></DialogBody>'
53
+ expect_silent "2. TabsContent className=mt-0 → silent"
54
+
55
+ # 3. NEGATIVE:TabsContent 不在 chrome body 內(頁面級 Tabs)→ silent
56
+ run_hook_file "$DS_DIR/case3.stories.tsx" '<Tabs value={t}><TabsList>…</TabsList><TabsContent value="a"><p>內容</p></TabsContent></Tabs>'
57
+ expect_silent "3. 頁面級 Tabs(無 chrome body)→ silent"
58
+
59
+ # 4. POSITIVE(Check 3 root 簽名):TabsList 手塞 DialogBody 同檔且無 tabsSlot → BLOCK
60
+ run_hook_file "$DS_DIR/case4.stories.tsx" '<DialogBody><TabsList size="sm"><TabsTrigger value="a">A</TabsTrigger></TabsList><TabsContent value="a" className="mt-0">x</TabsContent></DialogBody>'
61
+ expect_block "4. TabsList 手塞 chrome body 無 tabsSlot → BLOCK(root)"
62
+
63
+ # 5. NEGATIVE:escape 註解 → silent
64
+ run_hook_file "$DS_DIR/case5.stories.tsx" '{/* @tabs-content-gap-ok: 內容層分頁非 dialog chrome */}
65
+ <DialogBody><Tabs value={t}><TabsContent value="a">x</TabsContent></Tabs></DialogBody>'
66
+ expect_silent "5. @tabs-content-gap-ok escape → silent"
67
+
68
+ # 6. NEGATIVE:scope 外路徑(非 DS-src / apps)→ silent
69
+ run_hook_file "$TMP_DIR/docs/example.tsx" '<DialogBody><TabsContent value="a">x</TabsContent></DialogBody>'
70
+ expect_silent "6. scope 外路徑 → silent"
71
+
72
+ echo ""
73
+ echo "=== Summary ==="
74
+ echo "Passed: $PASS / $((PASS + FAIL))"
75
+ if [ "$FAIL" -gt 0 ]; then printf "Failed:%b\n" "$FAILED_TESTS"; exit 1; fi
76
+ exit 0
@@ -45,7 +45,7 @@
45
45
 
46
46
  | 真缺項 | 補的形式 | Commit |
47
47
  |---|---|---|
48
- | #13 i18n 硬寫字串 | `.claude/hooks/check_hardcoded_strings.sh` PostToolUse,flag DS primitive tsx(非 stories)CJK ≥ 3 chars / 英文 sentence-case label;支援 `// i18n-allow: {rationale}` 白名單 | 本次 session |
48
+ | #13 i18n 硬寫字串 | `post_edit_dispatcher.sh → lib/_hardcoded_strings.sh` PostToolUse flag(2026-05-13 由獨立 hook `check_hardcoded_strings.sh` folded 進 dispatcher lib),flag DS primitive tsx(非 stories)CJK ≥ 3 chars / 英文 sentence-case label;支援 `// i18n-allow: {rationale}` 白名單 | 本次 session |
49
49
  | #3 Controlled / Uncontrolled + #12 Form dual-mode | `design-system-audit` Dim 26(新 Group J)— 掃 form + overlay 元件 value/defaultValue / open/defaultOpen / checked/defaultChecked 的 pair 完整性;V1-V4 violation types | 本次 session |
50
50
  | #23 edge case(null / empty / rapid / success) | `/ux-audit` Phase 5 從 3 態 → 5 態 + null-safety + rapid-interaction + edge case corollary | 本次 session |
51
51