@qijenchen/design-system 0.1.0-beta.10 → 0.1.0-beta.13

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 (307) hide show
  1. package/CLAUDE.md +201 -0
  2. package/README.md +7 -15
  3. package/cli-init.mjs +90 -0
  4. package/ds-canonical/commands/README.md +26 -0
  5. package/ds-canonical/commands/gov-status.md +79 -0
  6. package/ds-canonical/hooks/README.md +145 -0
  7. package/ds-canonical/hooks/_log-fire.sh +44 -0
  8. package/ds-canonical/hooks/block_prototype_imports.py +111 -0
  9. package/ds-canonical/hooks/check_app_shell_primary_header_consistency.sh +68 -0
  10. package/ds-canonical/hooks/check_audit_post_report_validator.sh +88 -0
  11. package/ds-canonical/hooks/check_audit_sample_escape.sh +73 -0
  12. package/ds-canonical/hooks/check_benchmark_citation.sh +106 -0
  13. package/ds-canonical/hooks/check_canonical_propagation.sh +189 -0
  14. package/ds-canonical/hooks/check_chrome_header_handcraft.sh +70 -0
  15. package/ds-canonical/hooks/check_codex_brief_invariants.sh +83 -0
  16. package/ds-canonical/hooks/check_codex_collab_5step.sh +108 -0
  17. package/ds-canonical/hooks/check_datatable_invariants.sh +117 -0
  18. package/ds-canonical/hooks/check_dim_count_drift.sh +72 -0
  19. package/ds-canonical/hooks/check_field_controls_contracts.sh +110 -0
  20. package/ds-canonical/hooks/check_field_family_invariants.sh +205 -0
  21. package/ds-canonical/hooks/check_file_size_budget.sh +60 -0
  22. package/ds-canonical/hooks/check_header_with_tabs_border.sh +87 -0
  23. package/ds-canonical/hooks/check_main_branch_workbench.sh +93 -0
  24. package/ds-canonical/hooks/check_naming_and_abstraction.sh +165 -0
  25. package/ds-canonical/hooks/check_opacity_token_usage.sh +149 -0
  26. package/ds-canonical/hooks/check_pattern_invariants.sh +194 -0
  27. package/ds-canonical/hooks/check_peoplepicker_ssot_drift.sh +56 -0
  28. package/ds-canonical/hooks/check_pixel_quantified_audit.sh +53 -0
  29. package/ds-canonical/hooks/check_propose_plain_chinese.sh +74 -0
  30. package/ds-canonical/hooks/check_propose_pre_grep_verify.sh +70 -0
  31. package/ds-canonical/hooks/check_select_all_canonical.sh +58 -0
  32. package/ds-canonical/hooks/check_solo_workflow.sh +258 -0
  33. package/ds-canonical/hooks/check_spec_class_drift.sh +88 -0
  34. package/ds-canonical/hooks/check_story_invariants.sh +612 -0
  35. package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +105 -0
  36. package/ds-canonical/hooks/check_tab_lg_chrome_header_equal.sh +66 -0
  37. package/ds-canonical/hooks/check_wrapper_primitive_schema_drift.sh +104 -0
  38. package/ds-canonical/hooks/enforce_home_charter.sh +44 -0
  39. package/ds-canonical/hooks/inject_pending_self_audit.sh +204 -0
  40. package/ds-canonical/hooks/lib/_approval_re.sh +33 -0
  41. package/ds-canonical/hooks/lib/_code_quality.sh +73 -0
  42. package/ds-canonical/hooks/lib/_cva_default_sync.sh +69 -0
  43. package/ds-canonical/hooks/lib/_governance_coverage_check.sh +49 -0
  44. package/ds-canonical/hooks/lib/_hardcoded_strings.sh +163 -0
  45. package/ds-canonical/hooks/lib/_layout_space_canonical.sh +56 -0
  46. package/ds-canonical/hooks/lib/_overlay_handcraft.sh +141 -0
  47. package/ds-canonical/hooks/lib/_person_data_richness.sh +42 -0
  48. package/ds-canonical/hooks/lib/_story_compile_drift.sh +48 -0
  49. package/ds-canonical/hooks/lib/_token_hygiene.sh +95 -0
  50. package/ds-canonical/hooks/log_governance_fires.sh +50 -0
  51. package/ds-canonical/hooks/log_skill_invokes.sh +41 -0
  52. package/ds-canonical/hooks/post_edit_dispatcher.sh +62 -0
  53. package/ds-canonical/hooks/retired/check_anatomy_section_numbering.sh +106 -0
  54. package/ds-canonical/hooks/retired/check_avatar_hovercard.sh +90 -0
  55. package/ds-canonical/hooks/retired/check_button_icon_literal.sh.retired-2026-04-28 +38 -0
  56. package/ds-canonical/hooks/retired/check_container_breathing.sh +142 -0
  57. package/ds-canonical/hooks/retired/check_governance_compliance.sh +61 -0
  58. package/ds-canonical/hooks/retired/check_icon_only_padding_formula.sh +104 -0
  59. package/ds-canonical/hooks/retired/check_item_content_primitive.sh +150 -0
  60. package/ds-canonical/hooks/retired/check_item_list_gap.sh +153 -0
  61. package/ds-canonical/hooks/retired/check_sideoffset_canonical.sh +65 -0
  62. package/ds-canonical/hooks/retired/check_spec_iteration_tag.sh +87 -0
  63. package/ds-canonical/hooks/retired/check_ssot_consultation.sh +88 -0
  64. package/ds-canonical/hooks/retired/check_sync_update.sh +20 -0
  65. package/ds-canonical/hooks/retired/check_third_party_dom_verified.sh +95 -0
  66. package/ds-canonical/hooks/retired/enforce_home_charter.sh +125 -0
  67. package/ds-canonical/hooks/retired/post_edit_canonical_interrogate.sh +109 -0
  68. package/ds-canonical/hooks/retired/pre_edit_spec_check.sh +68 -0
  69. package/ds-canonical/hooks/retired/pre_new_component_spec.sh +39 -0
  70. package/ds-canonical/hooks/retired/pre_write_subsumption_check.sh +112 -0
  71. package/ds-canonical/hooks/retired/stop_meta_self_audit.sh.retired-2026-05-13 +76 -0
  72. package/ds-canonical/hooks/retired/tests/test_check_anatomy_section_numbering.sh +14 -0
  73. package/ds-canonical/hooks/retired/tests/test_check_avatar_hovercard.sh +15 -0
  74. package/ds-canonical/hooks/retired/tests/test_check_container_breathing.sh +15 -0
  75. package/ds-canonical/hooks/retired/tests/test_check_governance_compliance.sh +15 -0
  76. package/ds-canonical/hooks/retired/tests/test_check_icon_only_padding_formula.sh +79 -0
  77. package/ds-canonical/hooks/retired/tests/test_check_item_content_primitive.sh +15 -0
  78. package/ds-canonical/hooks/retired/tests/test_check_item_list_gap.sh +163 -0
  79. package/ds-canonical/hooks/retired/tests/test_check_sideoffset_canonical.sh +15 -0
  80. package/ds-canonical/hooks/retired/tests/test_check_spec_iteration_tag.sh +15 -0
  81. package/ds-canonical/hooks/retired/tests/test_check_ssot_consultation.sh +15 -0
  82. package/ds-canonical/hooks/retired/tests/test_check_sync_update.sh +14 -0
  83. package/ds-canonical/hooks/retired/tests/test_check_third_party_dom_verified.sh +15 -0
  84. package/ds-canonical/hooks/retired/tests/test_enforce_home_charter.sh +15 -0
  85. package/ds-canonical/hooks/retired/tests/test_pre_edit_spec_check.sh +15 -0
  86. package/ds-canonical/hooks/retired/tests/test_pre_new_component_spec.sh +15 -0
  87. package/ds-canonical/hooks/retired/tests/test_pre_write_subsumption_check.sh +63 -0
  88. package/ds-canonical/hooks/session_start_governance_check.sh +263 -0
  89. package/ds-canonical/hooks/stop_passive_logging.sh +322 -0
  90. package/ds-canonical/hooks/stop_self_audit.sh +450 -0
  91. package/ds-canonical/hooks/tests/KNOWN-BROKEN.md +15 -0
  92. package/ds-canonical/hooks/tests/run-all.sh +76 -0
  93. package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +143 -0
  94. package/ds-canonical/hooks/tests/test_check_app_shell_primary_header_consistency.sh +140 -0
  95. package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +115 -0
  96. package/ds-canonical/hooks/tests/test_check_audit_sample_escape.sh +93 -0
  97. package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +115 -0
  98. package/ds-canonical/hooks/tests/test_check_canonical_propagation.sh +133 -0
  99. package/ds-canonical/hooks/tests/test_check_chrome_header_handcraft.sh +123 -0
  100. package/ds-canonical/hooks/tests/test_check_code_quality.sh +15 -0
  101. package/ds-canonical/hooks/tests/test_check_codex_collab_5step.sh +96 -0
  102. package/ds-canonical/hooks/tests/test_check_cva_default_sync.sh +15 -0
  103. package/ds-canonical/hooks/tests/test_check_datatable_invariants.sh +122 -0
  104. package/ds-canonical/hooks/tests/test_check_dim_count_drift.sh +98 -0
  105. package/ds-canonical/hooks/tests/test_check_field_controls_contracts.sh +126 -0
  106. package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +194 -0
  107. package/ds-canonical/hooks/tests/test_check_file_size_budget.sh +32 -0
  108. package/ds-canonical/hooks/tests/test_check_hardcoded_strings.sh +14 -0
  109. package/ds-canonical/hooks/tests/test_check_header_with_tabs_border.sh +110 -0
  110. package/ds-canonical/hooks/tests/test_check_layout_space_canonical.sh +73 -0
  111. package/ds-canonical/hooks/tests/test_check_main_branch_workbench.sh +147 -0
  112. package/ds-canonical/hooks/tests/test_check_naming_and_abstraction.sh +136 -0
  113. package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +110 -0
  114. package/ds-canonical/hooks/tests/test_check_overlay_handcraft.sh +126 -0
  115. package/ds-canonical/hooks/tests/test_check_pattern_invariants.sh +148 -0
  116. package/ds-canonical/hooks/tests/test_check_peoplepicker_ssot_drift.sh +108 -0
  117. package/ds-canonical/hooks/tests/test_check_person_data_richness.sh +58 -0
  118. package/ds-canonical/hooks/tests/test_check_pixel_quantified_audit.sh +142 -0
  119. package/ds-canonical/hooks/tests/test_check_propose_plain_chinese.sh +126 -0
  120. package/ds-canonical/hooks/tests/test_check_propose_pre_grep_verify.sh +117 -0
  121. package/ds-canonical/hooks/tests/test_check_select_all_canonical.sh +125 -0
  122. package/ds-canonical/hooks/tests/test_check_solo_workflow.sh +201 -0
  123. package/ds-canonical/hooks/tests/test_check_spec_class_drift.sh +135 -0
  124. package/ds-canonical/hooks/tests/test_check_story_anatomy.sh.broken +197 -0
  125. package/ds-canonical/hooks/tests/test_check_story_category.sh.broken +187 -0
  126. package/ds-canonical/hooks/tests/test_check_story_compile_drift.sh +15 -0
  127. package/ds-canonical/hooks/tests/test_check_story_invariants.sh +209 -0
  128. package/ds-canonical/hooks/tests/test_check_story_name_jargon.sh.broken +53 -0
  129. package/ds-canonical/hooks/tests/test_check_story_slot_split.sh +156 -0
  130. package/ds-canonical/hooks/tests/test_check_substantive_edit_approval_preflight.sh +176 -0
  131. package/ds-canonical/hooks/tests/test_check_tab_lg_chrome_header_equal.sh +138 -0
  132. package/ds-canonical/hooks/tests/test_check_token_hygiene.sh +21 -0
  133. package/ds-canonical/hooks/tests/test_check_wrapper_primitive_schema_drift.sh +169 -0
  134. package/ds-canonical/hooks/tests/test_enforce_home_charter.sh +77 -0
  135. package/ds-canonical/hooks/tests/test_inject_pending_self_audit.sh +125 -0
  136. package/ds-canonical/hooks/tests/test_log_governance_fires.sh +10 -0
  137. package/ds-canonical/hooks/tests/test_log_skill_invokes.sh +7 -0
  138. package/ds-canonical/hooks/tests/test_post_edit_dispatcher.sh +108 -0
  139. package/ds-canonical/hooks/tests/test_session_start_governance_check.sh +143 -0
  140. package/ds-canonical/hooks/tests/test_stop_capture_metrics.sh +95 -0
  141. package/ds-canonical/hooks/tests/test_stop_governance_drift_check.sh.broken +125 -0
  142. package/ds-canonical/hooks/tests/test_stop_harvest_corrections.sh +10 -0
  143. package/ds-canonical/hooks/tests/test_stop_passive_logging.sh +100 -0
  144. package/ds-canonical/hooks/tests/test_stop_self_audit.sh +76 -0
  145. package/ds-canonical/hooks/tests/test_stop_tsc_sanity.sh +10 -0
  146. package/ds-canonical/references/README.md +43 -0
  147. package/ds-canonical/references/audit-coverage-vs-24-checklist.md +74 -0
  148. package/ds-canonical/references/build-ui-canonicals.md +69 -0
  149. package/ds-canonical/references/cva-patterns.md +41 -0
  150. package/ds-canonical/references/drag-canonical.md +331 -0
  151. package/ds-canonical/references/item-anatomy-recipe.md +225 -0
  152. package/ds-canonical/references/naming-conventions.md +56 -0
  153. package/ds-canonical/references/principle-dim-map.json +515 -0
  154. package/ds-canonical/references/props-naming.md +45 -0
  155. package/ds-canonical/references/spec-rules.md +58 -0
  156. package/ds-canonical/references/ssot-consultation.md +63 -0
  157. package/ds-canonical/references/ssot-index.md +40 -0
  158. package/ds-canonical/references/story-baseline-registry.json +79 -0
  159. package/ds-canonical/references/structural-token-retention.md +42 -0
  160. package/ds-canonical/references/tailwind-gotchas.md +87 -0
  161. package/ds-canonical/references/ui-dev-rules.md +60 -0
  162. package/ds-canonical/rules/README.md +34 -0
  163. package/ds-canonical/rules/meta-patterns.md +87 -0
  164. package/ds-canonical/rules/self-verify.md +53 -0
  165. package/ds-canonical/rules/spec-rules.md +25 -0
  166. package/ds-canonical/rules/story-rules.md +56 -0
  167. package/ds-canonical/rules/ui-development.md +87 -0
  168. package/ds-canonical/skills/README.md +88 -0
  169. package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +181 -0
  170. package/ds-canonical/skills/code-quality-audit/SKILL.md +63 -0
  171. package/ds-canonical/skills/codex-collab/SKILL.md +249 -0
  172. package/ds-canonical/skills/codex-collab/references/brief-template.md +48 -0
  173. package/ds-canonical/skills/codex-collab/references/transport.md +58 -0
  174. package/ds-canonical/skills/codify-corrections/SKILL.md +184 -0
  175. package/ds-canonical/skills/codify-principle/SKILL.md +151 -0
  176. package/ds-canonical/skills/component-quality-gate/SKILL.md +102 -0
  177. package/ds-canonical/skills/component-quality-gate/references/checklist.md +79 -0
  178. package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +247 -0
  179. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +123 -0
  180. package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +165 -0
  181. package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +91 -0
  182. package/ds-canonical/skills/delivery-handoff/SKILL.md +229 -0
  183. package/ds-canonical/skills/delivery-handoff/references/flow-diagram.md +180 -0
  184. package/ds-canonical/skills/delivery-handoff/references/handoff-template.md +177 -0
  185. package/ds-canonical/skills/delivery-handoff/references/inventory-checklist.md +196 -0
  186. package/ds-canonical/skills/design-system-audit/SKILL.md +343 -0
  187. package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +1260 -0
  188. package/ds-canonical/skills/design-system-audit/references/checkpoints.md +240 -0
  189. package/ds-canonical/skills/design-system-audit/references/historical-bugs.md +240 -0
  190. package/ds-canonical/skills/design-system-audit/references/principle-audit-protocol.md +364 -0
  191. package/ds-canonical/skills/design-system-audit/references/rule-placement.md +175 -0
  192. package/ds-canonical/skills/design-system-audit/references/spec-template.md +66 -0
  193. package/ds-canonical/skills/ensure-canonical/SKILL.md +196 -0
  194. package/ds-canonical/skills/governance-health/SKILL.md +146 -0
  195. package/ds-canonical/skills/knowledge-prune/SKILL.md +303 -0
  196. package/ds-canonical/skills/new-component/SKILL.md +170 -0
  197. package/ds-canonical/skills/new-component/references/new-component-checklist.md +85 -0
  198. package/ds-canonical/skills/performance-audit/SKILL.md +107 -0
  199. package/ds-canonical/skills/product-ui-audit/SKILL.md +230 -0
  200. package/ds-canonical/skills/product-ui-audit/references/audit-checks.md +246 -0
  201. package/ds-canonical/skills/product-ui-audit/references/common-misuses.md +329 -0
  202. package/ds-canonical/skills/product-ui-audit/references/report-template.md +159 -0
  203. package/ds-canonical/skills/propose-options/SKILL.md +177 -0
  204. package/ds-canonical/skills/prototype/SKILL.md +244 -0
  205. package/ds-canonical/skills/prototype/references/audit-checks.md +37 -0
  206. package/ds-canonical/skills/prototype/references/benchmark-sources.md +94 -0
  207. package/ds-canonical/skills/prototype/references/checkpoints.md +191 -0
  208. package/ds-canonical/skills/prototype/references/evaluation-matrix.md +141 -0
  209. package/ds-canonical/skills/prototype/references/ooux-template.md +198 -0
  210. package/ds-canonical/skills/prototype/references/proposal-template.md +229 -0
  211. package/ds-canonical/skills/scan-similar-bugs/SKILL.md +198 -0
  212. package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +159 -0
  213. package/ds-canonical/skills/story-writing/SKILL.md +122 -0
  214. package/ds-canonical/skills/story-writing/references/anatomy-standard.md +217 -0
  215. package/ds-canonical/skills/story-writing/references/category-templates.md +174 -0
  216. package/ds-canonical/skills/story-writing/references/example-selection.md +70 -0
  217. package/ds-canonical/skills/story-writing/references/self-check.md +20 -0
  218. package/ds-canonical/skills/ux-audit/SKILL.md +130 -0
  219. package/ds-canonical/skills/visual-audit/SKILL.md +245 -0
  220. package/ds-canonical/skills/visual-audit/output/.gitkeep +0 -0
  221. package/ds-canonical/skills/visual-audit/references/audit-architecture.md +100 -0
  222. package/ds-canonical/skills/visual-audit/references/visual-checklist.md +297 -0
  223. package/ds-canonical/skills/visual-audit/references/world-class-benchmarks.md +198 -0
  224. package/package.json +9 -5
  225. package/src/components/Accordion/accordion.spec.md +114 -0
  226. package/src/components/Alert/alert.spec.md +197 -0
  227. package/src/components/AppShell/app-shell.spec.md +331 -0
  228. package/src/components/AspectRatio/aspect-ratio.spec.md +134 -0
  229. package/src/components/Avatar/avatar.spec.md +329 -0
  230. package/src/components/Badge/badge.spec.md +380 -0
  231. package/src/components/Breadcrumb/breadcrumb.spec.md +257 -0
  232. package/src/components/BulkActionBar/bulk-action-bar.spec.md +210 -0
  233. package/src/components/Button/button.spec.md +460 -0
  234. package/src/components/Calendar/calendar.spec.md +242 -0
  235. package/src/components/Carousel/carousel.spec.md +253 -0
  236. package/src/components/Chart/chart.spec.md +155 -0
  237. package/src/components/Checkbox/checkbox.spec.md +344 -0
  238. package/src/components/Chip/chip.spec.md +237 -0
  239. package/src/components/CircularProgress/circular-progress.spec.md +268 -0
  240. package/src/components/Coachmark/coachmark.spec.md +230 -0
  241. package/src/components/Combobox/combobox.spec.md +180 -0
  242. package/src/components/Command/command.spec.md +171 -0
  243. package/src/components/DataTable/data-table.spec.md +525 -0
  244. package/src/components/DateGrid/date-grid.spec.md +215 -0
  245. package/src/components/DatePicker/date-picker.spec.md +334 -0
  246. package/src/components/DescriptionList/description-list.spec.md +214 -0
  247. package/src/components/Dialog/dialog.spec.md +202 -0
  248. package/src/components/DropdownMenu/dropdown-menu.spec.md +250 -0
  249. package/src/components/Empty/empty.spec.md +214 -0
  250. package/src/components/Field/field-controls.spec.md +338 -0
  251. package/src/components/Field/field.spec.md +438 -0
  252. package/src/components/Field/form-validation.spec.md +152 -0
  253. package/src/components/FieldControlGroup/field-control-group.spec.md +176 -0
  254. package/src/components/FileItem/file-item.spec.md +467 -0
  255. package/src/components/FileUpload/file-upload.spec.md +123 -0
  256. package/src/components/FileViewer/file-viewer.spec.md +373 -0
  257. package/src/components/HoverCard/hover-card.spec.md +157 -0
  258. package/src/components/Input/input.spec.md +193 -0
  259. package/src/components/LinkInput/link-input.spec.md +130 -0
  260. package/src/components/Menu/menu-item.spec.md +290 -0
  261. package/src/components/NameCard/name-card.spec.md +171 -0
  262. package/src/components/Notice/notice.spec.md +149 -0
  263. package/src/components/NumberInput/number-input.spec.md +126 -0
  264. package/src/components/OverflowIndicator/overflow-indicator.spec.md +120 -0
  265. package/src/components/PeoplePicker/people-picker.spec.md +263 -0
  266. package/src/components/Popover/popover.spec.md +198 -0
  267. package/src/components/ProgressBar/progress-bar.spec.md +232 -0
  268. package/src/components/RadioGroup/radio-group.spec.md +141 -0
  269. package/src/components/Rating/rating.spec.md +208 -0
  270. package/src/components/ScrollArea/scroll-area.spec.md +145 -0
  271. package/src/components/SegmentedControl/segmented-control.spec.md +295 -0
  272. package/src/components/Select/select.spec.md +299 -0
  273. package/src/components/SelectMenu/select-menu.spec.md +220 -0
  274. package/src/components/SelectionControl/selection-item.spec.md +128 -0
  275. package/src/components/Separator/separator.spec.md +109 -0
  276. package/src/components/Sheet/sheet.spec.md +148 -0
  277. package/src/components/Sidebar/sidebar.spec.md +713 -0
  278. package/src/components/Skeleton/skeleton.spec.md +104 -0
  279. package/src/components/Slider/slider.spec.md +353 -0
  280. package/src/components/Steps/steps.spec.md +465 -0
  281. package/src/components/Switch/switch.spec.md +215 -0
  282. package/src/components/Tabs/tabs.spec.md +314 -0
  283. package/src/components/Tag/tag.spec.md +282 -0
  284. package/src/components/Textarea/textarea.spec.md +151 -0
  285. package/src/components/TimePicker/time-picker.spec.md +279 -0
  286. package/src/components/Toast/toast.spec.md +177 -0
  287. package/src/components/Tooltip/tooltip.spec.md +139 -0
  288. package/src/components/TreeView/tree-view.spec.md +374 -0
  289. package/src/patterns/action-bar/action-bar.spec.md +458 -0
  290. package/src/patterns/element-anatomy/element-anatomy.spec.md +215 -0
  291. package/src/patterns/element-anatomy/inline-action.spec.md +315 -0
  292. package/src/patterns/element-anatomy/item-anatomy.spec.md +1042 -0
  293. package/src/patterns/header-canonical/header-canonical.spec.md +285 -0
  294. package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +191 -0
  295. package/src/patterns/overlay-surface/overlay-surface.spec.md +428 -0
  296. package/src/patterns/resize-handle/resize-handle.spec.md +109 -0
  297. package/src/tokens/color/color.spec.md +804 -0
  298. package/src/tokens/density/density.spec.md +127 -0
  299. package/src/tokens/elevation/elevation.spec.md +81 -0
  300. package/src/tokens/layoutSpace/layoutSpace.spec.md +314 -0
  301. package/src/tokens/motion/motion.spec.md +97 -0
  302. package/src/tokens/opacity/opacity.spec.md +78 -0
  303. package/src/tokens/orphan-tokens.spec.md +117 -0
  304. package/src/tokens/radius/radius.spec.md +123 -0
  305. package/src/tokens/typography/typography.spec.md +202 -0
  306. package/src/tokens/uiSize/uiSize.spec.md +438 -0
  307. package/src/styles/preset.css +0 -31
