@qijenchen/design-system 0.1.0-beta.83 → 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 (604) 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 +31 -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 +2 -1
  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 +28 -0
  255. package/ds-canonical/fork/hooks/check_story_determinism.sh +2 -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 +15 -0
  259. package/ds-canonical/fork/preamble.md +20 -18
  260. package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +3 -3
  261. package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
  262. package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +1 -1
  263. package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
  264. package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
  265. package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
  266. package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
  267. package/ds-canonical/fork/skills/visual-audit/SKILL.md +2 -2
  268. package/ds-canonical/hooks/README.md +1 -1
  269. package/ds-canonical/hooks/block_prototype_imports.py +15 -4
  270. package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
  271. package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
  272. package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
  273. package/ds-canonical/hooks/check_ds_anchor_preflight.sh +2 -1
  274. package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
  275. package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
  276. package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
  277. package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
  278. package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
  279. package/ds-canonical/hooks/check_opacity_token_usage.sh +28 -0
  280. package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
  281. package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
  282. package/ds-canonical/hooks/check_ssot_header_declaration.sh +3 -1
  283. package/ds-canonical/hooks/check_story_determinism.sh +2 -0
  284. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
  285. package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
  286. package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
  287. package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
  288. package/ds-canonical/hooks/stop_self_audit.sh +31 -0
  289. package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
  290. package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
  291. package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
  292. package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
  293. package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
  294. package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
  295. package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
  296. package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
  297. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +39 -0
  298. package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
  299. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
  300. package/ds-canonical/references/build-ui-canonicals.md +2 -1
  301. package/ds-canonical/references/failure-class-registry.json +145 -0
  302. package/ds-canonical/references/governance-audit-coverage.md +33 -0
  303. package/ds-canonical/references/item-anatomy-recipe.md +2 -2
  304. package/ds-canonical/references/scenario-definition.md +6 -9
  305. package/ds-canonical/references/ssot-consultation.md +2 -2
  306. package/ds-canonical/references/ssot-index.md +5 -4
  307. package/ds-canonical/references/story-baseline-registry.json +8 -2
  308. package/ds-canonical/references/structural-token-retention.md +6 -9
  309. package/ds-canonical/rules/meta-patterns.md +8 -8
  310. package/ds-canonical/rules/self-verify.md +4 -3
  311. package/ds-canonical/rules/story-rules.md +2 -2
  312. package/ds-canonical/rules/ui-development.md +2 -2
  313. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +3 -3
  314. package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
  315. package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
  316. package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
  317. package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
  318. package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
  319. package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
  320. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +51 -58
  321. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
  322. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
  323. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
  324. package/ds-canonical/skills/delivery-handoff/SKILL.md +1 -1
  325. package/ds-canonical/skills/design-system-audit/SKILL.md +26 -25
  326. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
  327. package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
  328. package/ds-canonical/skills/governance-health/SKILL.md +1 -1
  329. package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
  330. package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
  331. package/ds-canonical/skills/new-component/SKILL.md +5 -5
  332. package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
  333. package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
  334. package/ds-canonical/skills/propose-options/SKILL.md +3 -3
  335. package/ds-canonical/skills/prototype/SKILL.md +1 -1
  336. package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
  337. package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
  338. package/ds-canonical/skills/story-writing/SKILL.md +3 -3
  339. package/ds-canonical/skills/visual-audit/SKILL.md +2 -2
  340. package/ds-story-manifest.json +29 -20
  341. package/llms-full.txt +22 -1
  342. package/llms.txt +5 -4
  343. package/package.json +7 -3
  344. package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
  345. package/src/components/Accordion/accordion.stories.tsx +16 -1
  346. package/src/components/Alert/alert.principles.stories.tsx +1 -1
  347. package/src/components/Alert/alert.spec.md +8 -10
  348. package/src/components/Alert/alert.stories.tsx +28 -28
  349. package/src/components/Alert/alert.tsx +1 -1
  350. package/src/components/AppShell/_demo-helpers.tsx +6 -3
  351. package/src/components/AppShell/app-shell.spec.md +4 -4
  352. package/src/components/AppShell/app-shell.tsx +28 -2
  353. package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
  354. package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
  355. package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
  356. package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
  357. package/src/components/Avatar/avatar.spec.md +2 -2
  358. package/src/components/Avatar/avatar.stories.tsx +8 -6
  359. package/src/components/Avatar/avatar.tsx +13 -5
  360. package/src/components/Badge/badge.principles.stories.tsx +1 -1
  361. package/src/components/Badge/badge.spec.md +2 -0
  362. package/src/components/Badge/badge.stories.tsx +4 -2
  363. package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
  364. package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
  365. package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
  366. package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
  367. package/src/components/Button/button.principles.stories.tsx +1 -1
  368. package/src/components/Button/button.spec.md +2 -2
  369. package/src/components/Button/button.tsx +18 -3
  370. package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
  371. package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
  372. package/src/components/Calendar/calendar.spec.md +5 -4
  373. package/src/components/Calendar/calendar.stories.tsx +7 -4
  374. package/src/components/Calendar/calendar.tsx +26 -7
  375. package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
  376. package/src/components/Carousel/carousel.spec.md +2 -2
  377. package/src/components/Carousel/carousel.tsx +11 -3
  378. package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
  379. package/src/components/Chart/chart.principles.stories.tsx +1 -1
  380. package/src/components/Chart/chart.stories.tsx +2 -8
  381. package/src/components/Chart/chart.tsx +3 -0
  382. package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
  383. package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
  384. package/src/components/Checkbox/checkbox.spec.md +11 -26
  385. package/src/components/Checkbox/checkbox.stories.tsx +11 -8
  386. package/src/components/Checkbox/checkbox.tsx +18 -13
  387. package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
  388. package/src/components/Chip/chip.principles.stories.tsx +1 -1
  389. package/src/components/Chip/chip.spec.md +5 -4
  390. package/src/components/Chip/chip.tsx +5 -1
  391. package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
  392. package/src/components/CircularProgress/circular-progress.spec.md +3 -3
  393. package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
  394. package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
  395. package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
  396. package/src/components/Coachmark/coachmark.spec.md +5 -5
  397. package/src/components/Coachmark/coachmark.stories.tsx +3 -1
  398. package/src/components/Coachmark/coachmark.tsx +10 -3
  399. package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
  400. package/src/components/Combobox/combobox.tsx +53 -19
  401. package/src/components/Command/command.anatomy.stories.tsx +2 -2
  402. package/src/components/Command/command.principles.stories.tsx +1 -1
  403. package/src/components/Command/command.stories.tsx +42 -10
  404. package/src/components/DataTable/cell-registry.tsx +86 -63
  405. package/src/components/DataTable/column-types.ts +10 -1
  406. package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
  407. package/src/components/DataTable/data-table-filter-panel.tsx +4 -1
  408. package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
  409. package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
  410. package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
  411. package/src/components/DataTable/data-table.spec.md +32 -12
  412. package/src/components/DataTable/data-table.stories.tsx +16 -17
  413. package/src/components/DataTable/data-table.tsx +103 -60
  414. package/src/components/DataTable/index.ts +3 -0
  415. package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
  416. package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
  417. package/src/components/DateGrid/date-grid.spec.md +1 -1
  418. package/src/components/DateGrid/date-grid.tsx +3 -1
  419. package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
  420. package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
  421. package/src/components/DatePicker/date-picker.spec.md +3 -3
  422. package/src/components/DatePicker/date-picker.stories.tsx +4 -5
  423. package/src/components/DatePicker/date-picker.tsx +99 -45
  424. package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
  425. package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
  426. package/src/components/DescriptionList/description-list.spec.md +3 -3
  427. package/src/components/DescriptionList/description-list.stories.tsx +7 -6
  428. package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
  429. package/src/components/Dialog/dialog.spec.md +9 -0
  430. package/src/components/Dialog/dialog.stories.tsx +66 -5
  431. package/src/components/Dialog/dialog.tsx +60 -25
  432. package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
  433. package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
  434. package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
  435. package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
  436. package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
  437. package/src/components/Empty/empty.spec.md +2 -2
  438. package/src/components/Field/field-context.ts +69 -5
  439. package/src/components/Field/field-controls.spec.md +62 -8
  440. package/src/components/Field/field-edit-keys.ts +66 -0
  441. package/src/components/Field/field-types.ts +58 -9
  442. package/src/components/Field/field-wrapper.tsx +50 -42
  443. package/src/components/Field/field.anatomy.stories.tsx +9 -6
  444. package/src/components/Field/field.spec.md +1 -1
  445. package/src/components/Field/field.stories.tsx +1 -1
  446. package/src/components/Field/field.tsx +2 -1
  447. package/src/components/Field/form-validation.spec.md +3 -3
  448. package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
  449. package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
  450. package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
  451. package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
  452. package/src/components/FileItem/file-item.spec.md +5 -8
  453. package/src/components/FileItem/file-item.stories.tsx +36 -25
  454. package/src/components/FileItem/file-item.tsx +8 -6
  455. package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
  456. package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
  457. package/src/components/FileUpload/file-upload.spec.md +1 -1
  458. package/src/components/FileUpload/file-upload.tsx +1 -1
  459. package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
  460. package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
  461. package/src/components/FileViewer/file-viewer.spec.md +30 -12
  462. package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
  463. package/src/components/FileViewer/file-viewer.tsx +12 -4
  464. package/src/components/FileViewer/image-renderer.tsx +35 -7
  465. package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
  466. package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
  467. package/src/components/HoverCard/hover-card.spec.md +5 -5
  468. package/src/components/HoverCard/hover-card.stories.tsx +16 -16
  469. package/src/components/HoverCard/hover-card.tsx +5 -3
  470. package/src/components/InlineEdit/index.ts +5 -0
  471. package/src/components/InlineEdit/inline-edit.spec.md +149 -0
  472. package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
  473. package/src/components/InlineEdit/inline-edit.tsx +287 -0
  474. package/src/components/Input/input.anatomy.stories.tsx +8 -7
  475. package/src/components/Input/input.principles.stories.tsx +2 -12
  476. package/src/components/Input/input.spec.md +13 -18
  477. package/src/components/Input/input.tsx +69 -22
  478. package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
  479. package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
  480. package/src/components/LinkInput/link-input.tsx +11 -10
  481. package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
  482. package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
  483. package/src/components/Menu/menu-item.spec.md +22 -15
  484. package/src/components/Menu/menu-item.stories.tsx +39 -11
  485. package/src/components/Menu/menu-item.tsx +38 -4
  486. package/src/components/Notice/notice.principles.stories.tsx +1 -1
  487. package/src/components/Notice/notice.spec.md +16 -3
  488. package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
  489. package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
  490. package/src/components/NumberInput/number-input.spec.md +4 -4
  491. package/src/components/NumberInput/number-input.tsx +19 -12
  492. package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
  493. package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
  494. package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
  495. package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
  496. package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
  497. package/src/components/Pagination/pagination.spec.md +1 -1
  498. package/src/components/Pagination/pagination.stories.tsx +2 -6
  499. package/src/components/Pagination/pagination.tsx +1 -1
  500. package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
  501. package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
  502. package/src/components/PeoplePicker/people-picker.spec.md +6 -6
  503. package/src/components/PeoplePicker/people-picker.tsx +56 -16
  504. package/src/components/PeoplePicker/person-display.tsx +32 -16
  505. package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
  506. package/src/components/Popover/popover.tsx +3 -1
  507. package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
  508. package/src/components/ProfileCard/profile-card.spec.md +3 -3
  509. package/src/components/ProfileCard/profile-card.tsx +6 -6
  510. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
  511. package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
  512. package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
  513. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
  514. package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
  515. package/src/components/RadioGroup/radio-group.tsx +41 -15
  516. package/src/components/Rating/rating.spec.md +11 -3
  517. package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
  518. package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
  519. package/src/components/ScrollArea/scroll-area.spec.md +7 -3
  520. package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
  521. package/src/components/ScrollArea/scroll-area.tsx +17 -4
  522. package/src/components/Select/select.anatomy.stories.tsx +3 -3
  523. package/src/components/Select/select.spec.md +27 -17
  524. package/src/components/Select/select.stories.tsx +33 -0
  525. package/src/components/Select/select.tsx +190 -36
  526. package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
  527. package/src/components/SelectMenu/select-menu.spec.md +15 -7
  528. package/src/components/SelectMenu/select-menu.tsx +16 -3
  529. package/src/components/SelectionControl/boolean-value.tsx +39 -0
  530. package/src/components/SelectionControl/index.ts +1 -0
  531. package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
  532. package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
  533. package/src/components/SelectionControl/selection-item.spec.md +3 -3
  534. package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
  535. package/src/components/Separator/separator.spec.md +2 -2
  536. package/src/components/Separator/separator.stories.tsx +6 -27
  537. package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
  538. package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
  539. package/src/components/Sheet/sheet.spec.md +2 -2
  540. package/src/components/Sheet/sheet.tsx +9 -5
  541. package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
  542. package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
  543. package/src/components/Sidebar/sidebar.spec.md +13 -15
  544. package/src/components/Sidebar/sidebar.stories.tsx +8 -7
  545. package/src/components/Sidebar/sidebar.tsx +37 -25
  546. package/src/components/Skeleton/skeleton.stories.tsx +4 -11
  547. package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
  548. package/src/components/Slider/slider.principles.stories.tsx +2 -2
  549. package/src/components/Slider/slider.spec.md +5 -5
  550. package/src/components/Slider/slider.tsx +3 -1
  551. package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
  552. package/src/components/Steps/steps.principles.stories.tsx +1 -1
  553. package/src/components/Steps/steps.spec.md +1 -1
  554. package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
  555. package/src/components/Switch/switch.principles.stories.tsx +4 -4
  556. package/src/components/Switch/switch.spec.md +8 -8
  557. package/src/components/Switch/switch.stories.tsx +9 -24
  558. package/src/components/Switch/switch.tsx +17 -13
  559. package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
  560. package/src/components/Tabs/tabs.spec.md +1 -1
  561. package/src/components/Tabs/tabs.tsx +21 -1
  562. package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
  563. package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
  564. package/src/components/Textarea/textarea.spec.md +4 -4
  565. package/src/components/Textarea/textarea.tsx +72 -46
  566. package/src/components/TimePicker/time-columns.tsx +6 -2
  567. package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
  568. package/src/components/TimePicker/time-picker.spec.md +3 -3
  569. package/src/components/TimePicker/time-picker.tsx +16 -10
  570. package/src/components/Toast/toast.stories.tsx +7 -4
  571. package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
  572. package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
  573. package/src/components/Tooltip/tooltip.spec.md +1 -1
  574. package/src/components/Tooltip/tooltip.stories.tsx +4 -39
  575. package/src/components/Tooltip/tooltip.tsx +8 -6
  576. package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
  577. package/src/components/TreeView/tree-view.spec.md +42 -11
  578. package/src/components/TreeView/tree-view.stories.tsx +1 -0
  579. package/src/components/TreeView/tree-view.tsx +322 -17
  580. package/src/index.ts +584 -60
  581. package/src/patterns/action-bar/action-bar.spec.md +9 -0
  582. package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
  583. package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
  584. package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
  585. package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
  586. package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
  587. package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
  588. package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
  589. package/src/styles/tokens.css +3 -0
  590. package/src/tokens/README.md +1 -1
  591. package/src/tokens/color/color.spec.md +3 -3
  592. package/src/tokens/color/color.stories.tsx +3 -3
  593. package/src/tokens/density/density.stories.tsx +16 -3
  594. package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
  595. package/src/tokens/motion/motion.css +33 -21
  596. package/src/tokens/motion/motion.spec.md +32 -15
  597. package/src/tokens/motion/motion.stories.tsx +58 -5
  598. package/src/tokens/motion/motion.ts +7 -6
  599. package/src/tokens/motion/overlay-motion.ts +26 -0
  600. package/src/tokens/orphan-tokens.spec.md +4 -4
  601. package/src/tokens/token-system.spec.md +1 -0
  602. package/src/tokens/uiSize/uiSize.spec.md +1 -1
  603. package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
  604. package/src/tokens/utility-registry.json +160 -23
