@qijenchen/design-system 0.1.0-beta.83 → 0.1.0-beta.85

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 (622) 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-group.d.ts +47 -0
  53. package/dist/components/DataTable/data-table-filter-group.d.ts.map +1 -0
  54. package/dist/components/DataTable/data-table-filter-group.js +154 -0
  55. package/dist/components/DataTable/data-table-filter-group.js.map +1 -0
  56. package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
  57. package/dist/components/DataTable/data-table-filter-panel.js +285 -0
  58. package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
  59. package/dist/components/DataTable/data-table-filter-value-picker.d.ts +29 -0
  60. package/dist/components/DataTable/data-table-filter-value-picker.d.ts.map +1 -0
  61. package/dist/components/DataTable/data-table-filter-value-picker.js +187 -0
  62. package/dist/components/DataTable/data-table-filter-value-picker.js.map +1 -0
  63. package/dist/components/DataTable/data-table-interaction-layer.d.ts +11 -15
  64. package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
  65. package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
  66. package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
  67. package/dist/components/DataTable/data-table-sort-manager.js +140 -0
  68. package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
  69. package/dist/components/DataTable/data-table.d.ts +5 -6
  70. package/dist/components/DataTable/data-table.d.ts.map +1 -1
  71. package/dist/components/DataTable/data-table.js +36 -15
  72. package/dist/components/DataTable/data-table.js.map +1 -1
  73. package/dist/components/DataTable/filter-operators.js +140 -0
  74. package/dist/components/DataTable/filter-operators.js.map +1 -0
  75. package/dist/components/DataTable/filter-tree.js +312 -0
  76. package/dist/components/DataTable/filter-tree.js.map +1 -0
  77. package/dist/components/DataTable/index.d.ts +3 -0
  78. package/dist/components/DataTable/index.d.ts.map +1 -1
  79. package/dist/components/DataTable/index.js +12 -1
  80. package/dist/components/DataTable/index.js.map +1 -1
  81. package/dist/components/DataTable/lib/column-meta.js +25 -0
  82. package/dist/components/DataTable/lib/column-meta.js.map +1 -0
  83. package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
  84. package/dist/components/DateGrid/date-grid.js +3 -1
  85. package/dist/components/DateGrid/date-grid.js.map +1 -1
  86. package/dist/components/DatePicker/date-picker.d.ts +7 -1
  87. package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
  88. package/dist/components/DatePicker/date-picker.js +105 -74
  89. package/dist/components/DatePicker/date-picker.js.map +1 -1
  90. package/dist/components/Dialog/dialog.d.ts +20 -3
  91. package/dist/components/Dialog/dialog.d.ts.map +1 -1
  92. package/dist/components/Dialog/dialog.js +38 -20
  93. package/dist/components/Dialog/dialog.js.map +1 -1
  94. package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
  95. package/dist/components/DropdownMenu/dropdown-menu.js +3 -1
  96. package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
  97. package/dist/components/Field/field-context.d.ts +45 -5
  98. package/dist/components/Field/field-context.d.ts.map +1 -1
  99. package/dist/components/Field/field-context.js +19 -0
  100. package/dist/components/Field/field-context.js.map +1 -1
  101. package/dist/components/Field/field-edit-keys.d.ts +21 -0
  102. package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
  103. package/dist/components/Field/field-edit-keys.js +19 -0
  104. package/dist/components/Field/field-edit-keys.js.map +1 -0
  105. package/dist/components/Field/field-types.d.ts +20 -1
  106. package/dist/components/Field/field-types.d.ts.map +1 -1
  107. package/dist/components/Field/field-types.js.map +1 -1
  108. package/dist/components/Field/field-wrapper.d.ts +3 -2
  109. package/dist/components/Field/field-wrapper.d.ts.map +1 -1
  110. package/dist/components/Field/field-wrapper.js +38 -39
  111. package/dist/components/Field/field-wrapper.js.map +1 -1
  112. package/dist/components/Field/field.d.ts +2 -1
  113. package/dist/components/Field/field.d.ts.map +1 -1
  114. package/dist/components/Field/field.js.map +1 -1
  115. package/dist/components/Field/index.d.ts +1 -0
  116. package/dist/components/Field/index.d.ts.map +1 -1
  117. package/dist/components/Field/index.js +2 -0
  118. package/dist/components/Field/index.js.map +1 -1
  119. package/dist/components/FieldControlGroup/field-control-group.d.ts +1 -1
  120. package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
  121. package/dist/components/FileItem/file-item.d.ts.map +1 -1
  122. package/dist/components/FileItem/file-item.js +1 -1
  123. package/dist/components/FileItem/file-item.js.map +1 -1
  124. package/dist/components/FileUpload/file-upload.d.ts +1 -1
  125. package/dist/components/FileUpload/file-upload.js.map +1 -1
  126. package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
  127. package/dist/components/FileViewer/file-viewer.js +7 -2
  128. package/dist/components/FileViewer/file-viewer.js.map +1 -1
  129. package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
  130. package/dist/components/FileViewer/image-renderer.js +22 -1
  131. package/dist/components/FileViewer/image-renderer.js.map +1 -1
  132. package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
  133. package/dist/components/HoverCard/hover-card.js +5 -3
  134. package/dist/components/HoverCard/hover-card.js.map +1 -1
  135. package/dist/components/InlineEdit/index.d.ts +2 -0
  136. package/dist/components/InlineEdit/index.d.ts.map +1 -0
  137. package/dist/components/InlineEdit/index.js +5 -0
  138. package/dist/components/InlineEdit/index.js.map +1 -0
  139. package/dist/components/InlineEdit/inline-edit.d.ts +59 -0
  140. package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
  141. package/dist/components/InlineEdit/inline-edit.js +164 -0
  142. package/dist/components/InlineEdit/inline-edit.js.map +1 -0
  143. package/dist/components/Input/input.d.ts +6 -11
  144. package/dist/components/Input/input.d.ts.map +1 -1
  145. package/dist/components/Input/input.js +43 -13
  146. package/dist/components/Input/input.js.map +1 -1
  147. package/dist/components/LinkInput/link-input.d.ts +2 -2
  148. package/dist/components/LinkInput/link-input.d.ts.map +1 -1
  149. package/dist/components/LinkInput/link-input.js +6 -5
  150. package/dist/components/LinkInput/link-input.js.map +1 -1
  151. package/dist/components/Menu/menu-item.d.ts +14 -2
  152. package/dist/components/Menu/menu-item.d.ts.map +1 -1
  153. package/dist/components/Menu/menu-item.js +25 -3
  154. package/dist/components/Menu/menu-item.js.map +1 -1
  155. package/dist/components/NumberInput/number-input.d.ts +3 -3
  156. package/dist/components/NumberInput/number-input.d.ts.map +1 -1
  157. package/dist/components/NumberInput/number-input.js +6 -5
  158. package/dist/components/NumberInput/number-input.js.map +1 -1
  159. package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
  160. package/dist/components/OverflowIndicator/overflow-indicator.js +2 -6
  161. package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
  162. package/dist/components/Pagination/pagination.js +1 -1
  163. package/dist/components/Pagination/pagination.js.map +1 -1
  164. package/dist/components/PeoplePicker/index.js +7 -1
  165. package/dist/components/PeoplePicker/index.js.map +1 -1
  166. package/dist/components/PeoplePicker/people-picker.d.ts +9 -2
  167. package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
  168. package/dist/components/PeoplePicker/people-picker.js +23 -10
  169. package/dist/components/PeoplePicker/people-picker.js.map +1 -1
  170. package/dist/components/PeoplePicker/person-display.d.ts +6 -3
  171. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  172. package/dist/components/PeoplePicker/person-display.js +19 -14
  173. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  174. package/dist/components/Popover/popover.d.ts.map +1 -1
  175. package/dist/components/Popover/popover.js +3 -1
  176. package/dist/components/Popover/popover.js.map +1 -1
  177. package/dist/components/ProfileCard/profile-card.d.ts +2 -2
  178. package/dist/components/ProfileCard/profile-card.js +3 -3
  179. package/dist/components/ProfileCard/profile-card.js.map +1 -1
  180. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  181. package/dist/components/RadioGroup/radio-group.js +15 -9
  182. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  183. package/dist/components/ScrollArea/scroll-area.d.ts +11 -1
  184. package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
  185. package/dist/components/ScrollArea/scroll-area.js +6 -3
  186. package/dist/components/ScrollArea/scroll-area.js.map +1 -1
  187. package/dist/components/Select/select.d.ts +46 -5
  188. package/dist/components/Select/select.d.ts.map +1 -1
  189. package/dist/components/Select/select.js +109 -28
  190. package/dist/components/Select/select.js.map +1 -1
  191. package/dist/components/SelectMenu/select-menu.d.ts +3 -1
  192. package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
  193. package/dist/components/SelectMenu/select-menu.js +8 -1
  194. package/dist/components/SelectMenu/select-menu.js.map +1 -1
  195. package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
  196. package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
  197. package/dist/components/SelectionControl/boolean-value.js +23 -0
  198. package/dist/components/SelectionControl/boolean-value.js.map +1 -0
  199. package/dist/components/SelectionControl/index.d.ts +1 -0
  200. package/dist/components/SelectionControl/index.d.ts.map +1 -1
  201. package/dist/components/SelectionControl/index.js +2 -0
  202. package/dist/components/SelectionControl/index.js.map +1 -1
  203. package/dist/components/Sheet/index.js +2 -1
  204. package/dist/components/Sheet/sheet.d.ts +7 -1
  205. package/dist/components/Sheet/sheet.d.ts.map +1 -1
  206. package/dist/components/Sheet/sheet.js +5 -2
  207. package/dist/components/Sheet/sheet.js.map +1 -1
  208. package/dist/components/Sidebar/sidebar.d.ts +9 -4
  209. package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
  210. package/dist/components/Sidebar/sidebar.js +8 -10
  211. package/dist/components/Sidebar/sidebar.js.map +1 -1
  212. package/dist/components/Slider/slider.d.ts.map +1 -1
  213. package/dist/components/Slider/slider.js.map +1 -1
  214. package/dist/components/Switch/switch.d.ts +6 -6
  215. package/dist/components/Switch/switch.d.ts.map +1 -1
  216. package/dist/components/Switch/switch.js +3 -2
  217. package/dist/components/Switch/switch.js.map +1 -1
  218. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  219. package/dist/components/Tabs/tabs.js +15 -1
  220. package/dist/components/Tabs/tabs.js.map +1 -1
  221. package/dist/components/Textarea/textarea.d.ts +2 -2
  222. package/dist/components/Textarea/textarea.d.ts.map +1 -1
  223. package/dist/components/Textarea/textarea.js +50 -42
  224. package/dist/components/Textarea/textarea.js.map +1 -1
  225. package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
  226. package/dist/components/TimePicker/time-columns.js +42 -38
  227. package/dist/components/TimePicker/time-columns.js.map +1 -1
  228. package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
  229. package/dist/components/TimePicker/time-picker.js +8 -6
  230. package/dist/components/TimePicker/time-picker.js.map +1 -1
  231. package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
  232. package/dist/components/Tooltip/tooltip.js +7 -5
  233. package/dist/components/Tooltip/tooltip.js.map +1 -1
  234. package/dist/components/TreeView/tree-view.d.ts +56 -1
  235. package/dist/components/TreeView/tree-view.d.ts.map +1 -1
  236. package/dist/components/TreeView/tree-view.js +211 -12
  237. package/dist/components/TreeView/tree-view.js.map +1 -1
  238. package/dist/index.d.ts +115 -58
  239. package/dist/index.d.ts.map +1 -1
  240. package/dist/index.js +95 -108
  241. package/dist/index.js.map +1 -1
  242. package/dist/patterns/element-anatomy/item-anatomy.d.ts +7 -6
  243. package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
  244. package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
  245. package/dist/tokens/categorical-color.js +15 -0
  246. package/dist/tokens/categorical-color.js.map +1 -1
  247. package/dist/tokens/motion/motion.d.ts +7 -6
  248. package/dist/tokens/motion/motion.d.ts.map +1 -1
  249. package/dist/tokens/motion/motion.js +6 -6
  250. package/dist/tokens/motion/motion.js.map +1 -1
  251. package/dist/tokens/motion/overlay-motion.d.ts +19 -0
  252. package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
  253. package/dist/tokens/motion/overlay-motion.js +9 -0
  254. package/dist/tokens/motion/overlay-motion.js.map +1 -0
  255. package/dist/tokens/uiSize/icon-size.js +5 -0
  256. package/dist/tokens/uiSize/icon-size.js.map +1 -0
  257. package/ds-canonical/fork/governance.lock +31 -19
  258. package/ds-canonical/fork/hooks/_log-fire.sh +46 -0
  259. package/ds-canonical/fork/hooks/block_prototype_imports.py +15 -4
  260. package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +145 -13
  261. package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +2 -1
  262. package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +47 -0
  263. package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +27 -0
  264. package/ds-canonical/fork/hooks/check_field_family_invariants.sh +61 -1
  265. package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +28 -4
  266. package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +28 -0
  267. package/ds-canonical/fork/hooks/check_story_determinism.sh +2 -0
  268. package/ds-canonical/fork/hooks/check_story_invariants.sh +119 -0
  269. package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  270. package/ds-canonical/fork/manifest.json +15 -0
  271. package/ds-canonical/fork/preamble.md +20 -18
  272. package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +3 -3
  273. package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
  274. package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +1 -1
  275. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
  276. package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
  277. package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
  278. package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
  279. package/ds-canonical/fork/skills/visual-audit/SKILL.md +2 -2
  280. package/ds-canonical/hooks/README.md +1 -1
  281. package/ds-canonical/hooks/block_prototype_imports.py +15 -4
  282. package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
  283. package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
  284. package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
  285. package/ds-canonical/hooks/check_datatable_invariants.sh +6 -3
  286. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +2 -1
  287. package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
  288. package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
  289. package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
  290. package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
  291. package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
  292. package/ds-canonical/hooks/check_opacity_token_usage.sh +28 -0
  293. package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
  294. package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
  295. package/ds-canonical/hooks/check_ssot_header_declaration.sh +3 -1
  296. package/ds-canonical/hooks/check_story_determinism.sh +2 -0
  297. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
  298. package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  299. package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
  300. package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
  301. package/ds-canonical/hooks/stop_self_audit.sh +31 -0
  302. package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
  303. package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
  304. package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
  305. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
  306. package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
  307. package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
  308. package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
  309. package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
  310. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +39 -0
  311. package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
  312. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
  313. package/ds-canonical/references/build-ui-canonicals.md +2 -1
  314. package/ds-canonical/references/failure-class-registry.json +145 -0
  315. package/ds-canonical/references/governance-audit-coverage.md +33 -0
  316. package/ds-canonical/references/item-anatomy-recipe.md +2 -2
  317. package/ds-canonical/references/scenario-definition.md +6 -9
  318. package/ds-canonical/references/ssot-consultation.md +2 -2
  319. package/ds-canonical/references/ssot-index.md +5 -4
  320. package/ds-canonical/references/story-baseline-registry.json +8 -2
  321. package/ds-canonical/references/structural-token-retention.md +6 -9
  322. package/ds-canonical/rules/meta-patterns.md +8 -8
  323. package/ds-canonical/rules/self-verify.md +4 -3
  324. package/ds-canonical/rules/story-rules.md +2 -2
  325. package/ds-canonical/rules/ui-development.md +2 -2
  326. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +3 -3
  327. package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
  328. package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
  329. package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
  330. package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
  331. package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
  332. package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
  333. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +51 -58
  334. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
  335. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
  336. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
  337. package/ds-canonical/skills/delivery-handoff/SKILL.md +1 -1
  338. package/ds-canonical/skills/design-system-audit/SKILL.md +26 -25
  339. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
  340. package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
  341. package/ds-canonical/skills/governance-health/SKILL.md +1 -1
  342. package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
  343. package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
  344. package/ds-canonical/skills/new-component/SKILL.md +5 -5
  345. package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
  346. package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
  347. package/ds-canonical/skills/propose-options/SKILL.md +3 -3
  348. package/ds-canonical/skills/prototype/SKILL.md +1 -1
  349. package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
  350. package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
  351. package/ds-canonical/skills/story-writing/SKILL.md +3 -3
  352. package/ds-canonical/skills/visual-audit/SKILL.md +2 -2
  353. package/ds-story-manifest.json +29 -20
  354. package/llms-full.txt +22 -1
  355. package/llms.txt +5 -4
  356. package/package.json +7 -3
  357. package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
  358. package/src/components/Accordion/accordion.stories.tsx +16 -1
  359. package/src/components/Alert/alert.principles.stories.tsx +1 -1
  360. package/src/components/Alert/alert.spec.md +8 -10
  361. package/src/components/Alert/alert.stories.tsx +28 -28
  362. package/src/components/Alert/alert.tsx +1 -1
  363. package/src/components/AppShell/_demo-helpers.tsx +6 -3
  364. package/src/components/AppShell/app-shell.spec.md +4 -4
  365. package/src/components/AppShell/app-shell.tsx +28 -2
  366. package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
  367. package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
  368. package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
  369. package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
  370. package/src/components/Avatar/avatar.spec.md +2 -2
  371. package/src/components/Avatar/avatar.stories.tsx +8 -6
  372. package/src/components/Avatar/avatar.tsx +13 -5
  373. package/src/components/Badge/badge.principles.stories.tsx +1 -1
  374. package/src/components/Badge/badge.spec.md +2 -0
  375. package/src/components/Badge/badge.stories.tsx +4 -2
  376. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
  377. package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
  378. package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
  379. package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
  380. package/src/components/Button/button.principles.stories.tsx +1 -1
  381. package/src/components/Button/button.spec.md +2 -2
  382. package/src/components/Button/button.tsx +18 -3
  383. package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
  384. package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
  385. package/src/components/Calendar/calendar.spec.md +5 -4
  386. package/src/components/Calendar/calendar.stories.tsx +7 -4
  387. package/src/components/Calendar/calendar.tsx +26 -7
  388. package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
  389. package/src/components/Carousel/carousel.spec.md +2 -2
  390. package/src/components/Carousel/carousel.tsx +11 -3
  391. package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
  392. package/src/components/Chart/chart.principles.stories.tsx +1 -1
  393. package/src/components/Chart/chart.stories.tsx +2 -8
  394. package/src/components/Chart/chart.tsx +3 -0
  395. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
  396. package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
  397. package/src/components/Checkbox/checkbox.spec.md +13 -26
  398. package/src/components/Checkbox/checkbox.stories.tsx +11 -8
  399. package/src/components/Checkbox/checkbox.tsx +18 -13
  400. package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
  401. package/src/components/Chip/chip.principles.stories.tsx +1 -1
  402. package/src/components/Chip/chip.spec.md +5 -4
  403. package/src/components/Chip/chip.tsx +5 -1
  404. package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
  405. package/src/components/CircularProgress/circular-progress.spec.md +3 -3
  406. package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
  407. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
  408. package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
  409. package/src/components/Coachmark/coachmark.spec.md +5 -5
  410. package/src/components/Coachmark/coachmark.stories.tsx +3 -1
  411. package/src/components/Coachmark/coachmark.tsx +10 -3
  412. package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
  413. package/src/components/Combobox/combobox.tsx +53 -19
  414. package/src/components/Command/command.anatomy.stories.tsx +2 -2
  415. package/src/components/Command/command.principles.stories.tsx +1 -1
  416. package/src/components/Command/command.stories.tsx +42 -10
  417. package/src/components/DataTable/cell-registry.tsx +86 -63
  418. package/src/components/DataTable/column-types.ts +10 -1
  419. package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
  420. package/src/components/DataTable/data-table-filter-group.tsx +231 -0
  421. package/src/components/DataTable/data-table-filter-panel.tsx +16 -430
  422. package/src/components/DataTable/data-table-filter-value-picker.tsx +237 -0
  423. package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
  424. package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
  425. package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
  426. package/src/components/DataTable/data-table.spec.md +33 -13
  427. package/src/components/DataTable/data-table.stories.tsx +16 -17
  428. package/src/components/DataTable/data-table.tsx +107 -61
  429. package/src/components/DataTable/filter-operators.spec.md +3 -3
  430. package/src/components/DataTable/index.ts +3 -0
  431. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
  432. package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
  433. package/src/components/DateGrid/date-grid.spec.md +1 -1
  434. package/src/components/DateGrid/date-grid.tsx +3 -1
  435. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
  436. package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
  437. package/src/components/DatePicker/date-picker.spec.md +3 -3
  438. package/src/components/DatePicker/date-picker.stories.tsx +4 -5
  439. package/src/components/DatePicker/date-picker.tsx +99 -45
  440. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
  441. package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
  442. package/src/components/DescriptionList/description-list.spec.md +3 -3
  443. package/src/components/DescriptionList/description-list.stories.tsx +7 -6
  444. package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
  445. package/src/components/Dialog/dialog.spec.md +9 -0
  446. package/src/components/Dialog/dialog.stories.tsx +66 -5
  447. package/src/components/Dialog/dialog.tsx +60 -25
  448. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
  449. package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
  450. package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
  451. package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
  452. package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
  453. package/src/components/Empty/empty.spec.md +2 -2
  454. package/src/components/Field/field-context.ts +69 -5
  455. package/src/components/Field/field-controls.spec.md +62 -8
  456. package/src/components/Field/field-edit-keys.ts +66 -0
  457. package/src/components/Field/field-types.ts +58 -9
  458. package/src/components/Field/field-wrapper.tsx +50 -42
  459. package/src/components/Field/field.anatomy.stories.tsx +9 -6
  460. package/src/components/Field/field.spec.md +1 -1
  461. package/src/components/Field/field.stories.tsx +1 -1
  462. package/src/components/Field/field.tsx +2 -1
  463. package/src/components/Field/form-validation.spec.md +3 -3
  464. package/src/components/Field/index.ts +1 -0
  465. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
  466. package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
  467. package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
  468. package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
  469. package/src/components/FileItem/file-item.spec.md +5 -8
  470. package/src/components/FileItem/file-item.stories.tsx +36 -25
  471. package/src/components/FileItem/file-item.tsx +8 -6
  472. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
  473. package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
  474. package/src/components/FileUpload/file-upload.spec.md +1 -1
  475. package/src/components/FileUpload/file-upload.tsx +1 -1
  476. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
  477. package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
  478. package/src/components/FileViewer/file-viewer.spec.md +30 -12
  479. package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
  480. package/src/components/FileViewer/file-viewer.tsx +12 -4
  481. package/src/components/FileViewer/image-renderer.tsx +35 -7
  482. package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
  483. package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
  484. package/src/components/HoverCard/hover-card.spec.md +5 -5
  485. package/src/components/HoverCard/hover-card.stories.tsx +16 -16
  486. package/src/components/HoverCard/hover-card.tsx +5 -3
  487. package/src/components/InlineEdit/index.ts +5 -0
  488. package/src/components/InlineEdit/inline-edit.spec.md +149 -0
  489. package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
  490. package/src/components/InlineEdit/inline-edit.tsx +287 -0
  491. package/src/components/Input/input.anatomy.stories.tsx +8 -7
  492. package/src/components/Input/input.principles.stories.tsx +2 -12
  493. package/src/components/Input/input.spec.md +13 -18
  494. package/src/components/Input/input.tsx +69 -22
  495. package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
  496. package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
  497. package/src/components/LinkInput/link-input.tsx +11 -10
  498. package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
  499. package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
  500. package/src/components/Menu/menu-item.spec.md +22 -15
  501. package/src/components/Menu/menu-item.stories.tsx +39 -11
  502. package/src/components/Menu/menu-item.tsx +38 -4
  503. package/src/components/Notice/notice.principles.stories.tsx +1 -1
  504. package/src/components/Notice/notice.spec.md +16 -3
  505. package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
  506. package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
  507. package/src/components/NumberInput/number-input.spec.md +4 -4
  508. package/src/components/NumberInput/number-input.tsx +19 -12
  509. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
  510. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
  511. package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
  512. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
  513. package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
  514. package/src/components/Pagination/pagination.spec.md +1 -1
  515. package/src/components/Pagination/pagination.stories.tsx +2 -6
  516. package/src/components/Pagination/pagination.tsx +1 -1
  517. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
  518. package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
  519. package/src/components/PeoplePicker/people-picker.spec.md +6 -6
  520. package/src/components/PeoplePicker/people-picker.tsx +56 -16
  521. package/src/components/PeoplePicker/person-display.tsx +32 -16
  522. package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
  523. package/src/components/Popover/popover.tsx +3 -1
  524. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
  525. package/src/components/ProfileCard/profile-card.spec.md +3 -3
  526. package/src/components/ProfileCard/profile-card.tsx +6 -6
  527. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
  528. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
  529. package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
  530. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
  531. package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
  532. package/src/components/RadioGroup/radio-group.tsx +41 -15
  533. package/src/components/Rating/rating.spec.md +11 -3
  534. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  535. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
  536. package/src/components/ScrollArea/scroll-area.spec.md +7 -3
  537. package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
  538. package/src/components/ScrollArea/scroll-area.tsx +17 -4
  539. package/src/components/Select/select.anatomy.stories.tsx +3 -3
  540. package/src/components/Select/select.spec.md +29 -17
  541. package/src/components/Select/select.stories.tsx +33 -0
  542. package/src/components/Select/select.tsx +190 -36
  543. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
  544. package/src/components/SelectMenu/select-menu.spec.md +15 -7
  545. package/src/components/SelectMenu/select-menu.tsx +16 -3
  546. package/src/components/SelectionControl/boolean-value.tsx +39 -0
  547. package/src/components/SelectionControl/index.ts +1 -0
  548. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
  549. package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
  550. package/src/components/SelectionControl/selection-item.spec.md +3 -3
  551. package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
  552. package/src/components/Separator/separator.spec.md +2 -2
  553. package/src/components/Separator/separator.stories.tsx +6 -27
  554. package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
  555. package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
  556. package/src/components/Sheet/sheet.spec.md +2 -2
  557. package/src/components/Sheet/sheet.tsx +9 -5
  558. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
  559. package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
  560. package/src/components/Sidebar/sidebar.spec.md +13 -15
  561. package/src/components/Sidebar/sidebar.stories.tsx +8 -7
  562. package/src/components/Sidebar/sidebar.tsx +37 -25
  563. package/src/components/Skeleton/skeleton.stories.tsx +4 -11
  564. package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
  565. package/src/components/Slider/slider.principles.stories.tsx +2 -2
  566. package/src/components/Slider/slider.spec.md +5 -5
  567. package/src/components/Slider/slider.tsx +3 -1
  568. package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
  569. package/src/components/Steps/steps.principles.stories.tsx +1 -1
  570. package/src/components/Steps/steps.spec.md +1 -1
  571. package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
  572. package/src/components/Switch/switch.principles.stories.tsx +4 -4
  573. package/src/components/Switch/switch.spec.md +8 -8
  574. package/src/components/Switch/switch.stories.tsx +9 -24
  575. package/src/components/Switch/switch.tsx +17 -13
  576. package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
  577. package/src/components/Tabs/tabs.spec.md +1 -1
  578. package/src/components/Tabs/tabs.tsx +21 -1
  579. package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
  580. package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
  581. package/src/components/Textarea/textarea.spec.md +4 -4
  582. package/src/components/Textarea/textarea.tsx +72 -46
  583. package/src/components/TimePicker/time-columns.tsx +6 -2
  584. package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
  585. package/src/components/TimePicker/time-picker.spec.md +3 -3
  586. package/src/components/TimePicker/time-picker.tsx +16 -10
  587. package/src/components/Toast/toast.stories.tsx +7 -4
  588. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
  589. package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
  590. package/src/components/Tooltip/tooltip.spec.md +1 -1
  591. package/src/components/Tooltip/tooltip.stories.tsx +4 -39
  592. package/src/components/Tooltip/tooltip.tsx +8 -6
  593. package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
  594. package/src/components/TreeView/tree-view.spec.md +42 -11
  595. package/src/components/TreeView/tree-view.stories.tsx +1 -0
  596. package/src/components/TreeView/tree-view.tsx +322 -17
  597. package/src/index.ts +588 -60
  598. package/src/patterns/action-bar/action-bar.spec.md +9 -0
  599. package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
  600. package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
  601. package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
  602. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
  603. package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
  604. package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
  605. package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
  606. package/src/styles/tokens.css +3 -0
  607. package/src/tokens/README.md +1 -1
  608. package/src/tokens/color/color.spec.md +4 -4
  609. package/src/tokens/color/color.stories.tsx +3 -3
  610. package/src/tokens/density/density.stories.tsx +16 -3
  611. package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
  612. package/src/tokens/motion/motion.css +33 -21
  613. package/src/tokens/motion/motion.spec.md +32 -15
  614. package/src/tokens/motion/motion.stories.tsx +58 -5
  615. package/src/tokens/motion/motion.ts +7 -6
  616. package/src/tokens/motion/overlay-motion.ts +26 -0
  617. package/src/tokens/orphan-tokens.spec.md +4 -4
  618. package/src/tokens/token-system.spec.md +1 -0
  619. package/src/tokens/uiSize/uiSize.css +1 -1
  620. package/src/tokens/uiSize/uiSize.spec.md +1 -1
  621. package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
  622. package/src/tokens/utility-registry.json +160 -23