@@ -0,0 +1,105 @@
1
+ #!/bin/bash
2
+ # check_substantive_edit_approval_preflight.sh — Pre-action gate for substantive design edits.
3
+ #
4
+ # Purpose: PRE-flight 偵測 packages/design-system/src/**.{tsx,ts,css} edit + last 5 user msgs 無
5
+ # approval keyword → SOFT inject context warning。
6
+ #
7
+ # 對比 stop_self_audit.sh post-action BLOCKER:本 hook 是 PRE-action soft warn,
8
+ # 讓 AI 看到 context 後 self-decide(propose-only OR cite approval verbatim),
9
+ # 避免「edit → stop hook BLOCKER → revert」waste cycle(user 抓 2026-05-12 anti-pattern)。
10
+ #
11
+ # 對齊 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)
14
+ # - AI inline self-statement = discipline(M31 Layer A/C marker + 本 hook context)
15
+ #
16
+ # Why pre-action soft instead of hard BLOCK:false-positive 風險(legit bug fix 可能撞)+
17
+ # inject info 比 reject 更尊重 AI judgment + 配合 existing stop hook backstop。
18
+ #
19
+ # 對齊:CLAUDE.md `# 稽核 canonical` Audit-vs-execute 分權 + M31 Layer A/C + M32(f) ship gate。
20
+
21
+ source "$(dirname "$0")/_log-fire.sh" 2>/dev/null && log_hook_fire
22
+
23
+ set -uo pipefail
24
+ INPUT=$(cat 2>/dev/null || echo "{}")
25
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // ""' 2>/dev/null)
26
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""' 2>/dev/null)
27
+ TRANSCRIPT_PATH=$(echo "$INPUT" | jq -r '.transcript_path // ""' 2>/dev/null)
28
+ EVENT=$(echo "$INPUT" | jq -r '.hook_event_name // ""' 2>/dev/null)
29
+
30
+ # Only PreToolUse for Edit|Write|MultiEdit
31
+ [ "$EVENT" != "PreToolUse" ] && exit 0
32
+ case "$TOOL" in Edit|Write|MultiEdit) ;; *) exit 0 ;; esac
33
+
34
+ # Substantive scope:packages/design-system/src/**.{tsx,ts,css} only
35
+ case "$FILE_PATH" in
36
+ */packages/design-system/src/*.tsx|*/packages/design-system/src/*.ts|*/packages/design-system/src/*.css) ;;
37
+ *) exit 0 ;;
38
+ esac
39
+
40
+ # Allowlist:storybook config / scripts / tests 等非 production code
41
+ case "$FILE_PATH" in
42
+ *.stories.tsx|*.test.ts|*.spec.ts) exit 0 ;;
43
+ esac
44
+
45
+ [ -z "$TRANSCRIPT_PATH" ] || [ ! -f "$TRANSCRIPT_PATH" ] && exit 0
46
+
47
+ # Scan last 5 真 user msgs(transcript role=user 且 content 非 tool_result)
48
+ RECENT_USER_MSGS=$(tail -200 "$TRANSCRIPT_PATH" 2>/dev/null | \
49
+ jq -r 'select(.message.role=="user") |
50
+ .message.content // empty |
51
+ if type=="string" then .
52
+ else (.[]? | select(.type != "tool_result") | .text // empty)
53
+ end' 2>/dev/null | tail -5)
54
+
55
+ # Approval keywords(對齊 stop_self_audit.sh:172)+ 2026-05-15 升 numbered directive
56
+ # (`#1 A` / `#1 ship` 等)+ 「照建議」/「照共識」/「照我的」等 reference style approval
57
+ # 2026-05-21 M34 fix(per user verbatim「都給我做到好」approval blocked by 妳/決策N coverage gap):
58
+ # (a) 加「妳」變體(`照妳`= `照你` 文書通用 variant)
59
+ # (b) 加「決策[一二三四五六七八九十1-9]」numbered directive(eg.「決策一改…」「決策3做」)
60
+ # (c) 加「做到好」/「都做」/「全做」auto-approve 變體
61
+ APPROVAL_RE='(同意|採用|採納|拍板|拍\s*[A-Z0-9]|可以|改成|改為|執行|上吧|push|implement|go ahead|approved|OK|好|沒問題|做一做|就做|做吧|做完|全部做完|做到完|做到好|都做|全做|馬不停蹄|建議做|ship|合 main|^#[0-9]+|照你|照妳|照建議|照共識|照我的|按照|決策[一二三四五六七八九十1-9]|[A-Z][0-9]+\s*(做|改|修)|先\s*[A-Z][0-9]+)'
62
+ HAS_APPROVAL=$(echo "$RECENT_USER_MSGS" | grep -cE "$APPROVAL_RE" 2>/dev/null)
63
+ HAS_APPROVAL=${HAS_APPROVAL:-0}
64
+
65
+ # Substantive-discuss keywords(若 user 在 discuss mode → 提示 propose-only)
66
+ DISCUSS_RE='(propose|提案|建議|討論|比稿|看法|思考|評估|要不要|該不該|是否|怎麼想)'
67
+ HAS_DISCUSS=$(echo "$RECENT_USER_MSGS" | grep -cE "$DISCUSS_RE" 2>/dev/null)
68
+ HAS_DISCUSS=${HAS_DISCUSS:-0}
69
+
70
+ # Approval present → silent pass
71
+ if [ "$HAS_APPROVAL" -gt 0 ]; then
72
+ exit 0
73
+ fi
74
+
75
+ # 2026-05-15 upgrade per user verbatim:「上述的問題請你務必確實確保永遠他媽不要再給我犯了」
76
+ # (memory/feedback_ship_then_revert_anti_pattern.md SSOT)
77
+ # Soft warn → P0 BLOCKER on packages/design-system/src/**/*.tsx production substantive without approval。
78
+ # Override env var:CLAUDE_BYPASS_DESIGN_APPROVAL=1(audit-logged below)
79
+ REL_PATH=${FILE_PATH#*/my-project/}
80
+
81
+ if [ "${CLAUDE_BYPASS_DESIGN_APPROVAL:-0}" = "1" ]; then
82
+ # Audit log override
83
+ mkdir -p "$(dirname "$0")/../logs" 2>/dev/null
84
+ printf '{"ts":"%s","event":"design-approval-bypass","file":"%s","tool":"%s"}\n' \
85
+ "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$REL_PATH" "$TOOL" \
86
+ >> "$(dirname "$0")/../logs/approval-bypass.jsonl" 2>/dev/null || true
87
+ exit 0
88
+ fi
89
+
90
+ # BLOCKER:stderr + exit 2 = halt PreToolUse(Edit/Write/MultiEdit)
91
+ echo "🚨 BLOCKER: Pre-action gate(check_substantive_edit_approval_preflight,2026-05-15 P0 升級)" >&2
92
+ echo " - 目標: ${REL_PATH}" >&2
93
+ echo " - 範圍: packages/design-system/src production code(substantive SSOT change)" >&2
94
+ echo " - 近 5 條 user msg approval keyword: ${HAS_APPROVAL} 次 / discuss keyword: ${HAS_DISCUSS} 次" >&2
95
+ echo "" >&2
96
+ echo "→ SSOT-affecting UI/UX edit without verbatim approval = ship-then-revert anti-pattern" >&2
97
+ echo " (memory/feedback_ship_then_revert_anti_pattern.md SSOT)" >&2
98
+ echo "" >&2
99
+ echo "修法 — 2 選 1:" >&2
100
+ echo " (a) Convert to propose-only:列 option + 4-Q 自檢 + 等 user 拍板,撤回 edit" >&2
101
+ echo " (b) Cite user approval verbatim quote 在 commit message + reply,然後設" >&2
102
+ echo " \`CLAUDE_BYPASS_DESIGN_APPROVAL=1\` env var 跑 edit(audit-logged)" >&2
103
+ echo "" >&2
104
+ echo "「user echo hypothesis」≠「user approve」— M4 sub-check enforces。" >&2
105
+ exit 2
@@ -0,0 +1,66 @@
1
+ #!/bin/bash
2
+ set -uo pipefail
3
+ # Header canonical W3 Token alignment enforcement(per header-canonical.spec.md W3):
4
+ # --tab-height-lg(uiSize.css)與 --chrome-header-height(globals.css)必像素相等。
5
+ # 兩 token scope 不同(uiSize 是 component-size reset / chrome-header-height 是 app-density)
6
+ # 不該 CSS alias(綁死兩個不同 scope)— 改用 assert: parse 兩檔 md/lg 值對等。
7
+ #
8
+ # PreToolUse(Edit / Write)hook —— 編輯 `packages/design-system/src/tokens/uiSize/uiSize.css` 或
9
+ # `src/globals.css` 時 assert 兩值仍相等。動一方未同步 = BLOCKER。
10
+ #
11
+ # 對齊 M31 codex 比稿 Step 5「保留 duplicated literals + audit hook assert equality」decision。
12
+
13
+ source "$(dirname "$0")/_log-fire.sh" 2>/dev/null && log_hook_fire
14
+
15
+ set -euo pipefail
16
+
17
+ INPUT=$(cat)
18
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // ""')
19
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
20
+
21
+ case "$TOOL" in
22
+ Edit|Write|MultiEdit) ;;
23
+ *) exit 0 ;;
24
+ esac
25
+
26
+ case "$FILE_PATH" in
27
+ */packages/design-system/src/tokens/uiSize/uiSize.css|*/src/globals.css) ;;
28
+ *) exit 0 ;;
29
+ esac
30
+
31
+ PROJECT_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
32
+ UISIZE_CSS="$PROJECT_ROOT/packages/design-system/src/tokens/uiSize/uiSize.css"
33
+ GLOBALS_CSS="$PROJECT_ROOT/src/globals.css"
34
+
35
+ # Extract value of --tab-height-lg in md context(default :root block)
36
+ TAB_LG_MD=$(grep -oE '\--tab-height-lg:[[:space:]]*[0-9.]+rem' "$UISIZE_CSS" | head -1 | grep -oE '[0-9.]+')
37
+ # Extract --tab-height-lg in lg density override(2nd occurrence)
38
+ TAB_LG_LG=$(grep -oE '\--tab-height-lg:[[:space:]]*[0-9.]+rem' "$UISIZE_CSS" | sed -n '2p' | grep -oE '[0-9.]+')
39
+
40
+ # Extract --chrome-header-height md(1st occurrence)
41
+ CH_MD=$(grep -oE '\--chrome-header-height:[[:space:]]*[0-9.]+rem' "$GLOBALS_CSS" | head -1 | grep -oE '[0-9.]+')
42
+ # Extract --chrome-header-height lg(2nd occurrence in lg override)
43
+ CH_LG=$(grep -oE '\--chrome-header-height:[[:space:]]*[0-9.]+rem' "$GLOBALS_CSS" | sed -n '2p' | grep -oE '[0-9.]+')
44
+
45
+ ERRORS=()
46
+
47
+ if [ "$TAB_LG_MD" != "$CH_MD" ]; then
48
+ ERRORS+=("md: --tab-height-lg=$TAB_LG_MD rem ≠ --chrome-header-height=$CH_MD rem")
49
+ fi
50
+
51
+ if [ "$TAB_LG_LG" != "$CH_LG" ]; then
52
+ ERRORS+=("lg: --tab-height-lg=$TAB_LG_LG rem ≠ --chrome-header-height=$CH_LG rem")
53
+ fi
54
+
55
+ if [ ${#ERRORS[@]} -gt 0 ]; then
56
+ printf '🚨 TAB_LG vs CHROME_HEADER_HEIGHT EQUAL BLOCKER(header-canonical.spec.md W3):\n' >&2
57
+ for E in "${ERRORS[@]}"; do
58
+ printf ' • %s\n' "$E" >&2
59
+ done
60
+ printf '\n 動一方必同步另一方(兩 token 像素相等是「lg tabs 取代 chrome header」SSOT linkage 鐵證)\n' >&2
61
+ printf ' SSOT: packages/design-system/src/patterns/header-canonical/header-canonical.spec.md W3\n' >&2
62
+ printf ' 修方向: 改 uiSize.css 的 --tab-height-lg OR globals.css 的 --chrome-header-height 讓兩邊相等\n' >&2
63
+ exit 2
64
+ fi
65
+
66
+ exit 0
@@ -0,0 +1,104 @@
1
+ #!/bin/bash
2
+ set -uo pipefail
3
+ # M30 機械強制:wrapper-vs-primitive schema unify invariant。
4
+ #
5
+ # PreToolUse(Edit / Write)hook —— 編輯 `packages/design-system/src/components/**/*.tsx` 時掃:
6
+ # (a) 檢查同 file 是否 declare `export interface XxxOption` 同名於其他 file
7
+ # (b) 若同名且未 `extends XxxOption from primitive`/`extends YyyOption` → BLOCKER
8
+ # (c) 若 wrapper 用 `SelectMenuOption`(import from SelectMenu)但內部 `menuOptions` mapping
9
+ # 未 forward `avatar` / `description` / `disabled`(只 forward value+label)→ WARN
10
+ #
11
+ # Bug 史(2026-05-10):
12
+ # `Select.SelectOption` Issue 4 補 avatar / description / disabled,但 `Combobox.SelectOption`
13
+ # 是同名 weak schema `{ value, label }`。TypeScript 不抓(不同 file 同名各 export);consumer
14
+ # import 哪個版本看 import path 決定 → drift。PeoplePicker multi-mode dropdown 漏 avatar。
15
+ #
16
+ # Allow escape:
17
+ # 檔頭 `// @wrapper-schema-allow: <reason>` 整檔豁免(legacy migration 過渡期)。
18
+
19
+ source "$(dirname "$0")/_log-fire.sh" 2>/dev/null && log_hook_fire
20
+
21
+ set -euo pipefail
22
+
23
+ INPUT=$(cat)
24
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // ""')
25
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
26
+
27
+ case "$TOOL" in
28
+ Edit|Write|MultiEdit) ;;
29
+ *) exit 0 ;;
30
+ esac
31
+
32
+ case "$FILE_PATH" in
33
+ */packages/design-system/src/components/**/*.tsx) ;;
34
+ *) exit 0 ;;
35
+ esac
36
+
37
+ NEW_CONTENT=$(echo "$INPUT" | jq -r '
38
+ if .tool_input.new_string then .tool_input.new_string
39
+ elif .tool_input.content then .tool_input.content
40
+ else "" end
41
+ ')
42
+
43
+ # Allow escape
44
+ if echo "$NEW_CONTENT" | grep -qE '@wrapper-schema-allow:'; then
45
+ exit 0
46
+ fi
47
+
48
+ # Check 1: new file declares `export interface XxxOption {` ?
49
+ DECLARES=$(echo "$NEW_CONTENT" | grep -oE 'export interface [A-Z][a-zA-Z]*Option\b[^{]*\{' || true)
50
+ if [ -z "$DECLARES" ]; then
51
+ exit 0
52
+ fi
53
+
54
+ # For each declared OptionLike interface, check if same name declared elsewhere
55
+ DS_COMPONENTS_DIR="$(dirname "$0")/../../packages/design-system/src/components"
56
+
57
+ # normalize FILE_PATH relative to project for self-skip
58
+ SELF_BASENAME="$(basename "$FILE_PATH")"
59
+
60
+ WARNINGS=()
61
+ BLOCKERS=()
62
+
63
+ while IFS= read -r decl; do
64
+ IFACE_NAME=$(echo "$decl" | grep -oE '[A-Z][a-zA-Z]*Option' | head -1)
65
+ [ -z "$IFACE_NAME" ] && continue
66
+ # Skip if extends another OptionLike interface(M30 compliant)
67
+ if echo "$NEW_CONTENT" | grep -qE "interface $IFACE_NAME\b.*extends [A-Z][a-zA-Z]*Option"; then
68
+ continue
69
+ fi
70
+ # Find other files declaring same name(skip self by basename — imperfect but Edit context is single-file)
71
+ OTHER_DECLS=$(grep -rlE "export interface $IFACE_NAME\b" "$DS_COMPONENTS_DIR" 2>/dev/null | grep -v "/$SELF_BASENAME$" || true)
72
+ if [ -n "$OTHER_DECLS" ]; then
73
+ BLOCKERS+=("M30 schema drift: \`$IFACE_NAME\` declared in this file (no extends) + also in: $(echo "$OTHER_DECLS" | head -3 | xargs -n1 basename | tr '\n' ',' | sed 's/,$//')")
74
+ fi
75
+ done <<< "$DECLARES"
76
+
77
+ # Check 2: imports SelectMenuOption but menuOptions mapping drops fields(WARN)
78
+ if echo "$NEW_CONTENT" | grep -qE 'import.*SelectMenuOption.*from.*SelectMenu'; then
79
+ # Look for `menuOptions: SelectMenuOption[]` mapping that misses fields
80
+ MAP_BLOCK=$(echo "$NEW_CONTENT" | grep -A5 -E 'menuOptions.*SelectMenuOption\[\]' | head -30)
81
+ if [ -n "$MAP_BLOCK" ]; then
82
+ # Heuristic: should forward at least `avatar` OR `description` OR `disabled` field
83
+ if ! echo "$MAP_BLOCK" | grep -qE '(avatar|description|disabled)'; then
84
+ WARNINGS+=("M30 schema partial-forward: \`menuOptions\` mapping seems to drop avatar/description/disabled. Forward 全 SelectMenuOption surface or annotate \`// @wrapper-schema-allow: <reason>\`.")
85
+ fi
86
+ fi
87
+ fi
88
+
89
+ # Output
90
+ if [ ${#BLOCKERS[@]} -gt 0 ]; then
91
+ echo "🚨 M30 wrapper-vs-primitive schema drift BLOCKER:" >&2
92
+ for b in "${BLOCKERS[@]}"; do echo " • $b" >&2; done
93
+ echo "" >&2
94
+ echo "Fix: declare \`interface $IFACE_NAME extends <PrimitiveSSoT>\` (e.g. \`extends SelectMenuOption\`)" >&2
95
+ echo " 詳 .claude/rules/meta-patterns.md M30 + Polaris ChoiceList / Material Autocomplete idiom" >&2
96
+ exit 2
97
+ fi
98
+
99
+ if [ ${#WARNINGS[@]} -gt 0 ]; then
100
+ echo "⚠️ M30 wrapper schema forward warning:" >&2
101
+ for w in "${WARNINGS[@]}"; do echo " • $w" >&2; done
102
+ fi
103
+
104
+ exit 0
@@ -0,0 +1,44 @@
1
+ #!/bin/bash
2
+ # PreToolUse Write hook: gate new files in classification dirs.
3
+ # 確保新檔放對 home(8-home flowchart canonical)。
4
+ #
5
+ # Silent on pass(2026-04-26 noise reduction):only fire if charter README
6
+ # missing OR file-name pattern violates dir convention(no charter inject).
7
+
8
+ source "$(dirname "$0")/_log-fire.sh" 2>/dev/null && log_hook_fire
9
+
10
+ set -uo pipefail
11
+
12
+ INPUT=$(cat 2>/dev/null || echo "{}")
13
+ TOOL=$(echo "$INPUT" | jq -r '.tool_name // ""' 2>/dev/null)
14
+ [ "$TOOL" = "Write" ] || exit 0
15
+
16
+ FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""' 2>/dev/null)
17
+ [ -n "$FILE_PATH" ] && [ ! -e "$FILE_PATH" ] || exit 0 # only NEW files
18
+
19
+ # Classification dirs requiring charter
20
+ DIRS=(.claude/hooks .claude/skills .claude/agents .claude/commands .claude/rules packages/design-system/src/components packages/design-system/src/patterns packages/design-system/src/tokens)
21
+
22
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
23
+ REL=$(echo "$FILE_PATH" | sed "s|$PROJECT_DIR/||")
24
+
25
+ for d in "${DIRS[@]}"; do
26
+ case "$REL" in
27
+ "$d"/*)
28
+ # Charter README itself escape(2026-05-17 chicken-and-egg fix):
29
+ # 不能擋 README 本身建立(否則 charter 永遠無法被 init)
30
+ case "$REL" in "$d"/README.md) exit 0 ;; esac
31
+ CHARTER="$PROJECT_DIR/$d/README.md"
32
+ if [ ! -f "$CHARTER" ]; then
33
+ # P0:charter missing → block via stderr + exit 2
34
+ echo "❌ Charter missing for $d/. Create $CHARTER first per # 治理 canonical 8-home flowchart." >&2
35
+ exit 2
36
+ fi
37
+ # Charter exists → silent pass(content placement is AI's responsibility,
38
+ # audit Dim 19 periodic verify;no per-write nag)
39
+ exit 0
40
+ ;;
41
+ esac
42
+ done
43
+
44
+ exit 0
@@ -0,0 +1,204 @@
1
+ #!/bin/bash
2
+ set -uo pipefail
3
+ # UserPromptSubmit hook: 把上 turn Stop hook 累積的 warnings inject 到 next turn additionalContext.
4
+ #
5
+ # 修補 known issue:Stop hook silent-log 沒 inject → AI 看不到 self-audit warnings → reactive 模式持續。
6
+ # 對齊 CLAUDE.md M14 / M20「auto-inject corrective prompt」原意。
7
+ #
8
+ # Reads:
9
+ # .claude/logs/self-audit-warnings.jsonl(stop_self_audit 寫入,behavioral check)
10
+ # .claude/logs/score-history.jsonl(stop_meta_self_audit 寫入,infra-score regression)
11
+ # State:
12
+ # .claude/logs/last-inject-ts.txt — 上次 inject 的 timestamp
13
+ #
14
+ # Logic:
15
+ # 1. 讀 LAST_TS,撈兩個 log 中 ts > LAST_TS 的條目
16
+ # 2. 有條目 → format 成 additionalContext,inject 給 AI
17
+ # 3. 不論有無條目,更新 LAST_TS = NOW(避免 stuck on 舊 warnings)
18
+
19
+ source "$(dirname "$0")/_log-fire.sh" 2>/dev/null && log_hook_fire
20
+
21
+ set -uo pipefail
22
+
23
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
24
+ cd "$PROJECT_DIR" || exit 0
25
+
26
+ LAST_TS_FILE=".claude/logs/last-inject-ts.txt"
27
+ NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ)
28
+ # Default LAST_TS: 30 分鐘前(防呆 — session cutoff,老 warning 自動 expire 避免 echo)
29
+ # 之前 24h 太寬,session 跨 hour 仍 inject 老 warning。30m sliding window 讓 fresh
30
+ # warning 進 inject,old warning 自動老化。Cross-platform GNU + BSD date。
31
+ DEFAULT_AGO=$(date -u -d '30 minutes ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || \
32
+ date -u -v-30M +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || \
33
+ date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || \
34
+ echo "1970-01-01T00:00:00Z")
35
+ LAST_TS="$DEFAULT_AGO"
36
+ if [ -f "$LAST_TS_FILE" ]; then
37
+ STORED=$(cat "$LAST_TS_FILE" 2>/dev/null)
38
+ # 用 stored OR 30m-ago 較新者(避免被重置成 1970)
39
+ [ -n "$STORED" ] && [[ "$STORED" > "$LAST_TS" ]] && LAST_TS="$STORED"
40
+ fi
41
+
42
+ # ── Acknowledge detection(防呆)──────────────────────────────────────────
43
+ # 若 last user msg(transcript)含 acknowledge keyword,stop inject 該類 warning
44
+ # 這 turn — 表示 user 已 see + 接受該 warning,持續 inject 是 spam。
45
+ ACK_DETECTED=0
46
+ TRANSCRIPT_PATH=$(echo "${1:-}" | jq -r '.transcript_path // ""' 2>/dev/null || echo "")
47
+ if [ -z "$TRANSCRIPT_PATH" ]; then
48
+ # UserPromptSubmit hook 從 stdin JSON 讀 transcript_path
49
+ TRANSCRIPT_PATH=$(cat 2>/dev/null | jq -r '.transcript_path // ""' 2>/dev/null || echo "")
50
+ fi
51
+ if [ -n "$TRANSCRIPT_PATH" ] && [ -f "$TRANSCRIPT_PATH" ]; then
52
+ LAST_USER=$(tail -50 "$TRANSCRIPT_PATH" 2>/dev/null | \
53
+ jq -r 'select(.message.role=="user") | .message.content // empty | if type=="string" then . else (.[]? | .text // empty) end' 2>/dev/null | tail -3)
54
+ ACK_RE='(收到|知道了|了解|acknowledged|ok 撤回|不用再 inject|停止 inject|skip warning|不要再警告)'
55
+ if echo "$LAST_USER" | grep -qiE "$ACK_RE"; then
56
+ ACK_DETECTED=1
57
+ fi
58
+ fi
59
+
60
+ # ── Aggregate warnings 去重 + 計數(extract_warnings_dedup helper)─────────
61
+ # Reads stdin JSONL, filters by ts > LAST_TS, extracts .warnings, dedups bullet lines, prepends count.
62
+ extract_warnings_dedup() {
63
+ awk -v cutoff="$LAST_TS" '
64
+ BEGIN { in_str=0; for(k in seen) delete seen[k]; for(k in count) delete count[k]; n=0 }
65
+ {
66
+ # crude jsonl ts extract
67
+ if (match($0, /"ts":"[^"]+"/)) {
68
+ ts=substr($0, RSTART+6, RLENGTH-7)
69
+ if (ts <= cutoff) next
70
+ }
71
+ # extract warnings field(may contain \n escape)
72
+ if (match($0, /"warnings":"[^"]*"/)) {
73
+ w=substr($0, RSTART+12, RLENGTH-13)
74
+ # split by \\n
75
+ nlines=split(w, lines, "\\\\n")
76
+ for (i=1; i<=nlines; i++) {
77
+ line=lines[i]
78
+ gsub(/^[[:space:]]+/, "", line)
79
+ # strip leading "• " from source(避免 double bullet)
80
+ gsub(/^•[[:space:]]*/, "", line)
81
+ if (line == "") continue
82
+ if (!(line in seen)) {
83
+ seen[line] = 1
84
+ count[line] = 1
85
+ order[++n] = line
86
+ } else {
87
+ count[line]++
88
+ }
89
+ }
90
+ }
91
+ }
92
+ END {
93
+ for (i=1; i<=n; i++) {
94
+ l = order[i]
95
+ c = count[l]
96
+ if (c > 1) printf " • [×%d] %s\n", c, l
97
+ else printf " • %s\n", l
98
+ }
99
+ }
100
+ '
101
+ }
102
+
103
+ WARNINGS_BEHAVIORAL=""
104
+ WARNINGS_SCORE=""
105
+ LATEST_SCORE=""
106
+
107
+ # ── Read behavioral warnings since LAST_TS ─────────────────────────────────
108
+ if [ -f .claude/logs/self-audit-warnings.jsonl ]; then
109
+ WARNINGS_BEHAVIORAL=$(extract_warnings_dedup < .claude/logs/self-audit-warnings.jsonl)
110
+ fi
111
+
112
+ # ── Read infra-score warnings since LAST_TS ─────────────────────────────────
113
+ if [ -f .claude/logs/score-history.jsonl ]; then
114
+ WARNINGS_SCORE=$(extract_warnings_dedup < .claude/logs/score-history.jsonl)
115
+ # Latest score(取 file 最後一行 ts > cutoff 的)
116
+ LATEST_SCORE=$(awk -v cutoff="$LAST_TS" '
117
+ {
118
+ if (match($0, /"ts":"[^"]+"/)) {
119
+ ts=substr($0, RSTART+6, RLENGTH-7)
120
+ if (ts <= cutoff) next
121
+ }
122
+ if (match($0, /"score":[0-9]+/)) {
123
+ s=substr($0, RSTART+8, RLENGTH-8)
124
+ last_s=s
125
+ }
126
+ }
127
+ END { print last_s }
128
+ ' .claude/logs/score-history.jsonl)
129
+ fi
130
+
131
+ # Update LAST_TS regardless(若 inject 失敗,下 turn 會重看到 — 但 jq 出錯就靜默)
132
+ mkdir -p .claude/logs 2>/dev/null
133
+ echo "$NOW" > "$LAST_TS_FILE"
134
+
135
+ # Silent exit if nothing accumulated
136
+ if [ -z "$WARNINGS_BEHAVIORAL" ] && [ -z "$WARNINGS_SCORE" ]; then
137
+ exit 0
138
+ fi
139
+
140
+ # 防呆 layer 2:user 已 acknowledge → silent skip inject 本 turn
141
+ if [ "$ACK_DETECTED" = "1" ]; then
142
+ exit 0
143
+ fi
144
+
145
+ # ── Format additionalContext ────────────────────────────────────────────────
146
+ CTX_PARTS=""
147
+ if [ -n "$WARNINGS_BEHAVIORAL" ]; then
148
+ CTX_PARTS="${CTX_PARTS}## Behavioral self-audit(stop_self_audit):
149
+ ${WARNINGS_BEHAVIORAL}
150
+
151
+ "
152
+ fi
153
+ if [ -n "$WARNINGS_SCORE" ]; then
154
+ SCORE_LABEL=""
155
+ [ -n "$LATEST_SCORE" ] && SCORE_LABEL=" current=${LATEST_SCORE}/100"
156
+ CTX_PARTS="${CTX_PARTS}## Infra-score audit(stop_meta_self_audit,${SCORE_LABEL}):
157
+ ${WARNINGS_SCORE}
158
+
159
+ "
160
+ fi
161
+
162
+ # ── 偵測 directive 觸發類型,加 explicit 指示 ─────────────────────────────
163
+ DIRECTIVE=""
164
+ if echo "${WARNINGS_BEHAVIORAL}${WARNINGS_SCORE}" | grep -q "trigger-phrase 累計"; then
165
+ DIRECTIVE="${DIRECTIVE}
166
+ 🚨 **DIRECTIVE — M19 trigger phrase auto-pipeline 啟動**:
167
+ 當 user 反覆問「確保 / 一定 / 不會 / 是否能 / 永遠 / 是否符合原則」之類問題時(本 case 已累計多次),你**必須立刻 invoke \`/ensure-canonical\` skill** 跑 5-layer pipeline,不可只給 verbal 答覆 / 不可只 quote score / 不可只「下次承諾」。
168
+ 不確定主題 → 就用最近 user 提到的關鍵字當 ensure-canonical args。"
169
+ fi
170
+ if echo "${WARNINGS_BEHAVIORAL}${WARNINGS_SCORE}" | grep -q "Topic.*repeated"; then
171
+ DIRECTIVE="${DIRECTIVE}
172
+ 🚨 **DIRECTIVE — M10 proactive exhaustive scan**:
173
+ Topic 重複表示 prior turns 落地不徹底。**必須 grep DS-wide 同 pattern 批量修**(不只 user 點到的那個 case),否則持續 reactive。"
174
+ fi
175
+ if echo "${WARNINGS_BEHAVIORAL}${WARNINGS_SCORE}" | grep -q "Claim-verify gap"; then
176
+ DIRECTIVE="${DIRECTIVE}
177
+ 🚨 **DIRECTIVE — Claim-verify gap**:
178
+ 你說 done / verified / 通過 但本 turn 沒跑 \`tsc -b\` / hook test / score script。**現在立刻跑驗證**或在回答中明撤回 claim。"
179
+ fi
180
+
181
+ ADDITIONAL_CONTEXT=$(printf '⚠️ 來自上 turn(s) 的 governance self-audit warnings — M14/M20 auto-inject:
182
+
183
+ %s%s
184
+
185
+ → 這些是 stop hook 偵測到、應該主動處理的事項。在你回答 user prompt 前先處理(grep / fix / invoke skill / 跑驗證),不要等 user 提醒。' "$CTX_PARTS" "$DIRECTIVE")
186
+
187
+ # Safety cap:max 3KB(避免 inject context 過大)
188
+ MAX_LEN=3000
189
+ CTX_LEN=${#ADDITIONAL_CONTEXT}
190
+ if [ "$CTX_LEN" -gt "$MAX_LEN" ]; then
191
+ ADDITIONAL_CONTEXT="${ADDITIONAL_CONTEXT:0:$MAX_LEN}
192
+
193
+ [truncated — 原 ${CTX_LEN}B,顯示前 ${MAX_LEN}B。如要看全文 grep .claude/logs/self-audit-warnings.jsonl + score-history.jsonl]"
194
+ fi
195
+
196
+ # Output JSON for Claude Code to inject
197
+ jq -n --arg ctx "$ADDITIONAL_CONTEXT" '{
198
+ hookSpecificOutput: {
199
+ hookEventName: "UserPromptSubmit",
200
+ additionalContext: $ctx
201
+ }
202
+ }'
203
+
204
+ exit 0
@@ -0,0 +1,33 @@
1
+ #!/bin/bash
2
+ # SSOT approval keyword regex(M17 + M34,2026-05-18 codify per audit GAP 6)
3
+ #
4
+ # Used by:
5
+ # - check_substantive_edit_approval_preflight.sh(pre-flight Edit/Write production)
6
+ # - stop_self_audit.sh Mechanism 4(post-flight codex-design ship verify)
7
+ # - check_solo_workflow.sh R3(push main trigger detect)
8
+ #
9
+ # Background:GAP 6 audit(2026-05-18) found approval regex duplicated 3 places + drift:
10
+ # preflight 已加 `#[N] A` numbered directive + 照建議 / 照共識 reference-style
11
+ # 但 stop_self_audit / solo_workflow 沒 sync。
12
+ # 抽出 single SSOT,source from all consumers,確保未來 update 自動 propagate。
13
+
14
+ # 完整 approval keyword regex(extended POSIX)
15
+ #
16
+ # 涵蓋:
17
+ # (1) 明確同意:同意 / 採用 / 採納 / 拍板 / 可以 / OK / 好 / approved / approve / 沒問題
18
+ # (2) 動作指令:改成 / 改為 / 執行 / 上吧 / push / implement / go ahead / ship / 上 main
19
+ # (3) 大批做:做一做 / 就做 / 做吧 / 做完 / 全部做完 / 做到完 / 馬不停蹄 / 全部照建議做
20
+ # (4) 建議認可:建議做 / 照你建議 / 照建議 / 照共識 / 照我的 / 按照(代詞 reference)
21
+ # (5) Numbered directive:#1 A / #2 B / 1. B / 2. A 類 user 點選 option
22
+ # (6) 合 main trigger(R3 solo workflow specific):合進去 / 合 main / merge / 上 main
23
+ # (7) Past-tense 認可:好了 / OK 了 / 可以了 / 沒問題了 / 同意了 / 拍板了
24
+ # 2026-05-18 syntactic fix:加 closing `)` 收尾(原 `grep: parentheses not balanced`
25
+ # 錯誤造成 hook silent fail-closed BLOCKER。純語法 bug,**不** widen 偵測 scope —
26
+ # 既有 keyword list 不動。
27
+ export APPROVAL_KEYWORD_RE='(同意|採用|採納|拍板|可以|改成|改為|執行|上吧|push|implement|go ahead|approved|approve|OK|好|沒問題|做一做|就做|做吧|做完|全部做完|做到完|馬不停蹄|全部照建議做|建議做|照你建議|照建議|照共識|照我的|按照|合進去|合\s*main|merge|上\s*main|ship|好了|OK\s*了|可以了|沒問題了|同意了|拍板了|#[0-9]+\s*[A-Za-z]|^[0-9]+\.\s*[A-Za-z])'
28
+
29
+ # Helper:check input string contains approval keyword
30
+ # Usage: if has_approval "$user_msg"; then ...
31
+ has_approval() {
32
+ echo "$1" | grep -qE "$APPROVAL_KEYWORD_RE"
33
+ }
@@ -0,0 +1,73 @@
1
+ #!/bin/bash
2
+ # PostToolUse hook: lightweight code quality check on tsx/ts edit.
3
+ # Only runs the 2 fastest checks:
4
+ # 1. `any` usage without `// any-allow:` escape hatch
5
+ # 2. tsx file-size P0 (> 800 transition cap)
6
+ #
7
+ # Full audit (dead export / circular / long function) — use `/code-quality-audit` skill.
8
+
9
+ # Per-hook fire logging(enables /knowledge-prune D2 dead-hook detection)
10
+ source "$(dirname "$0")/../_log-fire.sh" 2>/dev/null && log_hook_fire
11
+
12
+ set -euo pipefail
13
+
14
+ FILE_PATH=$(jq -r '.tool_input.file_path // empty')
15
+
16
+ # Scope: only src/ .tsx / .ts files (not stories, not specs)
17
+ if ! echo "$FILE_PATH" | grep -qE 'src/.*\.tsx?$'; then
18
+ exit 0
19
+ fi
20
+ if echo "$FILE_PATH" | grep -qE '\.(stories|anatomy\.stories|principles\.stories)\.tsx$'; then
21
+ exit 0
22
+ fi
23
+ if [ ! -f "$FILE_PATH" ]; then
24
+ exit 0
25
+ fi
26
+
27
+ VIOLATIONS=""
28
+
29
+ # ── Check 1: `any` usage ────────────────────────────────────────────────────
30
+ # Flag `: any` / `as any` / `<any>` / `any[]` / `Record<X, any>`
31
+ # Skip lines with `any-allow` OR previous line with `any-allow`.
32
+ ANY_HITS=$(perl -ne '
33
+ BEGIN { our $prev_allow = 0; }
34
+ my $has_allow = /any-allow/;
35
+ my $line = $_;
36
+ if (!$prev_allow && !$has_allow) {
37
+ next if m{^\s*//};
38
+ next if m{^\s*\*};
39
+ next if m{/\* ?@ts-};
40
+ # Patterns
41
+ if (/:\s*any\b/ || /\bas\s+any\b/ || /<any>/ || /\bany\[\]/ || /Record<[^,]+,\s*any>/) {
42
+ # String literal FPs
43
+ unless (/[\x27"](any|many)[\x27"]/i) {
44
+ print "$.:$line";
45
+ }
46
+ }
47
+ }
48
+ $prev_allow = $has_allow;
49
+ ' "$FILE_PATH" 2>/dev/null | head -5)
50
+
51
+ if [ -n "$ANY_HITS" ]; then
52
+ VIOLATIONS="${VIOLATIONS}\n⚠️ TypeScript \`any\` usage(無 \`// any-allow: {rationale}\`):\n${ANY_HITS}\n 修法:改 proper type;真沒辦法(e.g. 3rd-party 類型外部化)→ 在同行或上一行加 \`// any-allow: {具體 rationale}\`"
53
+ fi
54
+
55
+ # ── Check 2: tsx file size ──────────────────────────────────────────────────
56
+ if echo "$FILE_PATH" | grep -qE '\.tsx$'; then
57
+ LINES=$(wc -l < "$FILE_PATH" | tr -d ' ')
58
+ # Exemption marker in top 20 lines: `// code-quality-allow: file-size {rationale}`
59
+ EXEMPT=$(head -20 "$FILE_PATH" | grep -cE 'code-quality-allow:\s*file-size' || true)
60
+ if [ "$LINES" -gt 800 ] && [ "$EXEMPT" -eq 0 ]; then
61
+ VIOLATIONS="${VIOLATIONS}\n⚠️ tsx file-size P0:${LINES} 行 > 800 transition cap(budget 500)。架構性拆分考慮:分 sub-component tsx(e.g. sidebar.tsx → sidebar.tsx + sidebar-menu.tsx + sidebar-group.tsx)。若係 foundational composite(Sidebar/TreeView 等),tsx 頂部加 \`// code-quality-allow: file-size {rationale}\` 明文豁免。"
62
+ fi
63
+ fi
64
+
65
+ # ── Emit warning ─────────────────────────────────────────────────────────
66
+ if [ -n "$VIOLATIONS" ]; then
67
+ ESCAPED=$(printf "%b" "$VIOLATIONS" | jq -Rs .)
68
+ cat <<EOJSON
69
+ {"hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":"Code quality lite check(full audit via /code-quality-audit):${ESCAPED}"}}
70
+ EOJSON
71
+ fi
72
+
73
+ exit 0