@@ -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
 
@@ -56,6 +56,18 @@ expect_warn() {
56
56
  fi
57
57
  }
58
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)"
66
+ echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
67
+ FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
68
+ fi
69
+ }
70
+
59
71
  echo "=== check_opacity_token_usage tests ==="
60
72
 
61
73
  # 1. raw opacity-30 → warn
@@ -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,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
 
@@ -18,6 +18,7 @@
18
18
  | 資料表格(含 header / sorting / sticky) | `<table><thead>...</thead><tbody>...</tbody></table>` | `<DataTable columns={...} data={...} />` |
19
19
  | 檔案上傳列表 | `<div>filename</div><ProgressBar /><Paperclip />` | `<FileItem mode="compact" />` or `<FileUpload>` |
20
20
  | 表單欄位(label + control + error) | `<label>...</label><input/><span className="text-error">...</span>` | `<Field><FieldLabel>...<Input />...<FieldError/>` |
21
+ | 表單提交驗證(何時顯錯 / 提交可點性) | 手刻 `useState(showErrors)` + `submitAttempt` 旗標自組顯錯時機 | `useFormValidation`(Field 家族 hook,`intent:'create'` = 提交恆可點、點擊時 validate 顯錯;搭 `<FieldError>`)|
21
22
  | 全頁 / 區域 loading | `<div className="absolute inset-0 flex center"><Spinner /></div>` | `<Empty icon={<CircularProgress />} description="..." />` |