@@ -1,12 +1,13 @@
1
1
  #!/bin/bash
2
2
  # Field family unified invariant hook(2026-05-08 cluster A consolidation)
3
3
  #
4
- # Merges PreToolUse hooks(原各檔已 retire,合併入此)— 共 5 條 sub-rules:
4
+ # Merges PreToolUse hooks(原各檔已 retire,合併入此)— 共 6 條 sub-rules:
5
5
  # A.1 naked row-mode propagation(原 check_naked_row_mode_propagation,P0 BLOCKER)
6
6
  # A.2 FieldControlGroup wrapper direct child(原 check_field_control_group_direct_child,P1 WARN)
7
7
  # A.3 Field state ring SSOT(原 check_field_state_token_consume 3 sub-rules,P0 BLOCKER)
8
8
  # A.4 disabled placeholder color(原 check_disabled_placeholder_color,P1 stderr only)
9
9
  # A.5 _Group child fieldCtx.id 隔離(2026-05-31 折入,M4 AR34 regression detector,P0 BLOCKER)
10
+ # A.6 空值顯示 SSOT(2026-07-08 user 拍板半形 hyphen,P0 BLOCKER)
10
11
  #
11
12
  # Why merge:皆 Field 家族 invariant,共用 INPUT parsing + Edit/Write filter pattern,
