@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
@@ -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"
@@ -230,6 +230,118 @@ expect_silent "25. P8 nearmiss shadow-[var(--elevation-100)] → silent"
230
230
  run_hook "$PROD_TSX" 'export const C = () => <div className="max-w-[600px] grid-cols-[1fr_2fr]">x</div>'
231
231
  expect_silent "26. P8 nearmiss max-w-[600px]/grid-cols-[...](非色字 shadow)→ silent"
232
232
 
233
+ # ── 手刻 menu-item 可點列(2026-07-10 WM TypeSettingsDialog 左 rail 錨例)──
234
+ # 27. POSITIVE:手刻 button + hover:bg-neutral-hover + bg-neutral-selected 成對 → BLOCK
235
+ run_hook "$PROD_TSX" 'const cls = `flex w-full items-center gap-2 rounded-md hover:bg-neutral-hover ${sel ? "bg-neutral-selected" : ""}`; export const C = () => <button type="button" className={cls}>Task</button>'
236
+ expect_block "27. 手刻 nav row(hover+selected 成對)→ BLOCK"
237
+
238
+ # 28. NEGATIVE:同簽名 token 出現但已消費 <MenuItem>(正道)→ silent
239
+ run_hook "$PROD_TSX" 'export const C = () => <MenuItem size="sm" selected startContent={<Badge/>}>Task</MenuItem> /* hover:bg-neutral-hover bg-neutral-selected */'
240
+ expect_silent "28. 消費 <MenuItem> → silent"
241
+
242
+ # 29. NEGATIVE:只有 hover 無 selected(單純 hover row,非 menu-item family 簽名)→ silent
243
+ run_hook "$PROD_TSX" 'export const C = () => <button className="hover:bg-neutral-hover">row</button>'
244
+ expect_silent "29. 只 hover 無 selected → silent"
245
+
246
+ # 30. NEGATIVE:escape marker → silent
247
+ run_hook "$PROD_TSX" 'export const C = () => <div className="hover:bg-neutral-hover bg-neutral-selected">x</div> // @nav-row-handcraft-ok: calendar cell 非 menu 語義'
248
+ expect_silent "30. @nav-row-handcraft-ok escape → silent"
249
+
250
+ # ── 2026-07-10 批次 A(治理覆蓋 matrix 收官)──
251
+ # 31. C5 POSITIVE:亮色底 + text-white 對比配對違規 → BLOCK
252
+ run_hook "$PROD_TSX" 'export const T = () => <span className="bg-[var(--color-amber-6)] text-white size-4">A</span>'
253
+ expect_block "31. C5 亮色底+text-white 配對 → BLOCK"
254
+
255
+ # 32. C5 NEGATIVE:CAT_SOLID 正道(深字桶自帶 on-emphasis-dark)→ silent
256
+ run_hook "$PROD_TSX" 'export const T = () => <span className={`size-4 ${CAT_SOLID[hue]}`}>A</span>'
257
+ expect_silent "32. C5 消費 CAT_SOLID → silent"
258
+
259
+ # 33. C18 POSITIVE:children 計數括號串接 → BLOCK
260
+ run_hook "$PROD_TSX" 'export const H = () => <span>{group.label} ({items.length})</span>'
261
+ expect_block "33. C18 {label} ({count}) 串接 → BLOCK"
262
+
263
+ # 34. C18 NEGATIVE:aria-label 字串層(attr 非 children)→ silent
264
+ run_hook "$PROD_TSX" 'export const H = () => <span aria-label={`${label} (${count})`}>{label}</span>'
265
+ expect_silent "34. C18 aria-label 括號形 → silent"
266
+
267
+ # 35. C17 POSITIVE:vertical Separator 無 mx → BLOCK
268
+ run_hook "$PROD_TSX" 'export const B = () => <><Button>A</Button><Separator orientation="vertical" className="h-6" /><Button>B</Button></>'
269
+ expect_block "35. C17 vertical Separator 無 mx → BLOCK"
270
+
271
+ # 36. C17 NEGATIVE:h-6 mx-1 canonical → silent
272
+ run_hook "$PROD_TSX" 'export const B = () => <><Button>A</Button><Separator orientation="vertical" className="h-6 mx-1" /><Button>B</Button></>'
273
+ expect_silent "36. C17 h-6 mx-1 canonical → silent"
274
+
275
+ # 37. C20 POSITIVE:手刻 underline 連結字 → BLOCK
276
+ run_hook "$PROD_TSX" 'export const D = () => <span className="text-primary underline">upload</span>'
277
+ expect_block "37. C20 裸 underline 連結 → BLOCK"
278
+
279
+ # 38. C20 NEGATIVE:no-underline(合規移除底線)→ silent
280
+ run_hook "$PROD_TSX" 'export const D = () => <a className="no-underline text-primary">upload</a>'
281
+ expect_silent "38. C20 no-underline → silent"
282
+
283
+ # 39. C10 POSITIVE:spacer 把 Search 推最右 → BLOCK
284
+ run_hook "$PROD_TSX" 'export const T = () => <div><Button>Add</Button><span className="flex-1" /><Input placeholder="Search employees" /></div>'
285
+ expect_block "39. C10 業務 search 被推最右 → BLOCK"
286
+
287
+ # 40. C10 NEGATIVE:search 在業務層(無 spacer 前置)→ silent
288
+ run_hook "$PROD_TSX" 'export const T = () => <div><Button>Add</Button><Input placeholder="Search employees" /><span className="flex-1" /></div>'
289
+ expect_silent "40. C10 search 歸業務層 → silent"
290
+
291
+ # 41. C11 POSITIVE:DialogHeader 手放 X(雙 X)→ BLOCK
292
+ run_hook "$PROD_TSX" 'export const D = () => <DialogHeader><DialogTitle>Edit</DialogTitle><Button iconOnly startIcon={X} aria-label="Close" /></DialogHeader>'
293
+ expect_block "41. C11 DialogHeader 雙 X → BLOCK"
294
+
295
+ # 42. C11 NEGATIVE:header 操作走 actions slot → silent
296
+ run_hook "$PROD_TSX" 'export const D = () => <DialogHeader actions={<Button iconOnly startIcon={X} aria-label="Prev" />}><DialogTitle>Edit</DialogTitle></DialogHeader>'
297
+ expect_silent "42. C11 actions slot → silent"
298
+
299
+ # 43. C12 POSITIVE:Select 硬寬 w-36 → BLOCK
300
+ run_hook "$PROD_TSX" 'export const F = () => <Select className="w-36" options={opts} />'
301
+ expect_block "43. C12 Select 硬寬 w-36 → BLOCK"
302
+
303
+ # 44. C12 NEGATIVE:width="hug" 語義軸 → silent
304
+ run_hook "$PROD_TSX" 'export const F = () => <Select width="hug" options={opts} />'
305
+ expect_silent "44. C12 width=hug → silent"
306
+
307
+ # 45. named-import 除鏽 POSITIVE:無 DS. 前綴的 LinkInput placeholder-only 也要抓 → BLOCK
308
+ run_hook "$PROD_TSX" 'export const L = () => <LinkInput placeholder="https://" />'
309
+ expect_block "45. named-import <LinkInput placeholder-only → BLOCK(除鏽)"
310
+
311
+ # ── C19 兩欄 dialog 共用捲軸(2026-07-10 user 拍板組合 canonical)──
312
+ # 46. POSITIVE:兩欄(border-l)+ 只有 1 個 ScrollArea = 共用捲軸 → BLOCK
313
+ run_hook "$PROD_TSX" 'export const D = () => <DialogBody><ScrollArea><div className="flex"><div>main</div><aside className="border-l">meta</aside></div></ScrollArea></DialogBody>'
314
+ expect_block "46. C19 兩欄共用單一 ScrollArea → BLOCK"
315
+
316
+ # 47. NEGATIVE:各欄自帶 ScrollArea(組合 canonical)→ silent
317
+ run_hook "$PROD_TSX" 'export const D = () => <DialogBody><div className="flex"><ScrollArea>main</ScrollArea><aside className="border-l"><ScrollArea>meta</ScrollArea></aside></div></DialogBody>'
318
+ expect_silent "47. C19 各欄自帶 ScrollArea → silent"
319
+
320
+ # 48. NEGATIVE:escape → silent
321
+ run_hook "$PROD_TSX" 'export const D = () => <DialogBody><div className="flex border-l">x</div></DialogBody> // @two-pane-dialog-ok: 非兩欄,版面裝飾線'
322
+ expect_silent "48. C19 @two-pane-dialog-ok escape → silent"
323
+
324
+ # ── C7 SelectMenu 直用 + C13 手刻 section header(2026-07-10 收官)──
325
+ # 49. C7 POSITIVE:<SelectMenu> 直用 → BLOCK
326
+ run_hook "$PROD_TSX" 'export const M = () => <SelectMenu options={opts} onSelect={pick} />'
327
+ expect_block "49. C7 <SelectMenu> 直用 → BLOCK"
328
+
329
+ # 50. C7 NEGATIVE:<Select>(正道)→ silent
330
+ run_hook "$PROD_TSX" 'export const M = () => <Select options={opts} onChange={pick} />'
331
+ expect_silent "50. C7 <Select> 正道 → silent"
332
+
333
+ # 51. C13 POSITIVE:手刻可收合標題列(Chevron + justify-between + button)→ BLOCK
334
+ run_hook "$PROD_TSX" 'export const H = () => <button onClick={toggle} className="flex w-full items-center justify-between"><span>Description</span><ChevronDown className="size-4" /></button>'
335
+ expect_block "51. C13 手刻可收合標題列 → BLOCK"
336
+
337
+ # 52. C13 NEGATIVE:共用 SectionHeader 元件(正道)→ silent
338
+ run_hook "$PROD_TSX" 'export const H = () => <SectionHeader title="Description" collapsed={c} onToggle={toggle} />'
339
+ expect_silent "52. C13 共用 SectionHeader → silent"
340
+
341
+ # 53. C13 NEGATIVE:escape(非 section 標題語義)→ silent
342
+ run_hook "$PROD_TSX" 'export const P = () => <button onClick={next} className="flex justify-between">next<ChevronRight /></button> // @section-header-ok: 分頁導航非 section 標題'
343
+ expect_silent "53. C13 @section-header-ok escape → silent"
344
+
233
345
  echo ""