22
23
  | 確認對話框 | raw `<div className="fixed inset-0 bg-black/50">...<button>OK</button>` | `<Dialog>` + `<DialogHeader>` etc |
23
24
  | 分隔線 | `<hr className="..." />` or `<div className="h-px bg-..."/>` | `<Separator />`(必要時)or CSS border(見 separator.spec) |
@@ -60,7 +61,7 @@
60
61
  - 以上都沒命中 → 才可自建,但 **建完要立刻回來加行**(防下一個人又重造輪子)
61
62
  - **本規則同樣適用 story / consumer / exploration code**:不 hand-craft 已有 prop 能做的事(如 Input loading 走 `loading` prop 不自刻 `<div className="relative"><input/><div className="absolute">` / 全頁 loading 走 `<Empty icon={<CircularProgress/>}/>` 不自刻 `absolute inset-0`)。遇缺口**回元件 spec 擴 API**,不自刻繞過 — hand-craft 視覺對齊 bug 上游
62
63
 
63
- 具體 anti-pattern signals → `/design-system-audit` Dim 21;pixel-level 視覺 regression(API 用對但視覺仍跑掉)→ `/visual-audit`(D5)抓(原 memory `project_pending_tasks` 已 retire)。
64
+ 具體 anti-pattern signals → `design-system-audit/references/audit-prompts.md`「L1. 手刻繞 DS canonical」+ Dim 71 consumer 手刻(Pattern 10;現行 Dim 21 已是「連續 item list wrapper gap」,勿誤指);pixel-level 視覺 regression(API 用對但視覺仍跑掉)→ `/visual-audit`(D5)抓(原 memory `project_pending_tasks` 已 retire)。
64
65
 
65
66
  ---
66
67
 