12
13
  # 分散在 4 個 hook 是「散裝 SSOT」(M17 + Anthropic ≤ 15 hook best practice 違反)。
@@ -19,6 +20,7 @@
19
20
  # A.3: `// @field-state-ring-allow: <reason>`
20
21
  # A.4: `// @disabled-color-allow: <reason>`
21
22
  # A.5: `// @group-fieldctx-allow: <reason>`
23
+ # A.6: `// @empty-display-allow: <reason>`
22
24
 
23
25
  source "$(dirname "$0")/_log-fire.sh" 2>/dev/null && log_hook_fire
24
26
 
@@ -247,4 +249,62 @@ EOF
247
249
  ;;
248
250
  esac
249
251
 
252
+ # ── A.6 空值顯示 SSOT(P0 BLOCKER,2026-07-08 user 拍板半形 hyphen)────────────────
253
+ # user verbatim「我從頭到尾哪裡有說要用全形的」+ 五情境空值框架。SSOT:符號常數 =
254
+ # field-wrapper.tsx `EMPTY_DISPLAY = '-'`(U+002D 半形);分流 hook = field-context.ts
255
+ # `useFieldEmptyDisplay()`。禁 2 shape:
256
+ # A.6.1 非 owner 檔直接 import `EMPTY_DISPLAY` 常數(應消費 hook 分流,否則 table-cell
257
+ # editable→'' 分流會漏);
258
+ # A.6.2 components/ tsx display 路徑 hardcode 全形 em dash `'—'`/`"—"`(U+2014)字面。
259
+ # M7 broad-vs-narrow:spec wording 廣(「禁 hardcode 空值符號」);hook 取「quoted em dash 字面」
260
+ # 高信號 subset + owner skip + comment 剝離 + `@empty-display-allow` escape,零誤判導向。
261
+ if ! echo "$NEW_CONTENT" | grep -q '@empty-display-allow'; then
262
+ # A.6.1 非 owner 檔 import EMPTY_DISPLAY 常數(剝離註解行)
263
+ case "$FILE_PATH" in
264
+ */field-context.ts|*/field-wrapper.tsx) ;; # SSOT owner(定義 + 分流 hook)skip
265
+ *)
266
+ A61_CONTENT=$(echo "$NEW_CONTENT" | grep -vE '^[[:space:]]*(//|\*|/\*)')
267
+ if printf '%s' "$A61_CONTENT" | grep -E "import.*EMPTY_DISPLAY|EMPTY_DISPLAY.*from" >/dev/null; then
268
+ cat >&2 <<EOF
269
+
270
+ ┄┄┄ A.6.1 check_field_family_invariants — EMPTY_DISPLAY 直引 BLOCKER ┄┄┄
271
+
272
+ [P0] ${FILE_PATH}
273
+ 偵測到直接 import \`EMPTY_DISPLAY\` 常數(非 field-context.ts owner)。
274
+ 空值顯示必經 \`useFieldEmptyDisplay()\` hook 分流(table-cell 可編輯→空白 / 其餘→半形 '-'),
275
+ 直引常數會漏 surface × editable 分流。
276
+
277
+ 修法:import { useFieldEmptyDisplay } from '@/design-system/components/Field/field-context'
278
+ const emptyDisplay = useFieldEmptyDisplay()
279
+ 例外:行尾 \`// @empty-display-allow: <reason>\`
280
+
281
+ EOF
282
+ record_worst 2
283
+ fi
284
+ ;;
285
+ esac
286
+ # A.6.2 components/ tsx hardcode 全形 em dash 空值字面(剝離註解行 + owner/story skip)
287
+ case "$FILE_PATH" in
288
+ *.stories.tsx|*/field-context.ts|*/field-wrapper.tsx) ;; # doc N/A marker + SSOT owner skip
289
+ *components/*.tsx)
290
+ A62_CONTENT=$(echo "$NEW_CONTENT" | grep -vE '^[[:space:]]*(//|\*|/\*)')
291
+ if printf '%s' "$A62_CONTENT" | grep -E "['\"]—['\"]" >/dev/null; then
292
+ cat >&2 <<EOF
293
+
294
+ ┄┄┄ A.6.2 check_field_family_invariants — 全形 em dash 空值 BLOCKER ┄┄┄
295
+
296
+ [P0] ${FILE_PATH}
297
+ 偵測到 components/ 實作檔 hardcode 全形 em dash \`'—'\`(U+2014)字面。
298
+ user 2026-07-08 拍板:空值符號 = **半形 hyphen '-'(U+002D)**,禁全形。
299
+
300
+ 修法:空值一律 \`{value ?? emptyDisplay}\`(emptyDisplay = useFieldEmptyDisplay()),不 hardcode 符號。
301
+ 例外:行尾 \`// @empty-display-allow: <reason>\`
302
+
303
+ EOF
304
+ record_worst 2
305
+ fi
306
+ ;;
307
+ esac
308
+ fi
309
+
250
310
  exit $WORST
@@ -43,7 +43,31 @@ ESCAPE_MARKER='@layout-space-magic-ok:'
43
43
 
44
44
  # Detect magic spacing classes (Tailwind class strings only — NOT JSX props like size={24})
45
45
  # Match per line so we can check per-line escape comments
46
- MAGIC_LINES=$(echo "$NEW_CONTENT" | grep -nE '\b(p|px|py|pt|pb|pl|pr|gap|space-x|space-y|m|mx|my|mt|mb|ml|mr)-(0\.5|[1-9][0-9]?(\.[0-9])?)\b')
46
+ # 2026-07-08 WM 戰役 R4 擴 scope(broad-vs-narrow gap 實證修補):
47
+ # (a) logical properties ps-/pe-/ms-/me-(WM 6 筆 ps-4 漏網實證)
48
+ # (b) arbitrary bracket 固定 px:gap-[7px] / p-[13px] 類(spacing 家族)
49
+ # (c) 固定寬度 w-[Npx](WM w-[640px] 丟失 min() viewport clamp 實證;w-[min(...)]/var()/% 不攔)
50
+ # (d) grid-template 固定 px 欄寬:grid-cols-[...Npx...](WM mini-table 88px/72px 黏死實證)
51
+ MAGIC_LINES=$(echo "$NEW_CONTENT" | grep -nE '\b(p|px|py|pt|pb|pl|pr|ps|pe|gap|space-x|space-y|m|mx|my|mt|mb|ml|mr|ms|me)-(0\.5|[1-9][0-9]?(\.[0-9])?)\b|\b(p|px|py|pt|pb|pl|pr|ps|pe|gap|m|mx|my|mt|mb|ml|mr|ms|me)-\[[0-9]+(\.[0-9]+)?px\]|\bw-\[[0-9]+(\.[0-9]+)?px\]|\bgrid-(cols|rows)-\[[^]]*[0-9]+px[^]]*\]')
52
+
53
+ # ── 幻覺 token 攔截(2026-07-08 WM 戰役:app 自創 var(--layout-space-distant) → CSS 未定義
54
+ # silent 解析 0 → 區塊全黏死,PDF「全部擠在一起」根因之一。白名單 = loose|tight|bottom
55
+ # (layoutSpace.css SSOT 僅此三顆;新增 tier 走 DS token 流程,不在 consumer 端發明)──
56
+ PHANTOM=$(echo "$NEW_CONTENT" | grep -nE 'var\(--layout-space-[a-z-]+\)' | grep -vE 'var\(--layout-space-(loose|tight|bottom)\)' || true)
57
+ if [ -n "$PHANTOM" ]; then
58
+ cat >&2 <<EOF_PH
59
+ 🚨 [P0 BLOCKER] 幻覺 layout-space token(CSS 未定義 = silent 0 = 佈局黏死):
60
+ $PHANTOM
61
+ → 白名單只有 --layout-space-{loose,tight,bottom}(layoutSpace.css SSOT)。
62
+ 要更大一級間距 → 用 loose;真需新 tier → 走 DS token 新增流程(layoutSpace.spec),禁 consumer 端自創。
63
+ Anchor:2026-07-08 WM --layout-space-distant ×4 處,整個 detail modal 區塊黏死。
64
+ EOF_PH
65
+ exit 2
66
+ fi
67
+
68
+ # 2026-07-10 批次 A:divider 幾何 canonical(h-6 mx-1 / h-5 mx-1,action-bar.spec.md「分隔線幾何」)
69
+ # 是**正解**,不該被 magic-number 攔(原本懲罰 canonical 修法、放行違規 = 治理自我打架)。
70
+ MAGIC_LINES=$(echo "$MAGIC_LINES" | grep -vE '(Separator|ButtonDivider)' || true)
47
71
 
48
72
  if [ -z "$MAGIC_LINES" ]; then
49
73
  exit 0
@@ -82,9 +106,9 @@ $(echo -e "$UNJUSTIFIED" | sed 's/^/ /' | head -10)
82
106
  per app-shell.spec.md L205-219 + layoutSpace.spec.md SSOT:consumer content 必遵循
83
107
  layoutSpace 6 條規則 + 親疏 3 級,**禁** 硬寫 Tailwind magic numbers。改用:
84
108
  p-[var(--layout-space-loose)] /* 16px 規則 1A/1B chrome / wrap */
85
- p-[var(--layout-space-tight)] /* 12px 規則 3 親 gap */
86
- gap-[var(--layout-space-distant)] /* 24px 規則 3 疏 gap */
87
- space-y-[var(--layout-space-distant)]
109
+ gap-[var(--layout-space-tight)] /* 12px 規則 3 親 gap(跨範疇相關) */
110
+ gap-[var(--layout-space-loose)] /* 16px 規則 3 疏 gap(跨範疇 parallel;lg 密度自動 24px) */
111
+ (token 全集 = loose/tight/bottom,無其他級 — 自創 --layout-space-distant 類 = 幻覺 token,本 hook 會攔)
88
112
 
89
113
  修法 2 選 1:
90
114
  (a) 改 token:換成 var(--layout-space-N) N∈{loose,tight} family per 6 規則 + 親疏 3 級
@@ -136,7 +136,7 @@ case "$FILE_PATH" in
136
136
  */components/Tag/*|*/components/Avatar/*|*/components/Chart/*|*/tokens/*) ;; # codified primitive-consumer skip
137
137
  *)
138
138
  if ! echo "$NEW_CONTENT" | grep -q 'primitive-color-allow-blanket'; then
139
- VIOLATIONS_D3=$(printf '%s' "$NEW_CONTENT" | grep -nE 'var\(--color-[a-z]+-[0-9](-opaque)?\)' | grep -v 'primitive-color-allow' || true)
139
+ VIOLATIONS_D3=$(printf '%s' "$NEW_CONTENT" | grep -nE 'var\(--color-[a-z][a-z-]*-[0-9]{1,2}(-opaque)?\)' | grep -v 'primitive-color-allow' || true)
140
140
  if [ -n "$VIOLATIONS_D3" ]; then
141
141
  cat >&2 <<EOF
142
142
 
@@ -135,6 +135,24 @@ if [ -n "$HITS_PRIMITIVE" ]; then
135
135
  VIOLATIONS="${VIOLATIONS}\n [primitive color as utility] $(echo "$HITS_PRIMITIVE" | tr '\n' ' ')"
136
136
  fi
137
137
 
138
+ # 10) 幻覺 semantic state 尾綴(2026-07-10 批次 A C1:WM hover:bg-neutral-hovered ×3 檔 silent no-op 實證。
139
+ # 真尾綴只有 -hover/-active/-selected(+ selected-hover/selected-active);過去式/-pressed 全幻覺,
140
+ # Tailwind 靜默不生成 → hover 無效果、build 不報錯)
141
+ HITS_PHANTOM_STATE=$(echo "$NEW_CONTENT" | grep -oE "\b(hover:|active:|focus:)?(bg|text|border|ring)-[a-z][a-z-]*-(hovered|actived|focussed|pressed)\b" | sort -u || true)
142
+ if [ -n "$HITS_PHANTOM_STATE" ]; then
143
+ VIOLATIONS="${VIOLATIONS}\n [phantom state suffix(silent no-op)] $(echo "$HITS_PHANTOM_STATE" | tr '\n' ' ')"
144
+ fi
145
+
146
+ # 11) micro gap(<4px)+ registry fraction width(#71 2026-07-11 接線)——
147
+ # registry micro_gap / fraction 的 rationale 明寫「flag for human review」(非硬禁)→ 走
148
+ # SOFT WARN 非 block(避免誤殺 Calendar/Chart/FileViewer/Carousel 等 4 個既有合法 micro-gap 用途)。
149
+ # fraction 用 registry 明列 14 條(w-1/3.. 不含 w-1/2 = 合法留白),避免廣捕 w-N/M 誤殺。
150
+ HITS_MICROGAP=$(echo "$NEW_CONTENT" | grep -oE "\bgap-(px|0\.5|1\.5)\b" | sort -u || true)
151
+ HITS_FRACTION=$(echo "$NEW_CONTENT" | grep -oE "\bw-(1/3|2/3|1/4|3/4|1/5|2/5|3/5|4/5|1/6|5/6|1/12|5/12|7/12|11/12)\b" | sort -u || true)
152
+ SOFT_NOTES=""
153
+ [ -n "$HITS_MICROGAP" ] && SOFT_NOTES="${SOFT_NOTES}\n [micro gap <4px] $(echo "$HITS_MICROGAP" | tr '\n' ' ')"
154
+ [ -n "$HITS_FRACTION" ] && SOFT_NOTES="${SOFT_NOTES}\n [fraction width] $(echo "$HITS_FRACTION" | tr '\n' ' ')"
155
+
138
156
  if [ -n "$VIOLATIONS" ]; then
139
157
  cat >&2 <<'EOF_HEAD'
140
158
 
@@ -160,7 +178,17 @@ EOF_HEAD
160
178
  EOF_BODY
161
179
  # P0 BLOCKER(2026-07-07 治理進化方向 2:對齊 user 2026-05-27「SSOT canonical 必 P0」doctrine;
162
180
  # 檔級豁免(anatomy/principles stories / token 自家)+ 行級 escape 已備,升級不增誤殺)
181
+ # micro-gap/fraction soft note 附在硬 block 訊息尾(一起讓 AI 看到,但不影響 exit code 判定)
182
+ [ -n "$SOFT_NOTES" ] && { echo "" >&2; echo " (另有 soft flag,非 block 原因):" >&2; echo -e "$SOFT_NOTES" >&2; }
163
183
  exit 2
164
184
  fi
165
185
 
186
+ # 只有 micro-gap / fraction soft note(無硬 violation)→ WARN 非 block(registry rationale「flag for human review」)
187
+ if [ -n "$SOFT_NOTES" ]; then
188
+ echo "" >&2
189
+ echo "⚠️ Dim 47 soft flag(registry micro_gap / fraction「flag for human review」— 非 block,#71 接線):" >&2
190
+ echo -e "$SOFT_NOTES" >&2
191
+ echo " <4px gap / registry fraction width 常違反 item-anatomy slot 幾何 / layout SSOT → 人工 review。合理則行尾 @token-registry-ok: <rationale>。" >&2
192
+ fi
193
+
166
194
  exit 0
@@ -6,7 +6,8 @@
6
6
  # `getAttribute('data-state')` / `class.includes('items-start')` attribute-existence
7
7
  # = false-positive trap(DOM-structure-pass ≠ visual-pass)。
8
8
  #
9
- # Mechanical rule:scripts/visual-audit-*.mjs(or *.js)若有 `getAttribute(` 但沒 paired
9
+ # Mechanical rule:scripts/visual-audit*.mjs(or *.js;含 canonical scripts/visual-audit.mjs,
10
+ # 舊 visual-audit-<target>.mjs 家族已於 2026-05-30 a2360e99 整批 retire)若有 `getAttribute(` 但沒 paired
10
11
  # `getBoundingClientRect(` 或 `offsetTop/.offsetHeight` 量化 measurement → warn。
11
12
  #
12
13
  # 對齊 Material X-DataGrid visual regression / AG Grid playwright pixel snapshot canonical。
@@ -21,7 +22,7 @@ EVENT=$(echo "$INPUT" | jq -r '.hook_event_name // ""' 2>/dev/null)
21
22
 
22
23
  case "$TOOL" in Edit|Write|MultiEdit) ;; *) exit 0 ;; esac
23
24
  case "$FILE_PATH" in
24
- */scripts/visual-audit-*.mjs|*/scripts/visual-audit-*.js) ;;
25
+ */scripts/visual-audit*.mjs|*/scripts/visual-audit*.js) ;;
25
26
  *) exit 0 ;;
26
27
  esac
27
28
  [ "$EVENT" != "PostToolUse" ] && exit 0
@@ -63,7 +63,10 @@ SSOT_COUNT=$(echo "$SSOT_DIFF" | wc -l | tr -d ' ')
63
63
  # Read current package version
64
64
  PKG_VERSION=$(jq -r '.version' "$CWD/packages/design-system/package.json" 2>/dev/null || echo "unknown")
65
65
 
66
- cat <<EOF
66
+ # 2026-07-11 #79 修:PostToolUse 純 stdout **不注入 AI context**(只進 transcript)→ 原 heredoc 的
67
+ # 「AI 必全自動執行」提議到不了 AI = 假 inject。對齊 inject_deploy_url_after_push.sh:236 root-cause fix,
68
+ # 收進 MSG 後用 jq hookSpecificOutput.additionalContext 真注入。
69
+ MSG=$(cat <<EOF
67
70
  🔄 SSOT propagation gate(post push origin main):
68
71
 
69
72
  📊 偵測:HEAD~1..HEAD 含 $SSOT_COUNT 個 SSOT-affecting file changes
@@ -87,4 +90,6 @@ AI 全自動執行步驟(user 已給 merge trigger → 以下不需再問;user
87
90
  - .claude/skills/knowledge-prune/SKILL.md「Phase Z」reference
88
91
  - .claude/skills/deep-audit-cross-codex/SKILL.md「Phase C」reference
89
92
  EOF
93
+ )
94
+ jq -n --arg ctx "$MSG" '{hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:$ctx}}'
90
95
  exit 0
@@ -3,7 +3,7 @@
3
3
  # (2026-07-07 治理進化方向 3 洞 a:原 check_ssot_consultation.sh 2026-05-XX retired 後,
4
4
  # CLAUDE.md「# SSOT 消費 canonical」+ ssot-consultation.md:30-51 強制的檔頭宣告段
5
5
  # **無任何機械驗證** — 內部盤點實證。本 hook = 精簡復活版,只驗「新檔有無宣告段」,
6
- # 不驗宣告品質(品質靠 audit dim 1 + M18/M29)。)
6
+ # 不驗宣告品質(品質靠 audit dim 5 + dim 54 + M18/M29)。)
7
7
  #
8
8
  # Scope(ratchet,對齊 Polaris stylelint-adoption 策略):
9
9
  # - 只攔 **Write 新檔**(components/ patterns/ 的 .tsx,磁碟上不存在)— 存量檔 Edit 豁免
@@ -11,6 +11,8 @@
11
11
  # - escape:內容含 `@ssot-header-exempt: <rationale>`(audit 可追)
12
12
  # P0 BLOCKER(user 2026-05-27「SSOT canonical 必 P0」doctrine)。
13
13
 
14
+ source "$(dirname "$0")/_log-fire.sh" 2>/dev/null && log_hook_fire
15
+
14
16
  set -euo pipefail
15
17
 
16
18
  INPUT=$(cat)
@@ -11,6 +11,8 @@
11
11
  # 第一期 WARN(exit 0):存量 10 檔(dry-run 2026-07-07,DateGrid 家族為主)未清,
12
12
  # 誤殺率驗證期後升 P0(對齊 handcraft 偵測同節奏;roadmap 方向 1 KPI 隨頻回顧)。
13
13
 
14
+ source "$(dirname "$0")/_log-fire.sh" 2>/dev/null && log_hook_fire
15
+
14
16
  set -euo pipefail
15
17
  INPUT=$(cat)
16
18
  TOOL=$(echo "$INPUT" | jq -r '.tool_name // ""')
@@ -2,19 +2,20 @@
2
2
  # check_substantive_edit_approval_preflight.sh — Pre-action gate for substantive design edits.
3
3
  #
4
4
  # Purpose: PRE-flight 偵測 packages/design-system/src/**.{tsx,ts,css} edit + last 5 user msgs 無
5
- # approval keyword → SOFT inject context warning。
5
+ # approval keyword → P0 BLOCKER(stderr + exit 2;2026-05-15 由 soft warn 升級,
6
+ # per memory/feedback_ship_then_revert_anti_pattern.md SSOT)。
6
7
  #
7
- # 對比 stop_self_audit.sh post-action BLOCKER:本 hook 是 PRE-action soft warn,
8
- # AI 看到 context 後 self-decide(propose-only OR cite approval verbatim),
8
+ # 對比 stop_self_audit.sh post-action BLOCKER:本 hook 是 PRE-action gate,
9
+ # edit 落地前就攔(propose-only OR cite approval verbatim + bypass env),
9
10
  # 避免「edit → stop hook BLOCKER → revert」waste cycle(user 抓 2026-05-12 anti-pattern)。
10
11
  #
11
12
  # 對齊 Option 3 hybrid(M32 split 後 (f) ship gate 的 PRE-flight 補位):
12
- # - PreToolUse soft warn = info inject(本 hook)
13
- # - Stop hook BLOCKER = enforcement(stop_self_audit.sh Mechanism 4)
13
+ # - PreToolUse P0 BLOCKER = pre-action enforcement(本 hook)
14
+ # - Stop hook BLOCKER = post-action backstop(stop_self_audit.sh Mechanism 4)
14
15
  # - AI inline self-statement = discipline(M31 Layer A/C marker + 本 hook context)
15
16
  #
16
- # Why pre-action soft instead of hard BLOCK:false-positive 風險(legit bug fix 可能撞)+
17
- # inject info reject 更尊重 AI judgment + 配合 existing stop hook backstop
17
+ # False-positive escape:CLAUDE_BYPASS_DESIGN_APPROVAL=1(audit-logged logs/approval-bypass.jsonl),
18
+ # cite user approval verbatim quote commit message + reply
18
19
  #
19
20
  # 對齊:CLAUDE.md `# 稽核 canonical` Audit-vs-execute 分權 + M31 Layer A/C + M32(f) ship gate。
20
21
 
@@ -52,6 +52,34 @@ if ! echo "$FILE" | grep -qE '(packages/design-system/src/|/apps/|(^|/)apps/)';
52
52
  CONTENT=$(cat "$FILE" 2>/dev/null)
53
53
  [ -z "$CONTENT" ] && exit 0
54
54
 
55
+ # ── Check 3(2026-07-08 WM 戰役 R4:root 偵測,不只 symptom)──
56
+ # WM 實證:app 把 TabsList 塞 DialogBody + `!pt-0` hack 對抗 primitive,TabsContent 加了 mt-0
57
+ # 就繞過 Check 2 —— 但 root 錯誤是「沒用 DialogHeader tabsSlot canonical」(雙線 + 底線內縮 +
58
+ # spacing owner 自組)。偵測兩個 root 簽名(任一 → BLOCK 指路 tabsSlot):
59
+ # (a) DialogBody/SheetBody/SurfaceBody className 含 `!pt-0`(important 對抗 primitive 的 pt owner)
60
+ # (b) <TabsList 出現在含 DialogBody 的同段 new content 且無 tabsSlot 字樣
61
+ ROOT_SIG_A=$(printf '%s\n' "$CONTENT" | grep -nE '(DialogBody|SheetBody|SurfaceBody)[^>]*className=[^>]*!pt-0' | grep -v '@tabs-content-gap-ok:' || true)
62
+ ROOT_SIG_B=""
63
+ if printf '%s\n' "$CONTENT" | grep -q '<TabsList' && printf '%s\n' "$CONTENT" | grep -qE '<(DialogBody|SheetBody|SurfaceBody)\b' && ! printf '%s\n' "$CONTENT" | grep -q 'tabsSlot' && ! printf '%s\n' "$CONTENT" | grep -q '@tabs-content-gap-ok:'; then
64
+ ROOT_SIG_B=$(printf '%s\n' "$CONTENT" | grep -n '<TabsList' | head -3)
65
+ fi
66
+ if [ -n "$ROOT_SIG_A" ] || [ -n "$ROOT_SIG_B" ]; then
67
+ cat >&2 << 'EOF_C3'
68
+ 🚨 TABS-IN-BODY ROOT BLOCKER(P0,2026-07-08 WM 戰役 — 攔 root 非 symptom)
69
+
70
+ 偵測到「TabsList 手塞 chrome body / body 用 !pt-0 hack」簽名 —— 這是「沒用 header tabsSlot
71
+ canonical」的 root 錯誤(後果:header 與 TabsList 雙底線、tabs 底線被 body padding 內縮不滿寬、
72
+ spacing owner 鏈自組)。WM ProjectSettings/TypeSettings 錨例。
73
+
74
+ ── 正解 ──
75
+ <Tabs> wrap → <DialogHeader tabsSlot={<TabsList/>}> → <DialogBody><TabsContent className="mt-0">
76
+ 照 dialog.stories.tsx#WithTabsInHeader 逐字結構(header-canonical.spec.md Rule W2)。
77
+ Escape:`// @tabs-content-gap-ok: <rationale>`(例:tabs 本來就不屬 header 的內容分頁場景)
78
+ EOF_C3
79
+ exit 2
80
+ fi
81
+
82
+
55
83
  # ══ Check 2:overlay body 自身用固定 macro gap-N → 該用 layout-space token(2026-07-01 Sheet gap-4 錨例)══
56
84
  # Root(layoutSpace.spec.md 規則 2/3):浮層 body 直接堆疊內容的垂直 gap 屬 macro layout-space,該用
57
85
  # density-scaling token(並列 = loose / functional 交互 = tight),非固定 gap-N(lg 不縮放 → 跟 DS
@@ -157,6 +185,7 @@ while IFS= read -r ln; do
157
185
  UNJUSTIFIED="${UNJUSTIFIED}${ln}: $(echo "$cur" | sed 's/^[[:space:]]*//')\n"
158
186
  done <<< "$CANDIDATES"
159
187
 
188
+
160
189
  if [ -z "$UNJUSTIFIED" ]; then exit 0; fi
161
190
 
162
191
  cat >&2 << EOF
@@ -41,7 +41,7 @@ OUTPUT=$(node "$COMPILE_SCRIPT" "$COMP_NAME" --check 2>&1 || true)
41
41
  if echo "$OUTPUT" | grep -qE "spec/tsx canonical drift|spec-only|tsx-only"; then
42
42
  MSG="📐 Story canonical drift detected in ${COMP_NAME}:\n\n${OUTPUT}\n\nFix tsx componentMeta export 或 spec frontmatter 讓 keys 對齊。"
43
43
  ESCAPED=$(printf '%s' "$MSG" | jq -Rs .)
44
- printf '{"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":%s}}\n' "$ESCAPED"
44
+ printf '{"hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":%s}}\n' "$ESCAPED"
45
45
  fi
46
46
 
47
47
  # Skip graceful(migration 未做的元件)不報
@@ -35,10 +35,19 @@ VIOLATIONS=""
35
35
  # ── Check 1: shadcn compat alias 回流 ─────────────────────────────────────────
36
36
  # These are all shadcn safety-net aliases. Our code must use direct tokens instead.
37
37
  # bg-muted / bg-secondary / ring-ring are OUR tokens (kept), not listed here.
38
+ # SSOT-drive(#87 2026-07-11):deny-list SSOT = utility-registry.json;優先從 registry 組 pattern
39
+ # (未來新增 alias 只改 registry 自動傳播到本 write-time 主防線,消除「hardcoded 主 / registry 從」倒置)。
40
+ # registry 讀不到 → 保留 hardcoded fallback(11 條)避免 hook 啞掉。
41
+ _REG="${CLAUDE_PROJECT_DIR:-}/packages/design-system/src/tokens/utility-registry.json"
42
+ [ -f "$_REG" ] || _REG="$(dirname "${BASH_SOURCE[0]}")/../../packages/design-system/src/tokens/utility-registry.json"
38
43
  SHADCN_PATTERN='\b(bg-popover|text-popover-foreground|text-muted-foreground|bg-accent|text-accent-foreground|bg-destructive|bg-background|bg-card|text-card-foreground|border-input|text-primary-foreground)\b'
44
+ if [ -f "$_REG" ] && command -v jq >/dev/null 2>&1; then
45
+ _SHADCN_LIST=$(jq -r '.shadcn_alias.block.color_alias | join("|")' "$_REG" 2>/dev/null || true)
46
+ [ -n "$_SHADCN_LIST" ] && SHADCN_PATTERN="\\b(${_SHADCN_LIST})\\b"
47
+ fi
39
48
  SHADCN_HITS=$(grep -nE "$SHADCN_PATTERN" "$FILE_PATH" 2>/dev/null | head -5)
40
49
  if [ -n "$SHADCN_HITS" ]; then
41
- VIOLATIONS="${VIOLATIONS}\n⚠️ shadcn compat alias found (必須遷移為 direct token):\n${SHADCN_HITS}\n 映射: bg-popover→bg-surface-raised / text-popover-foreground→text-foreground / text-muted-foreground→text-fg-muted / bg-accent→bg-neutral-hover / text-accent-foreground→text-foreground / bg-destructive→bg-error / bg-background→bg-canvas / bg-card→bg-surface / border-input→border-border / text-primary-foreground→text-white"
50
+ VIOLATIONS="${VIOLATIONS}\n⚠️ shadcn compat alias found (必須遷移為 direct token):\n${SHADCN_HITS}\n 映射: bg-popover→bg-surface-raised / text-popover-foreground→text-foreground / text-muted-foreground→text-fg-muted / bg-accent→bg-neutral-hover / text-accent-foreground→text-foreground / bg-destructive→bg-error / bg-background→bg-canvas / bg-card→bg-surface / text-card-foreground→text-foreground / border-input→border-border / text-primary-foreground→text-white /(其餘 registry alias → 對應 semantic token,見 tokens/color/semantic.css)"
42
51
  fi
43
52
 
44
53
  # ── Check 2: Tailwind v4 [--foo] shorthand (silent fail) ─────────────────────
@@ -99,6 +99,20 @@ if [ "${LAST_USER_LINE:-0}" -gt 0 ] && [ -n "$LAST_ASSISTANT" ]; then
99
99
  fi
100
100
  fi
101
101
 
102
+ # ── Mechanism 7c: Deep-audit coverage gate(2026-07-12 user verbatim「不抽樣不偷懶…現在和未來可以確保嗎」)──
103
+ # Why: deep audit「完成」宣告前必證 91 dim × Claude+codex 雙軌全有證據。AI 自律不可靠(本 session 漏跑
104
+ # deterministic 24 + judgment 27 + hook 40 三層,只做 claim-vs-code + 反應式補,user 憤怒)。
105
+ # verify-deep-audit-coverage.mjs = 機械閘;宣告完成 + ledger 有缺口 → BLOCK。
106
+ if [ "${LAST_USER_LINE:-0}" -gt 0 ] && [ -n "$LAST_ASSISTANT" ] && [ -f scripts/verify-deep-audit-coverage.mjs ]; then
107
+ DEEPAUDIT_CLAIM_RE='(deep.?audit.{0,10}(完成|完整|done)|稽核.{0,8}(完整完美|全部完成|都.?跑完)|91.{0,6}dim.{0,8}(都|全).{0,4}(跑|過|完|有證據)|Phase A.{0,6}完成)'
108
+ DEEPAUDIT_NEG_RE='(未完成|還沒|尚未|缺口|gap|未跑|待跑|待驗|不算完成|覆蓋.{0,4}未|還有.{0,4}dim|待補)'
109
+ if echo "$LAST_ASSISTANT" | grep -qE "$DEEPAUDIT_CLAIM_RE" && ! echo "$LAST_ASSISTANT" | grep -qE "$DEEPAUDIT_NEG_RE"; then
110
+ if ! node scripts/verify-deep-audit-coverage.mjs >/dev/null 2>&1; then
111
+ CRITICAL_DEEPAUDIT_COVERAGE=1
112
+ fi
113
+ fi
114
+ fi
115
+
102
116
  # ── Mechanism 2: Auto-prune trigger ─────────────────────────────────────────
103
117
  if [ -f CLAUDE.md ]; then
104
118
  L=$(wc -l < CLAUDE.md | tr -d ' ')
@@ -513,4 +527,21 @@ if [ "${CRITICAL_COMPLETENESS:-0}" = "1" ] && [ -n "$LAST_ASSISTANT" ]; then
513
527
  fi
514
528
  fi
515
529
 
530
+ # ── BLOCKER for Mechanism 7c deep-audit coverage(2026-07-12 user-authorized)──
531
+ if [ "${CRITICAL_DEEPAUDIT_COVERAGE:-0}" = "1" ] && [ -n "$LAST_ASSISTANT" ]; then
532
+ DACOV_HASH=$(echo "$LAST_ASSISTANT" | tail -c 200 | shasum -a 256 | cut -c1-16)
533
+ LAST_BLOCKED_DACOV_FILE="$PROJECT_DIR/.claude/logs/.last-blocked-deepaudit-coverage.txt"
534
+ LAST_BLOCKED_DACOV=""
535
+ [ -f "$LAST_BLOCKED_DACOV_FILE" ] && LAST_BLOCKED_DACOV=$(cat "$LAST_BLOCKED_DACOV_FILE" 2>/dev/null || echo "")
536
+ if [ "$DACOV_HASH" != "$LAST_BLOCKED_DACOV" ]; then
537
+ echo "$DACOV_HASH" > "$LAST_BLOCKED_DACOV_FILE" 2>/dev/null || true
538
+ GAPLINE=$(node scripts/verify-deep-audit-coverage.mjs 2>/dev/null | grep -E '個 dim-證據缺口' | head -1)
539
+ REASON=$(printf '%s' \
540
+ "🚨 DEEP-AUDIT-COVERAGE BLOCKER(M7c,2026-07-12 user-authorized「不抽樣不偷懶…現在和未來可以確保嗎」):你宣告 deep audit 完成,但 verify-deep-audit-coverage.mjs exit 1 — ${GAPLINE:-91 dim × Claude+codex 雙軌未全有證據}。禁宣稱 done。跑 node scripts/verify-deep-audit-coverage.mjs 看缺哪些 dim,填完(judgment findings 檔 / deterministic log / hook residue verify / codex-dim-audit)才可宣稱;OR 明寫『核心做完,dim 覆蓋待補』。否則 turn 不結束。" \
541
+ "本機制起因:本 session AI 漏跑 91 dim 裡 deterministic 24 + judgment 27 + hook 40 三層,只做 claim-vs-code + 反應式補,user 憤怒。觸發器 = 宣告 deep audit 完成本身。")
542
+ printf '{"decision":"block","reason":%s}\n' "$(printf '%s' "$REASON" | jq -Rs .)"
543
+ exit 0
544
+ fi
545
+ fi
546
+
516
547
  exit 0
@@ -131,6 +131,30 @@ echo "Test 5: nonexistent path → pass (silently skip)"
131
131
  run_hook "src/does-not-exist-$$.tsx"
132
132
  expect_pass "Test 5 nonexistent path"
133
133
 
134
+ # ── Test 6: ABSOLUTE path with explorations import → block ───────────────────
135
+ # Real Edit/Write events carry absolute file_path(2026-07-10 wiring-hunt:hook
136
+ # 原本只比對相對路徑 prefix → 對真實 edits 形同虛設)。
137
+ echo ""
138
+ echo "Test 6: absolute path tsx imports from src/explorations/ → block"
139
+ F6="$SANDBOX/violation-abs.tsx"
140
+ cat >"$F6" <<'EOF'
141
+ import { ProtoX } from '@/explorations/foo/bar'
142
+ export const X = () => <ProtoX />
143
+ EOF
144
+ run_hook "$F6"
145
+ expect_block "Test 6 absolute path explorations import blocked" "Blocked"
146
+
147
+ # ── Test 7: ABSOLUTE path clean import → pass ────────────────────────────────
148
+ echo ""
149
+ echo "Test 7: absolute path tsx with clean import → pass"
150
+ F7="$SANDBOX/clean-abs.tsx"
151
+ cat >"$F7" <<'EOF'
152
+ import { Button } from '@/design-system/components/Button/button'
153
+ export const X = () => <Button>OK</Button>
154
+ EOF
155
+ run_hook "$F7"
156
+ expect_pass "Test 7 absolute path clean import"
157
+
134
158
  # ── Summary ──────────────────────────────────────────────────────────────────
135
159
  echo ""
136
160
  echo "════════════════════════════════════════"
@@ -118,6 +118,50 @@ EOF
118
118
  run_hook "$TMPDIR_TEST/.claude/memory/project_audit_progress.md" "Edit"
119
119
  expect_block_stderr "5. judgment dim 缺 prompt → Validator C exit-2 block" "VALIDATOR BLOCK"
120
120
 
121
+ # 6/7. Validator K 決策品質四要件(2026-07-14;SSOT = deep-audit SKILL C.1「🔒 決策品質四要件」)
122
+ # 拍板 section 內每個決策 block 必含 SSOT-check / 世界級 cite(URL)/ codex verdict / design-fit 四 marker。
123
+ # 先補 `## 99.` prompt 讓 test 5 留下的 Validator C 條件通過,隔離 K 的判定。
124
+ cat > "$TMPDIR_TEST/.claude/skills/design-system-audit/references/audit-prompts.md" <<'EOF'
125
+ ## 1. foo
126
+ prompt
127
+ ## 99. test judgment dim
128
+ prompt
129
+ EOF
130
+ mkdir -p "$TMPDIR_TEST/.claude/logs/deep-audit-test"
131
+ cat > "$TMPDIR_TEST/.claude/logs/deep-audit-test/C1-final-report.md" <<'EOF'
132
+ # Deep Audit 報告
133
+ Dim 1: pass
134
+
135
+ ### 待你拍板
136
+ 1. 決策一:Popover 內距是否改 12px
137
+ - SSOT 理由:改跨元件 canonical 視覺結構
138
+ - SSOT-check:grep spec + memory,無既有拍板
139
+ - codex verdict:agree(辯論共識)
140
+ - 設計語言 fit:符合 density canonical
141
+ EOF
142
+ run_hook "$TMPDIR_TEST/.claude/logs/deep-audit-test/C1-final-report.md" "Write"
143
+ expect_block_stderr "6. 決策缺世界級 cite → Validator K exit-2 block" "決策四要件不全"
144
+
145
+ cat > "$TMPDIR_TEST/.claude/logs/deep-audit-test/C1-final-report.md" <<'EOF'
146
+ # Deep Audit 報告
147
+ Dim 1: pass
148
+
149
+ ### 待你拍板
150
+ 1. 決策一:Popover 內距是否改 12px
151
+ - SSOT 理由:改跨元件 canonical 視覺結構
152
+ - SSOT-check:grep spec + memory,無既有拍板
153
+ - 世界級:Polaris https://polaris.shopify.com/tokens/space / Material / Ant(3 家)
154
+ - codex verdict:agree(辯論共識)
155
+ - 設計語言 fit:符合 density canonical
156
+ EOF
157
+ run_hook "$TMPDIR_TEST/.claude/logs/deep-audit-test/C1-final-report.md" "Write"
158
+ if [ "$EXIT" = "0" ]; then
159
+ echo " PASS 7. 四要件齊 → Validator K pass(exit 0)"; PASS=$((PASS+1))
160
+ else
161
+ echo " FAIL 7. 四要件齊 → Validator K pass (expected exit 0, got $EXIT, stderr=[$STDERR_TEXT])"
162
+ FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - 7. 四要件齊 pass"
163
+ fi
164
+
121
165
  echo ""
122
166
  echo "=== Summary ==="
123
167
  echo "Passed: $PASS / $((PASS + FAIL))"
@@ -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"