234
346
  echo "=== Summary ==="
235
347
  echo "Passed: $PASS / $((PASS + FAIL))"
@@ -161,12 +161,19 @@ expect_pass_silent "N4. DS internal stories → excluded silent"
161
161
  run_hook "Read" "$CONSUMER_STORY" "$CONTENT_VIOLATION"
162
162
  expect_pass_silent "N5. tool=Read → silent"
163
163
 
164
- # N6. over-broad guard A:bare <Dialog>(no DS. namespace prefix)→ silent
164
+ # N6. over-broad guard A:bare <Dialog>(no DS. namespace prefix)from consumer-local import → silent
165
165
  # consumer 用自己的 local Dialog,不是高風險 DS primitive → 不該 fire
166
166
  CONTENT_BARE='import { Dialog } from "./local-dialog";
167
167
  export const Basic = () => <Dialog open>hi</Dialog>;'
168
168
  run_hook "Write" "$CONSUMER_STORY" "$CONTENT_BARE"
169
- expect_pass_silent "N6. bare <Dialog> (no DS. prefix) → silent (over-broad guard)"
169
+ expect_pass_silent "N6. bare <Dialog> (local import) → silent (over-broad guard)"
170
+
171
+ # P5. named-import 除鏽 POSITIVE(2026-07-10):bare <Dialog> 但由 DS package named-import 進來
172
+ # → 是真 DS Dialog(fork 慣用 named import 繞過 <DS.> 前綴)→ 無 marker 必 BLOCK
173
+ CONTENT_NAMED='import { Dialog, Button } from "@qijenchen/design-system";
174
+ export const Basic = () => <Dialog open><Button>ok</Button></Dialog>;'
175
+ run_hook "Write" "$CONSUMER_STORY" "$CONTENT_NAMED"
176
+ expect_block "P5. named-import <Dialog> from DS pkg 無 marker → BLOCK" "CONSUMER-STORY-BASELINE BLOCKER"
170
177
 
171
178
  # N7. over-broad guard B:comment / prose mentioning "Dialog DataTable Sheet" but no JSX usage → silent
172
179
  CONTENT_PROSE='// This story demonstrates a layout. We avoid Dialog and DataTable here.