@@ -0,0 +1,145 @@
1
+ {
2
+ "_meta": {
3
+ "invariant": "每類被抓過的 failure class 必須終有 ship 到 consumer 的機械防線(user 2026-07-10 verbatim「建立治理的基本原則」)。status 三態:protected(已有 MECHANICAL_CONSUMER / DS_API_FIXED 防線)/ remediating(必帶 plan 指標)/ judgment(regex 不可判,必帶 auditDim 兜底)。gate = scripts/audit-failure-class-coverage.mjs --check(deep-audit dim 91 chain)。",
4
+ "source": ".claude/logs/failure-class-coverage-matrix.json(2026-07-10 41-agent 對抗 workflow,每 verdict cite 驗證)",
5
+ "addRule": "新 failure class(deep-audit / user 抓 / codex 抓)→ 本 registry 加 row;沒 row 或 status 缺 = gate 紅燈。remediation 落地後把 status 升 protected 並記 landedAt。"
6
+ },
7
+ "classes": [
8
+ {
9
+ "id": "phantom-layout-token",
10
+ "name": "幻覺 layout token / utility",
11
+ "status": "protected",
12
+ "note": "check_layout_space_magic_numbers PHANTOM 白名單(SHIP_AS_IS)+ opacity hook 第 10 類幻覺 state 尾綴(2026-07-10)"
13
+ },
14
+ {
15
+ "id": "handcraft-mini-table",
16
+ "name": "手刻 mini-table(grid-cols 黏死欄寬)",
17
+ "status": "protected",
18
+ "note": "r3 偽表格簽名 + magic-hook grid-cols px(皆 SHIP_AS_IS)"
19
+ },
20
+ {
21
+ "id": "handcraft-menu-item-row",
22
+ "name": "手刻 menu-item 可點列",
23
+ "status": "protected",
24
+ "landedAt": "2026-07-10",
25
+ "note": "根因 MenuItem startContent(beta.84)+ r3 nav-row 簽名(hover+selected 成對)"
26
+ },
27
+ {
28
+ "id": "export-chain-break",
29
+ "name": "export 斷鏈逼手刻(R2)",
30
+ "status": "protected",
31
+ "note": "DS_API_FIXED — barrel generator + preflight --check drift gate;beta.84 發版後 consumer 正式接上"
32
+ },
33
+ {
34
+ "id": "contrast-pair-violation",
35
+ "name": "對比配對違規(亮色底 × text-white)",
36
+ "status": "protected",
37
+ "landedAt": "2026-07-10",
38
+ "note": "r3 C5 簽名 → CAT_SOLID pair"
39
+ },
40
+ {
41
+ "id": "handcraft-form-validation",
42
+ "name": "手刻表單驗證 state",
43
+ "status": "protected",
44
+ "note": "r3 useFormValidation 零消費簽名(SHIP_AS_IS)"
45
+ },
46
+ {
47
+ "id": "selectmenu-direct-use",
48
+ "name": "SelectMenu internal 直用",
49
+ "status": "protected",
50
+ "note": "r3 C7 簽名(<SelectMenu 直用 → BLOCK,escape @selectmenu-direct-ok:;select-menu.spec.md:53 明文禁直用特例)",
51
+ "landedAt": "2026-07-10"
52
+ },
53
+ {
54
+ "id": "handcraft-header-tabs",
55
+ "name": "頁內手刻 header+TabsList(未走 tabsSlot)",
56
+ "status": "judgment",
57
+ "note": "dialog/surface 半邊已有 check_tabs_content_chrome_body_double_gap P0(SHIP_AS_IS);頁內 h2+TabsList 存在合法場景(TypeSettings 內容層分頁 @tabs-content-gap-ok 錨例)= context 判斷,倉促 regex = 誤殺",
58
+ "auditDim": "product-ui-audit + header-canonical.spec.md Rule W4"
59
+ },
60
+ {
61
+ "id": "spacing-tier-semantic",
62
+ "name": "spacing 親疏語義誤用(tier 選錯)",
63
+ "status": "judgment",
64
+ "auditDim": "90(layout-space macro judgment sweep)+ product-ui-audit",
65
+ "note": "合法 token 用錯 tier = context 判斷,regex 不可判;magic/phantom 機械半邊已 protected"
66
+ },
67
+ {
68
+ "id": "search-action-position",
69
+ "name": "業務 search 被推工具層位置",
70
+ "status": "protected",
71
+ "landedAt": "2026-07-10",
72
+ "note": "r3 C10 簽名(spacer+Search Input);業務 vs 工具判定本身 judgment → escape @search-right-ok"
73
+ },
74
+ {
75
+ "id": "dialog-chrome-double-x",
76
+ "name": "dialog chrome 雙 X / header 操作不走 actions",
77
+ "status": "protected",
78
+ "landedAt": "2026-07-10",
79
+ "note": "r3 C11 簽名(DialogHeader 250 字窗)"
80
+ },
81
+ {
82
+ "id": "field-width-misuse",
83
+ "name": "Field 家族硬寬 / hug-fill 語義",
84
+ "status": "protected",
85
+ "landedAt": "2026-07-10",
86
+ "note": "硬寬 w-N 機械(r3 C12);hug vs fill 語義選擇 = judgment 半邊歸 product-ui-audit"
87
+ },
88
+ {
89
+ "id": "handcraft-section-header",
90
+ "name": "手刻可收合 section header",
91
+ "status": "protected",
92
+ "note": "R3-7 拍板 codify 進 item-anatomy.spec.md「可收合 section header 組合 canonical」(組合非元件,隨 npm ship)+ r3 C13 簽名(Chevron+justify-between+可點且無共用元件 → BLOCK)",
93
+ "landedAt": "2026-07-10"
94
+ },
95
+ {
96
+ "id": "avatar-anatomy-misuse",
97
+ "name": "avatar row-context 直用(未走 ItemAvatar/PersonValue 鏈)",
98
+ "status": "judgment",
99
+ "note": "前置已清:PersonValue/PersonDisplay/PersonAvatarTag 2026-07-10 補進 export 面(probe 驗 root barrel 解析)= 正道可 import;「row context 內 raw Avatar」判定 = context 判斷,regex 不可判(Avatar 合法 standalone 場景遍地)",
100
+ "auditDim": "product-ui-audit + item-anatomy.spec.md:178(Prefix 垂直對齊)"
101
+ },
102
+ {
103
+ "id": "datatable-density-structure",
104
+ "name": "DataTable 密度/tree 佔位/inline-create idle 未消費",
105
+ "status": "judgment",
106
+ "note": "tree 佔位半邊 DS_API_FIXED(data-table.tsx sibling-aware,beta.84 生效);size 密度選擇與 idle 列樣式 = context 判斷(嵌入式 vs 主表格),spec 隨 npm ship 供讀",
107
+ "auditDim": "product-ui-audit + data-table.spec.md:71/80(size 密度)+ :360(inline-create idle)"
108
+ },
109
+ {
110
+ "id": "always-edit-cell",
111
+ "name": "恆-edit cell(display 態渲染 edit 控件)",
112
+ "status": "judgment",
113
+ "note": "機械半邊已上:story-baseline-registry antiPattern datatable-always-edit-cell(cell: 直渲 edit 控件 → R8 BLOCK,unless onCellCommit/editable/display);custom cell 元件包裹子集 regex 看不進去 + RoleCell 拍板反例證實 context 判斷 → judgment 兜底",
114
+ "auditDim": "product-ui-audit + data-table.spec.md:373(indicator A 案)"
115
+ },
116
+ {
117
+ "id": "separator-geometry",
118
+ "name": "分隔線幾何(黏按鈕無 mx)",
119
+ "status": "protected",
120
+ "landedAt": "2026-07-10",
121
+ "note": "r3 C17 簽名 + magic-hook divider 行豁免(治理自我打架修正)"
122
+ },
123
+ {
124
+ "id": "count-label-concat",
125
+ "name": "計數括號串接(children 層)",
126
+ "status": "protected",
127
+ "landedAt": "2026-07-10",
128
+ "note": "r3 C18 簽名(children 錨定,aria attr 合法)"
129
+ },
130
+ {
131
+ "id": "two-pane-dialog",
132
+ "name": "兩欄 dialog 版型 canonical 缺席",
133
+ "status": "protected",
134
+ "landedAt": "2026-07-10",
135
+ "note": "user 拍板:組合非元件(對齊 Atlassian/MUI composition verdict)→ overlay-surface.spec.md「兩欄 dialog 組合 canonical」(隨 npm ship)+ r3 C19 簽名(共用捲軸機械攔)"
136
+ },
137
+ {
138
+ "id": "handcraft-link-underline",
139
+ "name": "連結字手刻 underline",
140
+ "status": "protected",
141
+ "landedAt": "2026-07-10",
142
+ "note": "r3 C20 簽名(no-underline / hover:underline 形不誤殺)"
143
+ }
144
+ ]
145
+ }
@@ -0,0 +1,33 @@
1
+ # 治理 home × 稽核者 覆蓋表(2026-07-10)
2
+
3
+ **觸發**:user verbatim「綜觀來看,deep audit 到底會不會稽核**所有** DS 的治理?」— 不是單軸,是全部。本表 = 逐 home 盤點「誰稽核它、怎麼稽核、多常跑」,誠實標出弱軸。**機械消費點:deep-audit SKILL C.0b(2026-07-10 接線)— 每輪收尾必逐 row 對照本表,新治理物無 row = C 階段不完整**;另 knowledge-prune 季度掃時參照。
4
+
5
+ ## 覆蓋表(逐 home,cite 查證過)
6
+
7
+ | 治理 home | 稽核者(機械) | 跑的時機 | 覆蓋度 |
8
+ |---|---|---|---|
9
+ | `CLAUDE.md` ×2 + 計數 snapshot | `sync-governance-counters --check`(數字 drift,fail-closed)+ session-start Check 7 + `_governance_coverage_check` PostToolUse(原則→dim 對映)+ knowledge-prune D1/D4(重複/矛盾) | 每 session + 每發版 + 季度 | ✅ 強 |
10
+ | `.claude/rules/*.md`(M-rules 等) | counters(M-rule 數)+ `extract-canonical-rules --check` + canonical-reviewer agent(edit 時)+ knowledge-prune D1/D3/D4 | 每 edit + 每發版 + 季度 | ✅ 強 |
11
+ | `*.spec.md`(83+) | deep-audit dims 6/7/8(NO-SAMPLE judgment)+ A.1b claim-vs-code 逐句 + `audit-spec-deadlinks --check` + `add-reciprocal-pointers --check` + `check_spec_class_drift` hook + `audit-content-quality --check`(**scope 註:此 script 只掃 components/ 的 spec/story,非治理 md**) | 每 deep-audit + 每發版 | ✅ 強 |
12
+ | hooks(56) | `audit:hook-quality`(fire 活性/假死)+ `audit-hook-test-coverage --check`(BLOCKER hook 必有 test;**2026-07-10 進 preflight fail-closed**)+ `tests/run-all` + fork classification gate(`build-fork-governance --check`,新 hook 未分類 = 擋發版)+ counters(數量 cap) | 每發版 + 季度 | ✅ 強 |
13
+ | skills(SKILL.md ×22) | knowledge-prune D7(invoke 活性)+ file-size hook + deep-audit A.0 第 7 項全讀(2026-07-10 補真 — 原宣稱超前)+ governance-health 月度 | 每 deep-audit + 季度 + 月度 | ⚠️ 中(read 層有了;逐句 claim-vs-behavior 仍無機械閘 = 弱軸 2) |
14
+ | memory(SSOT + mirror) | session-start cap 檢查(≤20)+ `sync-memory` drift + knowledge-prune D8(recency/orphan) | 每 session + 季度 | ✅ 強 |
15
+ | `references/`(registry / 對照表) | dim 91 registry gate(failure-class)+ `check_story_invariants` R8(story-baseline-registry 消費)+ prune D1/D4 + **D2 references-orphan 掃(2026-07-10 加)** | 每發版 + 季度 | ⚠️ 中(2026-07-10 修:原誤引 canonical_propagation/counters — 兩者實際不掃本目錄;純文字 reference 靠季度) |
16
+ | `planning/`(Level 9 plan doc) | 設計上 = 歷史 SSOT 存檔;**D8 planning-orphan 掃(2026-07-10 補 — 原 D8 只掃 memory 方向相反)** | 季度 | ⚠️ 低-by-design(存檔性質;活的必有 memory pointer,無引用 → D8 列 orphan 候選) |
17
+ | scripts/ gates(76 .mjs) | `audit-coverage-matrix --check`(每 dim 的 mechanism script 必存在於 disk)+「DETERMINISTIC dim 必驗 mode 真跑」鐵律(2026-06-11)+ 引入時 breadth-test 鐵律(注入違規→抓到→revert) | 每 deep-audit + 每發版 | ⚠️ 中(**gate script 自身正確性**只有 3 支有專屬 meta-test〔fork harness / DataTable invariants / story-manifest〕;其餘靠引入時 breadth-test + dim 真跑證據。系統性 meta-test = roadmap 候選,見下) |
18
+ | plugin / marketplace / fork corpus | `plugin-structure-validate` + `build-fork-governance --check` + `test-fork-governance` 假 fork harness(防 false-green/brick)+ counters | 每發版 | ✅ 強 |
19
+ | eslint-plugin | 自帶 node --test(50 case)| 手跑/CI 無(**未發佈 = 對 consumer 零效**,plan doc 批次 B) | ⚠️ 已知缺口(tracked) |
20
+ | commands / agents(稀住戶) | knowledge-prune D2(2026-07-10 補 bullet:commands 對照 skill-invokes log / agents 用 git recency + transcript grep — 原 D2 零掃描此二 home) | 季度 | ⚠️ 低(住戶少、變動少) |
21
+ | failure-class(病根→防線) | **dim 91 `audit-failure-class-coverage --check`(2026-07-10 新)** | 每 deep-audit + 每發版 | ✅ 強 |
22
+ | codex 鏈(CLI/model 新鮮度) | **`check-codex-freshness.mjs`(2026-07-10;deep-audit B.0 前置 + codex-collab Step 0.4 同日補接 = 兩條 codex 路徑皆 gate;CLI 落後自動升 + 禁 model pin + effort probe top)** | 每次 codex 使用(兩路徑)| ✅ 強 |
23
+
24
+ ## 誠實結論(回答「所有?」)
25
+
26
+ **主幹 9 軸已全機械化 + fail-closed**(內容/計數/機械化程度/hook 活性+測試/膨脹矛盾/fork 出貨/病根覆蓋/codex 新鮮度/dim 自身反抽樣)。**「所有」還不成立的 4 個弱軸**(全部 tracked,非隱藏):
27
+
28
+ 1. **gate script 自身正確性**:多數 .mjs gate 無 meta-test(靠引入時 breadth-test + deep-audit「真跑證據」規則)。升級路 = 對 fail-closed gate 逐支補「注入違規必 exit 1」self-test(fork harness 模式推廣)。歸 governance-evolution roadmap 方向 5 品質回灌。
29
+ 2. **SKILL.md 內容 claim-vs-behavior**:skill 文字宣稱的流程 vs 實際 hook/script 行為,無逐句機械比對(A.1b 只對 component spec)。季度 prune D5 部分覆蓋。
30
+ 3. **eslint-plugin 未發佈**(批次 B tracked)。
31
+ 4. **planning / 純文字 reference 靜置漂移**:by-design 低頻,D1/D4/D8 季度兜底;規則 = 活的內容必有 memory pointer。
32
+
33
+ **加新治理物時的規矩**:新 home / 新 artifact 類型 → 本表加 row(誰稽核它、多常跑);沒 row = deep-audit C.0b 抓(已接線)。
@@ -204,14 +204,14 @@ const isActive = variant === "meta" ? false : (... 同上)
204
204
 
205
205
  ```bash
206
206
  # 找出可疑的 raw ItemPrefix wrap 用法(應該幾乎沒有)
207
- rg '<ItemPrefix>\s*<[A-Z]' src/design-system
207
+ rg '<ItemPrefix>\s*<[A-Z]' packages/design-system/src
208
208
 
209
209
  # 找出硬寫 size 的 Avatar / Icon(在 row primitive 內應該為零)
210
210
  rg '<Avatar[^>]*size=\{[0-9]+\}' packages/design-system/src/components/{Sidebar,TreeView,SelectMenu,DropdownMenu}
211
211
  rg 'size=\{16\}|size=\{20\}|size=\{24\}' packages/design-system/src/components/{Sidebar,TreeView}
212
212
 
213
213
  # 找出沒走 ItemInlineAction 的 inline action button
214
- rg "group/action.*relative grid place-content-center" src/design-system
214
+ rg "group/action.*relative grid place-content-center" packages/design-system/src
215
215
  ```
216
216
 
217
217
  任何一條結果非空就是 drift,要修。
@@ -23,7 +23,7 @@
23
23
  **他拿到**:scaffold + 治理 via C-prime committed-config(.claude hooks + SessionStart preamble 注入)+ DS + 治理本體 via npm
24
24
  **DS 取得方式**:`@qijenchen/design-system` npm registry(`^X.Y.Z`)
25
25
  **Governance 取得**:committed `.claude/settings.json`(dispatcher hooks + fail-open bootstrap)+ SessionStart 注入 npm-current preamble;本體在 npm `ds-canonical/fork`(`npm install` / `npm run sync-all` 同步)。**不需 /plugin install**(雲端不可靠 #62174/#63028)
26
- **E2E 流程**:`fork → npm install(治理本體隨 npm + committed hook 自動生效,免 plugin)→ claude → npm run setup:netlify(Netlify env var 設 STORYBOOK_BASIC_AUTH = user:password,免費機制走 edge function basic-auth)→ npm run create-app order-dashboard → npm install → npm run storybook → git push`
26
+ **E2E 流程**:`fork → npm install(治理本體隨 npm + committed hook 自動生效,免 plugin)→ claude → npm run setup:netlify(自動 site create/link + 引導在 Netlify dashboard 設 STORYBOOK_BASIC_AUTH = user:password env var — CLI 不提供 one-shot setup,script 印 dashboard URL + step-by-step;免費機制走 edge function basic-auth)→ npm run create-app order-dashboard → npm install → npm run storybook → git push`
27
27
  **禁**:import `@qijenchen/design-system/src/**` 或 `/dist/**`(`lint:imports` 攔)
28
28
 
29
29
  ## 2. SSOT Architecture
@@ -56,12 +56,9 @@ ajenchen/ds-product-template (published repo) ← Mirror artifact ────
56
56
 
57
57
  ## 3. Mirror Workflow Chain(Scenario B 自動同步)
58
58
 
59
- **Trigger**:DS push main + template-affecting paths(per `.github/workflows/mirror-to-published-template.yml`):
60
- - `apps/template/**`
61
- - `scripts/create-app.mjs` + `scripts/setup-netlify-access.mjs` + `scripts/check-plugin-installed.mjs` + `scripts/build-published-template-mirror.mjs`
62
- - `.devcontainer/**`
63
- - `template/ds-product-template/**`
64
- - `package.json`
59
+ **Trigger**(雙觸發,2026-06-16 起):
60
+ - `workflow_run: Release completed` = **發版主路徑**(Release 成功 → npm 已有新版本 → mirror 內部 poll 第一輪即過,零等待)
61
+ - DS push main + template-affecting paths(scaffold 改動路徑;版本未上 npm 時 graceful skip 不長等)— path 列表以 `.github/workflows/mirror-to-published-template.yml` `paths:` 為準(含 apps/template、consumer scripts、.devcontainer、template/ds-product-template、package.json 等),不在此逐條複寫
65
62
 
66
63
  **Build**:`scripts/build-published-template-mirror.mjs` 用 ALLOWLIST(non denylist,per codex r5)+ transform:
67
64
  - Flatten `template/ds-product-template/*` → mirror root
@@ -69,7 +66,7 @@ ajenchen/ds-product-template (published repo) ← Mirror artifact ────
69
66
  - Transform `apps/template/package.json`:`@qijenchen/design-system: "*"` → `^X.Y.Z`
70
67
  - 4 integrity scans:DS source residue / secret leak / Storybook glob / package dep
71
68
 
72
- **Push**:`workflow + CROSS_REPO_TOKEN PAT(user one-time setup,workflow 印中文指引若 missing)` force-push to `ajenchen/ds-product-template` main
69
+ **Push**:`workflow + CROSS_REPO_TOKEN PAT(user one-time setup,workflow 印中文指引若 missing + fail-loud exit 1)` clone-and-overlay push to `ajenchen/ds-product-template` main — git clone + `rsync --checksum --delete --exclude='.github/workflows'`(保留 published repo 既有 workflows)+ fetch-rebase-retry 迴圈(非 force-push;2026-06-07 競態修)
73
70
 
74
71
  ## 4. Test Cases(Claude 19 + codex 18 union → 20 canonical)
75
72
 
@@ -106,7 +103,7 @@ ajenchen/ds-product-template (published repo) ← Mirror artifact ────
106
103
  | M4 | Storybook glob apps-only(no `../packages/**`)| build script integrity scan 3 |
107
104
  | M5 | package.json workspaces apps-only + DS dep transformed | build script integrity scan 4 |
108
105
  | M6 | `apps/template/package.json` DS dep `*` → `^X.Y.Z` | build script auto transform |
109
- | M7 | Force-push idempotent(reproducible)| `node scripts/build-published-template-mirror.mjs --out=/tmp/x` 多次 = 相同 output |
106
+ | M7 | Clone-and-overlay push idempotent(reproducible)| `node scripts/build-published-template-mirror.mjs --out=/tmp/x` 多次 = 相同 output |
110
107
 
111
108
  ## 5. Verify Checkpoints — 後續增刪改 reference 此 SSOT
112
109
 
@@ -50,7 +50,7 @@ CLAUDE.md `# SSOT 消費 canonical` 的詳表 + 反例。主章留核心 + point
50
50
  */
51
51
  ```
52
52
 
53
- Hook `check_ssot_consultation.sh`(retired;改靠 mindset #2 + `check_canonical_propagation.sh`)( Write tsx `packages/design-system/src/components/` `src/explorations/` 若檔內無上述註解區 warn 要求補齊)
53
+ Hook `check_ssot_consultation.sh` retired;**2026-07-07 `check_ssot_header_declaration.sh` 精簡復活**(新建 production tsx 必帶「── 消費的 SSOT ──」段,P0 BLOCKER)+ mindset #2 + `check_canonical_propagation.sh`。(2026-07-10 hunt stale 描述)
54
54
 
55
55
  ## 禁止:隱性自創
56
56
 
@@ -60,4 +60,4 @@ Hook `check_ssot_consultation.sh`(retired;改靠 mindset #2 + `check_canonical_p
60
60
  - 自寫 `<button aria-label="Close"><X /></button>` 作 dismiss(應用 `ItemInlineAction`)
61
61
  - 自寫 Row `<div><Icon /><span>label</span><Button /></div>`(應用 `<MenuItem>` + slot)
62
62
  - 自訂 Input `variant="custom-name"` 未先 grep 既有 variant 值
63
- - 在 Toolbar 用 `<input className="bg-transparent border-0 ...">`(應用 `<Input variant="bare">` 若既有;無 Ambiguity Protocol)
63
+ - 在 Toolbar 用 `<input className="bg-transparent border-0 ...">`(應用 `<Input size="sm" autoWidth>` 標準 default variant;`variant="bare"` 已於 2026-07-09 退役,不再使用)
@@ -12,29 +12,30 @@
12
12
 
13
13
  | Interface | Owner spec | Canonical sentence | Drift status | Last divergence event |
14
14
  |---|---|---|---|---|
15
- | **DataTable body cell internal indicator**(display endAction / clear / edit indicator)| `data-table.spec.md`「Body cell internal」row + `inline-action.spec.md`「DataTable body cell internal」row | 「Body cell internal = Field family endAction(自動繼承)」「Field display 元件已對齊」 | ✅ aligned:2026-05-09 D-path retired — `getEditIndicator(colType)` parallel system 移除,indicator authority 移交 Field naked-display `showDisplayEndIcon` opt-in,cellEl 不再 render parallel indicator(見 data-table.tsx「D-path retired」註解)| 2026-05-08 round 5 → 2026-05-09 resolved |
15
+ | **DataTable body cell internal indicator**(display endAction / clear / edit indicator)| `data-table.spec.md`「Body cell internal」row + `inline-action.spec.md`「DataTable body cell internal」row | 「Body cell internal = Field family endAction(自動繼承)」「Field display 元件已對齊」 | ✅ aligned:2026-05-09 D-path retired — `getEditIndicator(colType)` parallel system 移除,indicator authority 移交 Field naked-display `showDisplayEndIcon` opt-in,cellEl 不再 render parallel indicator(見 data-table.tsx「D-path retired」註解);2026-07-08 A 案:cell-registry 預設不再傳(display 態零恆顯 icon,prop 留 opt-in 逃生門,見 field.spec L6 v16)| 2026-05-08 round 5 → 2026-05-09 resolved |
16
16
  | **Field naked variant state ring**(hover / focus / open / error)| `field-wrapper.tsx` cva compoundVariants(v13.3)+ `field.spec.md`「focus dominates」段 | 「SSOT 在 field-wrapper.tsx 三 compoundVariant — 改一處全 control + cell + variant 跟動」 | ✅ aligned(2026-05-08 D path canary 違反後 revert)| 2026-05-08 round 4(D path canary 違反 SSOT,已 revert `f0faab9`)|
17
17
  | **Row prefix/suffix slot**(`<ItemPrefix>` / `<ItemSuffix>`)| `patterns/element-anatomy/item-anatomy.spec.md:175+190` | 「row prefix/suffix slot 必走 patterns/element-anatomy L1 primitive」「`h-[1lh] shrink-0 flex items-center` 普世正確」 | ✅ aligned(hook `check_pattern_invariants.sh` C.4 enforce)| — |
18
18
  | **Inline action gap**(ItemInlineAction sibling spacing)| `patterns/element-anatomy/inline-action.spec.md`「多個 inline action 間距」段 | 「inline-action 跟 sibling gap 必 = `gap-2`(8px)」 | ✅ aligned(hook C.2 enforce)| — |
19
19
  | **Drag visual**(drop indicator / drag overlay)| `lib/drag-visual.ts`(2026-05-06 v14.5)+ `tree-view.spec.md:265` | 「TreeView 是 DS 內最早 codified 的 drag canonical,DataTable row drag + column reorder 都 inherit via drag-visual.ts SSOT module」 | ✅ aligned | — |
20
- | **Color tokens**(primitive vs semantic)| `tokens/color/color.spec.md`(架構流派定位)+ `tokens/color/semantic.css` | 「禁 primitive 色名作 utility,用 semantic alias」 | ✅ aligned(hook D.3 enforce)| — |
20
+ | **Color tokens**(primitive vs semantic)| `tokens/color/color.spec.md`(架構流派定位)+ `tokens/color/semantic.css` | 「禁 primitive 色名作 utility,用 semantic alias」 | ✅ aligned(hook `check_naming_and_abstraction.sh` D.3 enforce)| — |
21
21
  | **Layout space**(region/element + 親疏三級)| `tokens/layoutSpace/layoutSpace.spec.md` v6(原 memory `feedback_layout_v6_canonical.md` 已 retire)| 「region/element + bounded/unbounded + 親疏三級」 | ✅ aligned(2026-05-01 flush variant retire)| 2026-05-01 |
22
22
  | **DataTable scroll**(3-region synced + cross-OS scrollbar)| `data-table.spec.md:245-251` | 「center body 用 native overflow-x-auto(非 ScrollArea),pinned column 三 region 同步」 | ✅ aligned(v15.13 interim CSS parity for Windows Bug H,deferred ScrollArea full migration)| 2026-04-30 / 2026-05-07 |
23
23
  | **Cell display vs edit content position**(picker offset)| `field.spec.md`「Layout Family 4」段 + `data-table.spec.md`「Body cell internal」row | 「Field control display + edit 共用同 wrapper geometry」 | ⚠ partial:DataTable cell 場景已對齊(D-path `showDisplayEndIcon` opt-in 走 Field naked-display);standalone `mode="display"` 仍 bare-span(documented deferral,見 select.tsx 檔頭 `@renderer-symmetry-allow`)| 2026-05-07~08 round 1-5 → 2026-05-09 D-path 部分解決 |
24
24
  | **Field state machine focus dominates**(v13.3)| `field-wrapper.tsx` cva compoundVariants + `field.spec.md`「focus dominates」段 + `check_field_family_invariants.sh` A.3 | 「focus dominates everything;naked 不寫平行 outline ring」 | ✅ aligned;hook A.3 enforce | 2026-05-06 v9-v13.3 5 round refinement |
25
25
  | **Solo dev workflow**(1 chat = 1 branch / Netlify gate / squash merge)| `feedback_solo_dev_workflow.md` + CLAUDE.md「Git solo-work canonical」 | 「1 chat = 1 working branch;Netlify preview = user gate;『push / OK』trigger 才 merge main」 | ✅ aligned(M28 + hook `check_solo_workflow.sh`)| 2026-05-08 M28 codify |
26
26
  | **Wrapper-vs-primitive schema unify**(SelectOption / MenuItemProps 等)| `SelectMenu/select-menu.tsx` SelectMenuOption + `Combobox/combobox.tsx` extends + `PeoplePicker/people-picker.tsx` extends | 「wrapper API schema 必 `extends primitive`,wrapper 內部 mapping 必 forward 全 primitive surface field(M30)」 | ✅ aligned(2026-05-10 Round 1 commit `561945b` Combobox extends + forward 全 field;PeoplePicker 對齊 + hook `check_wrapper_primitive_schema_drift.sh` BLOCKER)| 2026-05-10 M30 codify |
27
+ | **空值顯示符號 + 分流**(empty value display)| `field-context.ts` `useFieldEmptyDisplay()`(分流 hook)+ `field-wrapper.tsx` `EMPTY_DISPLAY = '-'`(半形常數)+ `field-controls.spec.md`「null / undefined 值」段 | 「符號 = 半形 hyphen `-`(U+002D),**非**全形 em dash;`surface==='table-cell' && isEditable ? '' : '-'`;可編輯 form edit 走 native placeholder。全 Field family 空值渲染必經 hook,consumer 禁直引 `EMPTY_DISPLAY`」 | ✅ aligned(2026-07-08 user 拍板半形;hook `check_field_family_invariants.sh` A.6 BLOCKER — 禁非 owner 直引常數 + 禁 hardcode 全形 em dash;DescriptionList / ProfileCard / FileViewer consumer 同步半形)| 2026-07-08 user directive |
27
28
 
28
29
  ## How to maintain
29
30
 
30
31
  - 新 interface 第一次 surface → 加進本 index
31
32
  - 新 divergence 發現 → 加 row + 標 ⚠ DRIFT
32
33
  - Drift 解決 → 改 ✅ aligned
33
- - 重大 round 結束 → audit Dim 38 grep verify
34
+ - 重大 round 結束 → row 反 grep owner spec/code 驗仍一致(`/deep-audit-cross-codex` Phase A 必讀清單已含本檔,見 `phase-a-workflow.md:15`;無專屬 audit dim 機械化)
34
35
 
35
36
  ## 與 hook 關係
36
37
 
37
- - `check_ds_anchor_preflight.sh`(live,soft warn)— 偵測編 Field / DataTable / patterns code stderr 提醒「先 grep ssot-index.md」
38
+ - `check_ds_anchor_preflight.sh`(live,P0 BLOCKER exit 2,2026-07-07 升級)— 偵測 production tsx / apps consumer DS primitive wrap 而無 canonical read trace → block;bypass `CLAUDE_BYPASS_DS_ANCHOR=1`(audit-logged)
38
39
  - `check_field_family_invariants.sh` A.3 — 機械化 enforce v13.3 SSOT
39
40
  - `check_pattern_invariants.sh` C.4 — 機械化 enforce row slot SSOT
40
41
  - `check_canonical_propagation.sh` E.2 — 機械化 enforce L3 primitive import