@qijenchen/design-system 0.1.0-beta.82 → 0.1.0-beta.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +8 -8
- package/README.md +3 -2
- package/dist/components/Alert/alert.js.map +1 -1
- package/dist/components/AppShell/_demo-helpers.d.ts.map +1 -1
- package/dist/components/AppShell/app-shell.d.ts +1 -1
- package/dist/components/AppShell/app-shell.d.ts.map +1 -1
- package/dist/components/AppShell/app-shell.js +22 -2
- package/dist/components/AppShell/app-shell.js.map +1 -1
- package/dist/components/Avatar/avatar.d.ts.map +1 -1
- package/dist/components/Avatar/avatar.js +4 -4
- package/dist/components/Avatar/avatar.js.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.d.ts.map +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js +1 -1
- package/dist/components/Breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/Button/button.d.ts +2 -2
- package/dist/components/Button/button.d.ts.map +1 -1
- package/dist/components/Button/button.js +12 -3
- package/dist/components/Button/button.js.map +1 -1
- package/dist/components/Calendar/calendar.d.ts +13 -5
- package/dist/components/Calendar/calendar.d.ts.map +1 -1
- package/dist/components/Calendar/calendar.js +7 -1
- package/dist/components/Calendar/calendar.js.map +1 -1
- package/dist/components/Carousel/carousel.d.ts.map +1 -1
- package/dist/components/Carousel/carousel.js +8 -3
- package/dist/components/Carousel/carousel.js.map +1 -1
- package/dist/components/Chart/chart.d.ts.map +1 -1
- package/dist/components/Chart/chart.js +1 -0
- package/dist/components/Chart/chart.js.map +1 -1
- package/dist/components/Checkbox/checkbox.d.ts +1 -1
- package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/checkbox.js +8 -4
- package/dist/components/Checkbox/checkbox.js.map +1 -1
- package/dist/components/Chip/chip.d.ts +1 -1
- package/dist/components/Chip/chip.d.ts.map +1 -1
- package/dist/components/Chip/chip.js.map +1 -1
- package/dist/components/Coachmark/coachmark.d.ts +10 -3
- package/dist/components/Coachmark/coachmark.d.ts.map +1 -1
- package/dist/components/Coachmark/coachmark.js.map +1 -1
- package/dist/components/Combobox/combobox.d.ts +5 -1
- package/dist/components/Combobox/combobox.d.ts.map +1 -1
- package/dist/components/Combobox/combobox.js +30 -13
- package/dist/components/Combobox/combobox.js.map +1 -1
- package/dist/components/DataTable/cell-registry.d.ts.map +1 -1
- package/dist/components/DataTable/cell-registry.js +53 -62
- package/dist/components/DataTable/cell-registry.js.map +1 -1
- package/dist/components/DataTable/column-types.d.ts +10 -4
- package/dist/components/DataTable/column-types.d.ts.map +1 -1
- package/dist/components/DataTable/column-types.js.map +1 -1
- package/dist/components/DataTable/data-table-column-visibility-panel.d.ts +1 -1
- package/dist/components/DataTable/data-table-column-visibility-panel.js +183 -0
- package/dist/components/DataTable/data-table-column-visibility-panel.js.map +1 -0
- package/dist/components/DataTable/data-table-filter-panel.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-filter-panel.js +607 -0
- package/dist/components/DataTable/data-table-filter-panel.js.map +1 -0
- package/dist/components/DataTable/data-table-interaction-layer.d.ts +11 -15
- package/dist/components/DataTable/data-table-interaction-layer.d.ts.map +1 -1
- package/dist/components/DataTable/data-table-interaction-layer.js +1 -3
- package/dist/components/DataTable/data-table-interaction-layer.js.map +1 -1
- package/dist/components/DataTable/data-table-sort-manager.js +140 -0
- package/dist/components/DataTable/data-table-sort-manager.js.map +1 -0
- package/dist/components/DataTable/data-table.d.ts +5 -6
- package/dist/components/DataTable/data-table.d.ts.map +1 -1
- package/dist/components/DataTable/data-table.js +36 -15
- package/dist/components/DataTable/data-table.js.map +1 -1
- package/dist/components/DataTable/filter-operators.js +140 -0
- package/dist/components/DataTable/filter-operators.js.map +1 -0
- package/dist/components/DataTable/filter-tree.js +312 -0
- package/dist/components/DataTable/filter-tree.js.map +1 -0
- package/dist/components/DataTable/index.d.ts +3 -0
- package/dist/components/DataTable/index.d.ts.map +1 -1
- package/dist/components/DataTable/index.js +12 -1
- package/dist/components/DataTable/index.js.map +1 -1
- package/dist/components/DataTable/lib/column-meta.js +25 -0
- package/dist/components/DataTable/lib/column-meta.js.map +1 -0
- package/dist/components/DateGrid/date-grid.d.ts.map +1 -1
- package/dist/components/DateGrid/date-grid.js +3 -1
- package/dist/components/DateGrid/date-grid.js.map +1 -1
- package/dist/components/DatePicker/date-picker.d.ts +7 -1
- package/dist/components/DatePicker/date-picker.d.ts.map +1 -1
- package/dist/components/DatePicker/date-picker.js +105 -74
- package/dist/components/DatePicker/date-picker.js.map +1 -1
- package/dist/components/Dialog/dialog.d.ts +20 -3
- package/dist/components/Dialog/dialog.d.ts.map +1 -1
- package/dist/components/Dialog/dialog.js +38 -20
- package/dist/components/Dialog/dialog.js.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/DropdownMenu/dropdown-menu.js +3 -1
- package/dist/components/DropdownMenu/dropdown-menu.js.map +1 -1
- package/dist/components/Field/field-context.d.ts +45 -5
- package/dist/components/Field/field-context.d.ts.map +1 -1
- package/dist/components/Field/field-context.js +19 -0
- package/dist/components/Field/field-context.js.map +1 -1
- package/dist/components/Field/field-edit-keys.d.ts +21 -0
- package/dist/components/Field/field-edit-keys.d.ts.map +1 -0
- package/dist/components/Field/field-edit-keys.js +19 -0
- package/dist/components/Field/field-edit-keys.js.map +1 -0
- package/dist/components/Field/field-types.d.ts +20 -1
- package/dist/components/Field/field-types.d.ts.map +1 -1
- package/dist/components/Field/field-types.js.map +1 -1
- package/dist/components/Field/field-wrapper.d.ts +3 -2
- package/dist/components/Field/field-wrapper.d.ts.map +1 -1
- package/dist/components/Field/field-wrapper.js +38 -39
- package/dist/components/Field/field-wrapper.js.map +1 -1
- package/dist/components/Field/field.d.ts +2 -1
- package/dist/components/Field/field.d.ts.map +1 -1
- package/dist/components/Field/field.js.map +1 -1
- package/dist/components/FieldControlGroup/field-control-group.d.ts +1 -1
- package/dist/components/FieldControlGroup/field-control-group.js.map +1 -1
- package/dist/components/FileItem/file-item.d.ts.map +1 -1
- package/dist/components/FileItem/file-item.js +1 -1
- package/dist/components/FileItem/file-item.js.map +1 -1
- package/dist/components/FileUpload/file-upload.d.ts +1 -1
- package/dist/components/FileUpload/file-upload.js.map +1 -1
- package/dist/components/FileViewer/file-viewer.d.ts.map +1 -1
- package/dist/components/FileViewer/file-viewer.js +7 -2
- package/dist/components/FileViewer/file-viewer.js.map +1 -1
- package/dist/components/FileViewer/image-renderer.d.ts.map +1 -1
- package/dist/components/FileViewer/image-renderer.js +22 -1
- package/dist/components/FileViewer/image-renderer.js.map +1 -1
- package/dist/components/HoverCard/hover-card.d.ts.map +1 -1
- package/dist/components/HoverCard/hover-card.js +5 -3
- package/dist/components/HoverCard/hover-card.js.map +1 -1
- package/dist/components/InlineEdit/index.d.ts +2 -0
- package/dist/components/InlineEdit/index.d.ts.map +1 -0
- package/dist/components/InlineEdit/index.js +5 -0
- package/dist/components/InlineEdit/index.js.map +1 -0
- package/dist/components/InlineEdit/inline-edit.d.ts +59 -0
- package/dist/components/InlineEdit/inline-edit.d.ts.map +1 -0
- package/dist/components/InlineEdit/inline-edit.js +164 -0
- package/dist/components/InlineEdit/inline-edit.js.map +1 -0
- package/dist/components/Input/input.d.ts +6 -11
- package/dist/components/Input/input.d.ts.map +1 -1
- package/dist/components/Input/input.js +43 -13
- package/dist/components/Input/input.js.map +1 -1
- package/dist/components/LinkInput/link-input.d.ts +2 -2
- package/dist/components/LinkInput/link-input.d.ts.map +1 -1
- package/dist/components/LinkInput/link-input.js +6 -5
- package/dist/components/LinkInput/link-input.js.map +1 -1
- package/dist/components/Menu/menu-item.d.ts +14 -2
- package/dist/components/Menu/menu-item.d.ts.map +1 -1
- package/dist/components/Menu/menu-item.js +25 -3
- package/dist/components/Menu/menu-item.js.map +1 -1
- package/dist/components/NumberInput/number-input.d.ts +3 -3
- package/dist/components/NumberInput/number-input.d.ts.map +1 -1
- package/dist/components/NumberInput/number-input.js +6 -5
- package/dist/components/NumberInput/number-input.js.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.d.ts.map +1 -1
- package/dist/components/OverflowIndicator/overflow-indicator.js +2 -6
- package/dist/components/OverflowIndicator/overflow-indicator.js.map +1 -1
- package/dist/components/Pagination/pagination.js +1 -1
- package/dist/components/Pagination/pagination.js.map +1 -1
- package/dist/components/PeoplePicker/index.js +7 -1
- package/dist/components/PeoplePicker/index.js.map +1 -1
- package/dist/components/PeoplePicker/people-picker.d.ts +9 -2
- package/dist/components/PeoplePicker/people-picker.d.ts.map +1 -1
- package/dist/components/PeoplePicker/people-picker.js +23 -10
- package/dist/components/PeoplePicker/people-picker.js.map +1 -1
- package/dist/components/PeoplePicker/person-display.d.ts +6 -3
- package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
- package/dist/components/PeoplePicker/person-display.js +19 -14
- package/dist/components/PeoplePicker/person-display.js.map +1 -1
- package/dist/components/Popover/popover.d.ts.map +1 -1
- package/dist/components/Popover/popover.js +3 -1
- package/dist/components/Popover/popover.js.map +1 -1
- package/dist/components/ProfileCard/profile-card.d.ts +2 -2
- package/dist/components/ProfileCard/profile-card.js +3 -3
- package/dist/components/ProfileCard/profile-card.js.map +1 -1
- package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
- package/dist/components/RadioGroup/radio-group.js +15 -9
- package/dist/components/RadioGroup/radio-group.js.map +1 -1
- package/dist/components/ScrollArea/scroll-area.d.ts +11 -1
- package/dist/components/ScrollArea/scroll-area.d.ts.map +1 -1
- package/dist/components/ScrollArea/scroll-area.js +6 -3
- package/dist/components/ScrollArea/scroll-area.js.map +1 -1
- package/dist/components/Select/select.d.ts +46 -5
- package/dist/components/Select/select.d.ts.map +1 -1
- package/dist/components/Select/select.js +109 -28
- package/dist/components/Select/select.js.map +1 -1
- package/dist/components/SelectMenu/select-menu.d.ts +3 -1
- package/dist/components/SelectMenu/select-menu.d.ts.map +1 -1
- package/dist/components/SelectMenu/select-menu.js +8 -1
- package/dist/components/SelectMenu/select-menu.js.map +1 -1
- package/dist/components/SelectionControl/boolean-value.d.ts +11 -0
- package/dist/components/SelectionControl/boolean-value.d.ts.map +1 -0
- package/dist/components/SelectionControl/boolean-value.js +23 -0
- package/dist/components/SelectionControl/boolean-value.js.map +1 -0
- package/dist/components/SelectionControl/index.d.ts +1 -0
- package/dist/components/SelectionControl/index.d.ts.map +1 -1
- package/dist/components/SelectionControl/index.js +2 -0
- package/dist/components/SelectionControl/index.js.map +1 -1
- package/dist/components/Sheet/index.js +2 -1
- package/dist/components/Sheet/sheet.d.ts +7 -1
- package/dist/components/Sheet/sheet.d.ts.map +1 -1
- package/dist/components/Sheet/sheet.js +5 -2
- package/dist/components/Sheet/sheet.js.map +1 -1
- package/dist/components/Sidebar/sidebar.d.ts +9 -4
- package/dist/components/Sidebar/sidebar.d.ts.map +1 -1
- package/dist/components/Sidebar/sidebar.js +8 -10
- package/dist/components/Sidebar/sidebar.js.map +1 -1
- package/dist/components/Slider/slider.d.ts.map +1 -1
- package/dist/components/Slider/slider.js.map +1 -1
- package/dist/components/Switch/switch.d.ts +6 -6
- package/dist/components/Switch/switch.d.ts.map +1 -1
- package/dist/components/Switch/switch.js +3 -2
- package/dist/components/Switch/switch.js.map +1 -1
- package/dist/components/Tabs/tabs.d.ts.map +1 -1
- package/dist/components/Tabs/tabs.js +15 -1
- package/dist/components/Tabs/tabs.js.map +1 -1
- package/dist/components/Textarea/textarea.d.ts +2 -2
- package/dist/components/Textarea/textarea.d.ts.map +1 -1
- package/dist/components/Textarea/textarea.js +50 -42
- package/dist/components/Textarea/textarea.js.map +1 -1
- package/dist/components/TimePicker/time-columns.d.ts.map +1 -1
- package/dist/components/TimePicker/time-columns.js +42 -38
- package/dist/components/TimePicker/time-columns.js.map +1 -1
- package/dist/components/TimePicker/time-picker.d.ts.map +1 -1
- package/dist/components/TimePicker/time-picker.js +8 -6
- package/dist/components/TimePicker/time-picker.js.map +1 -1
- package/dist/components/Tooltip/tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip/tooltip.js +7 -5
- package/dist/components/Tooltip/tooltip.js.map +1 -1
- package/dist/components/TreeView/tree-view.d.ts +56 -1
- package/dist/components/TreeView/tree-view.d.ts.map +1 -1
- package/dist/components/TreeView/tree-view.js +211 -12
- package/dist/components/TreeView/tree-view.js.map +1 -1
- package/dist/index.d.ts +115 -58
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +93 -108
- package/dist/index.js.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.d.ts +7 -6
- package/dist/patterns/element-anatomy/item-anatomy.d.ts.map +1 -1
- package/dist/patterns/element-anatomy/item-anatomy.js.map +1 -1
- package/dist/tokens/categorical-color.js +15 -0
- package/dist/tokens/categorical-color.js.map +1 -1
- package/dist/tokens/motion/motion.d.ts +7 -6
- package/dist/tokens/motion/motion.d.ts.map +1 -1
- package/dist/tokens/motion/motion.js +6 -6
- package/dist/tokens/motion/motion.js.map +1 -1
- package/dist/tokens/motion/overlay-motion.d.ts +19 -0
- package/dist/tokens/motion/overlay-motion.d.ts.map +1 -0
- package/dist/tokens/motion/overlay-motion.js +9 -0
- package/dist/tokens/motion/overlay-motion.js.map +1 -0
- package/dist/tokens/uiSize/icon-size.js +5 -0
- package/dist/tokens/uiSize/icon-size.js.map +1 -0
- package/ds-canonical/fork/governance.lock +37 -19
- package/ds-canonical/fork/hooks/_log-fire.sh +46 -0
- package/ds-canonical/fork/hooks/block_prototype_imports.py +15 -4
- package/ds-canonical/fork/hooks/check_consumer_app_invariants.sh +145 -13
- package/ds-canonical/fork/hooks/check_ds_anchor_preflight.sh +17 -5
- package/ds-canonical/fork/hooks/check_dynamic_tailwind_class.sh +47 -0
- package/ds-canonical/fork/hooks/check_escape_marker_abuse.sh +27 -0
- package/ds-canonical/fork/hooks/check_field_family_invariants.sh +61 -1
- package/ds-canonical/fork/hooks/check_layout_space_magic_numbers.sh +28 -4
- package/ds-canonical/fork/hooks/check_opacity_token_usage.sh +36 -0
- package/ds-canonical/fork/hooks/check_story_determinism.sh +39 -0
- package/ds-canonical/fork/hooks/check_story_invariants.sh +119 -0
- package/ds-canonical/fork/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
- package/ds-canonical/fork/manifest.json +20 -0
- package/ds-canonical/fork/preamble.md +22 -18
- package/ds-canonical/fork/skills/bug-fix-rhythm/SKILL.md +9 -3
- package/ds-canonical/fork/skills/code-quality-audit/SKILL.md +3 -3
- package/ds-canonical/fork/skills/delivery-handoff/SKILL.md +7 -0
- package/ds-canonical/fork/skills/performance-audit/SKILL.md +4 -2
- package/ds-canonical/fork/skills/product-ui-audit/SKILL.md +3 -3
- package/ds-canonical/fork/skills/propose-options/SKILL.md +3 -3
- package/ds-canonical/fork/skills/prototype/SKILL.md +1 -1
- package/ds-canonical/fork/skills/scan-similar-bugs/SKILL.md +2 -2
- package/ds-canonical/fork/skills/visual-audit/SKILL.md +10 -2
- package/ds-canonical/hooks/README.md +1 -1
- package/ds-canonical/hooks/block_prototype_imports.py +15 -4
- package/ds-canonical/hooks/check_audit_post_report_validator.sh +65 -7
- package/ds-canonical/hooks/check_benchmark_citation.sh +5 -3
- package/ds-canonical/hooks/check_codex_brief_invariants.sh +28 -1
- package/ds-canonical/hooks/check_consumer_app_invariants.sh +145 -13
- package/ds-canonical/hooks/check_ds_anchor_preflight.sh +17 -5
- package/ds-canonical/hooks/check_dynamic_tailwind_class.sh +47 -0
- package/ds-canonical/hooks/check_escape_marker_abuse.sh +27 -0
- package/ds-canonical/hooks/check_field_family_invariants.sh +61 -1
- package/ds-canonical/hooks/check_layout_space_magic_numbers.sh +28 -4
- package/ds-canonical/hooks/check_naming_and_abstraction.sh +1 -1
- package/ds-canonical/hooks/check_opacity_token_usage.sh +36 -0
- package/ds-canonical/hooks/check_pixel_quantified_audit.sh +3 -2
- package/ds-canonical/hooks/check_post_main_ssot_propagate.sh +6 -1
- package/ds-canonical/hooks/check_propose_without_benchmark.sh +6 -2
- package/ds-canonical/hooks/check_ssot_header_declaration.sh +55 -0
- package/ds-canonical/hooks/check_story_determinism.sh +39 -0
- package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +8 -7
- package/ds-canonical/hooks/check_tabs_content_chrome_body_double_gap.sh +29 -0
- package/ds-canonical/hooks/lib/_story_compile_drift.sh +1 -1
- package/ds-canonical/hooks/lib/_token_hygiene.sh +10 -1
- package/ds-canonical/hooks/stop_self_audit.sh +31 -0
- package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +24 -0
- package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +44 -0
- package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +3 -3
- package/ds-canonical/hooks/tests/test_check_codex_brief_invariants.sh +43 -2
- package/ds-canonical/hooks/tests/test_check_consumer_ds_primitive_misuse.sh +112 -0
- package/ds-canonical/hooks/tests/test_check_consumer_story_baseline.sh +9 -2
- package/ds-canonical/hooks/tests/test_check_dynamic_tailwind_class.sh +76 -0
- package/ds-canonical/hooks/tests/test_check_escape_marker_abuse.sh +24 -0
- package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +27 -2
- package/ds-canonical/hooks/tests/test_check_fork_user_plugin_install.sh +3 -1
- package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +41 -2
- package/ds-canonical/hooks/tests/test_check_ssot_header_declaration.sh +72 -0
- package/ds-canonical/hooks/tests/test_check_tabs_content_chrome_body_double_gap.sh +76 -0
- package/ds-canonical/references/audit-coverage-vs-24-checklist.md +1 -1
- package/ds-canonical/references/build-ui-canonicals.md +2 -1
- package/ds-canonical/references/failure-class-registry.json +145 -0
- package/ds-canonical/references/governance-audit-coverage.md +33 -0
- package/ds-canonical/references/item-anatomy-recipe.md +2 -2
- package/ds-canonical/references/scenario-definition.md +6 -9
- package/ds-canonical/references/ssot-consultation.md +2 -2
- package/ds-canonical/references/ssot-index.md +5 -4
- package/ds-canonical/references/story-baseline-registry.json +8 -2
- package/ds-canonical/references/structural-token-retention.md +6 -9
- package/ds-canonical/rules/meta-patterns.md +8 -8
- package/ds-canonical/rules/self-verify.md +4 -3
- package/ds-canonical/rules/spec-rules.md +1 -1
- package/ds-canonical/rules/story-rules.md +2 -2
- package/ds-canonical/rules/ui-development.md +4 -2
- package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +9 -3
- package/ds-canonical/skills/code-quality-audit/SKILL.md +3 -3
- package/ds-canonical/skills/codex-collab/SKILL.md +9 -7
- package/ds-canonical/skills/codex-collab/references/brief-template.md +1 -1
- package/ds-canonical/skills/codify-principle/SKILL.md +2 -2
- package/ds-canonical/skills/component-quality-gate/SKILL.md +1 -1
- package/ds-canonical/skills/component-quality-gate/references/checklist.md +2 -2
- package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +57 -68
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +29 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +29 -10
- package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +21 -0
- package/ds-canonical/skills/delivery-handoff/SKILL.md +5 -0
- package/ds-canonical/skills/design-system-audit/SKILL.md +27 -26
- package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +13 -1
- package/ds-canonical/skills/design-system-audit/references/rule-placement.md +1 -1
- package/ds-canonical/skills/governance-health/SKILL.md +2 -1
- package/ds-canonical/skills/knowledge-prune/SKILL.md +3 -0
- package/ds-canonical/skills/knowledge-prune/references/prune-dimensions-d5-d10.md +1 -0
- package/ds-canonical/skills/new-component/SKILL.md +7 -5
- package/ds-canonical/skills/new-component/references/new-component-checklist.md +1 -1
- package/ds-canonical/skills/performance-audit/SKILL.md +2 -2
- package/ds-canonical/skills/product-ui-audit/SKILL.md +3 -3
- package/ds-canonical/skills/propose-options/SKILL.md +3 -3
- package/ds-canonical/skills/prototype/SKILL.md +1 -1
- package/ds-canonical/skills/scan-similar-bugs/SKILL.md +2 -2
- package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +3 -3
- package/ds-canonical/skills/story-writing/SKILL.md +3 -3
- package/ds-canonical/skills/visual-audit/SKILL.md +10 -2
- package/ds-story-manifest.json +29 -20
- package/llms-full.txt +22 -1
- package/llms.txt +5 -4
- package/package.json +7 -3
- package/src/components/Accordion/accordion.principles.stories.tsx +1 -1
- package/src/components/Accordion/accordion.stories.tsx +16 -1
- package/src/components/Alert/alert.principles.stories.tsx +1 -1
- package/src/components/Alert/alert.spec.md +8 -10
- package/src/components/Alert/alert.stories.tsx +28 -28
- package/src/components/Alert/alert.tsx +1 -1
- package/src/components/AppShell/_demo-helpers.tsx +6 -3
- package/src/components/AppShell/app-shell.spec.md +4 -4
- package/src/components/AppShell/app-shell.tsx +28 -2
- package/src/components/AspectRatio/aspect-ratio.spec.md +1 -1
- package/src/components/AspectRatio/aspect-ratio.stories.tsx +7 -89
- package/src/components/Avatar/avatar.anatomy.stories.tsx +7 -3
- package/src/components/Avatar/avatar.principles.stories.tsx +19 -15
- package/src/components/Avatar/avatar.spec.md +2 -2
- package/src/components/Avatar/avatar.stories.tsx +8 -6
- package/src/components/Avatar/avatar.tsx +13 -5
- package/src/components/Badge/badge.principles.stories.tsx +1 -1
- package/src/components/Badge/badge.spec.md +2 -0
- package/src/components/Badge/badge.stories.tsx +4 -2
- package/src/components/Breadcrumb/breadcrumb.principles.stories.tsx +6 -4
- package/src/components/Breadcrumb/breadcrumb.stories.tsx +6 -5
- package/src/components/Breadcrumb/breadcrumb.tsx +3 -2
- package/src/components/BulkActionBar/bulk-action-bar.spec.md +4 -2
- package/src/components/Button/button.principles.stories.tsx +1 -1
- package/src/components/Button/button.spec.md +2 -2
- package/src/components/Button/button.tsx +18 -3
- package/src/components/Calendar/calendar.anatomy.stories.tsx +12 -10
- package/src/components/Calendar/calendar.principles.stories.tsx +14 -6
- package/src/components/Calendar/calendar.spec.md +5 -4
- package/src/components/Calendar/calendar.stories.tsx +7 -4
- package/src/components/Calendar/calendar.tsx +26 -7
- package/src/components/Carousel/carousel.anatomy.stories.tsx +5 -4
- package/src/components/Carousel/carousel.spec.md +2 -2
- package/src/components/Carousel/carousel.tsx +11 -3
- package/src/components/Chart/chart.anatomy.stories.tsx +7 -4
- package/src/components/Chart/chart.principles.stories.tsx +1 -1
- package/src/components/Chart/chart.stories.tsx +2 -8
- package/src/components/Chart/chart.tsx +3 -0
- package/src/components/Checkbox/checkbox.anatomy.stories.tsx +28 -49
- package/src/components/Checkbox/checkbox.principles.stories.tsx +1 -1
- package/src/components/Checkbox/checkbox.spec.md +11 -26
- package/src/components/Checkbox/checkbox.stories.tsx +11 -8
- package/src/components/Checkbox/checkbox.tsx +18 -13
- package/src/components/Chip/chip.anatomy.stories.tsx +44 -24
- package/src/components/Chip/chip.principles.stories.tsx +1 -1
- package/src/components/Chip/chip.spec.md +5 -4
- package/src/components/Chip/chip.tsx +5 -1
- package/src/components/CircularProgress/circular-progress.principles.stories.tsx +7 -4
- package/src/components/CircularProgress/circular-progress.spec.md +3 -3
- package/src/components/CircularProgress/circular-progress.stories.tsx +2 -2
- package/src/components/Coachmark/coachmark.anatomy.stories.tsx +2 -2
- package/src/components/Coachmark/coachmark.principles.stories.tsx +2 -1
- package/src/components/Coachmark/coachmark.spec.md +5 -5
- package/src/components/Coachmark/coachmark.stories.tsx +3 -1
- package/src/components/Coachmark/coachmark.tsx +10 -3
- package/src/components/Combobox/combobox.anatomy.stories.tsx +2 -2
- package/src/components/Combobox/combobox.tsx +53 -19
- package/src/components/Command/command.anatomy.stories.tsx +2 -2
- package/src/components/Command/command.principles.stories.tsx +1 -1
- package/src/components/Command/command.stories.tsx +42 -10
- package/src/components/DataTable/cell-registry.tsx +86 -63
- package/src/components/DataTable/column-types.ts +10 -1
- package/src/components/DataTable/data-table-column-visibility-panel.tsx +1 -1
- package/src/components/DataTable/data-table-filter-panel.tsx +4 -1
- package/src/components/DataTable/data-table-interaction-layer.tsx +15 -19
- package/src/components/DataTable/data-table.anatomy.stories.tsx +15 -13
- package/src/components/DataTable/data-table.principles.stories.tsx +9 -9
- package/src/components/DataTable/data-table.spec.md +32 -12
- package/src/components/DataTable/data-table.stories.tsx +16 -17
- package/src/components/DataTable/data-table.tsx +103 -60
- package/src/components/DataTable/index.ts +3 -0
- package/src/components/DateGrid/date-grid.anatomy.stories.tsx +4 -4
- package/src/components/DateGrid/date-grid.principles.stories.tsx +1 -1
- package/src/components/DateGrid/date-grid.spec.md +1 -1
- package/src/components/DateGrid/date-grid.tsx +3 -1
- package/src/components/DatePicker/date-picker.anatomy.stories.tsx +8 -8
- package/src/components/DatePicker/date-picker.principles.stories.tsx +3 -3
- package/src/components/DatePicker/date-picker.spec.md +3 -3
- package/src/components/DatePicker/date-picker.stories.tsx +4 -5
- package/src/components/DatePicker/date-picker.tsx +99 -45
- package/src/components/DescriptionList/description-list.anatomy.stories.tsx +12 -10
- package/src/components/DescriptionList/description-list.principles.stories.tsx +2 -2
- package/src/components/DescriptionList/description-list.spec.md +3 -3
- package/src/components/DescriptionList/description-list.stories.tsx +7 -6
- package/src/components/Dialog/dialog.anatomy.stories.tsx +1 -0
- package/src/components/Dialog/dialog.spec.md +9 -0
- package/src/components/Dialog/dialog.stories.tsx +66 -5
- package/src/components/Dialog/dialog.tsx +60 -25
- package/src/components/DropdownMenu/dropdown-menu.anatomy.stories.tsx +1 -1
- package/src/components/DropdownMenu/dropdown-menu.principles.stories.tsx +8 -6
- package/src/components/DropdownMenu/dropdown-menu.spec.md +5 -5
- package/src/components/DropdownMenu/dropdown-menu.tsx +18 -9
- package/src/components/Empty/empty.anatomy.stories.tsx +1 -1
- package/src/components/Empty/empty.spec.md +2 -2
- package/src/components/Field/field-context.ts +69 -5
- package/src/components/Field/field-controls.spec.md +62 -8
- package/src/components/Field/field-edit-keys.ts +66 -0
- package/src/components/Field/field-types.ts +58 -9
- package/src/components/Field/field-wrapper.tsx +50 -42
- package/src/components/Field/field.anatomy.stories.tsx +9 -6
- package/src/components/Field/field.spec.md +1 -1
- package/src/components/Field/field.stories.tsx +1 -1
- package/src/components/Field/field.tsx +2 -1
- package/src/components/Field/form-validation.spec.md +3 -3
- package/src/components/FieldControlGroup/field-control-group.principles.stories.tsx +6 -6
- package/src/components/FieldControlGroup/field-control-group.spec.md +9 -4
- package/src/components/FieldControlGroup/field-control-group.tsx +1 -1
- package/src/components/FileItem/file-item.anatomy.stories.tsx +1 -1
- package/src/components/FileItem/file-item.spec.md +14 -8
- package/src/components/FileItem/file-item.stories.tsx +36 -25
- package/src/components/FileItem/file-item.tsx +8 -6
- package/src/components/FileUpload/file-upload.anatomy.stories.tsx +6 -6
- package/src/components/FileUpload/file-upload.principles.stories.tsx +5 -5
- package/src/components/FileUpload/file-upload.spec.md +1 -1
- package/src/components/FileUpload/file-upload.tsx +1 -1
- package/src/components/FileViewer/file-viewer.anatomy.stories.tsx +4 -3
- package/src/components/FileViewer/file-viewer.principles.stories.tsx +3 -3
- package/src/components/FileViewer/file-viewer.spec.md +30 -12
- package/src/components/FileViewer/file-viewer.stories.tsx +1 -2
- package/src/components/FileViewer/file-viewer.tsx +12 -4
- package/src/components/FileViewer/image-renderer.tsx +35 -7
- package/src/components/HoverCard/hover-card.anatomy.stories.tsx +6 -2
- package/src/components/HoverCard/hover-card.principles.stories.tsx +6 -3
- package/src/components/HoverCard/hover-card.spec.md +5 -5
- package/src/components/HoverCard/hover-card.stories.tsx +16 -16
- package/src/components/HoverCard/hover-card.tsx +5 -3
- package/src/components/InlineEdit/index.ts +5 -0
- package/src/components/InlineEdit/inline-edit.spec.md +149 -0
- package/src/components/InlineEdit/inline-edit.stories.tsx +246 -0
- package/src/components/InlineEdit/inline-edit.tsx +287 -0
- package/src/components/Input/input.anatomy.stories.tsx +8 -7
- package/src/components/Input/input.principles.stories.tsx +2 -12
- package/src/components/Input/input.spec.md +13 -18
- package/src/components/Input/input.tsx +69 -22
- package/src/components/LinkInput/link-input.anatomy.stories.tsx +1 -1
- package/src/components/LinkInput/link-input.principles.stories.tsx +2 -2
- package/src/components/LinkInput/link-input.tsx +11 -10
- package/src/components/Menu/menu-item.anatomy.stories.tsx +3 -3
- package/src/components/Menu/menu-item.principles.stories.tsx +1 -1
- package/src/components/Menu/menu-item.spec.md +22 -15
- package/src/components/Menu/menu-item.stories.tsx +39 -11
- package/src/components/Menu/menu-item.tsx +38 -4
- package/src/components/Notice/notice.principles.stories.tsx +1 -1
- package/src/components/Notice/notice.spec.md +16 -3
- package/src/components/NumberInput/number-input.anatomy.stories.tsx +3 -3
- package/src/components/NumberInput/number-input.principles.stories.tsx +1 -1
- package/src/components/NumberInput/number-input.spec.md +4 -4
- package/src/components/NumberInput/number-input.tsx +19 -12
- package/src/components/OverflowIndicator/overflow-indicator.anatomy.stories.tsx +10 -8
- package/src/components/OverflowIndicator/overflow-indicator.principles.stories.tsx +3 -3
- package/src/components/OverflowIndicator/overflow-indicator.spec.md +4 -2
- package/src/components/OverflowIndicator/overflow-indicator.stories.tsx +71 -63
- package/src/components/OverflowIndicator/overflow-indicator.tsx +9 -8
- package/src/components/Pagination/pagination.spec.md +1 -1
- package/src/components/Pagination/pagination.stories.tsx +2 -6
- package/src/components/Pagination/pagination.tsx +1 -1
- package/src/components/PeoplePicker/people-picker.anatomy.stories.tsx +4 -4
- package/src/components/PeoplePicker/people-picker.principles.stories.tsx +2 -2
- package/src/components/PeoplePicker/people-picker.spec.md +6 -6
- package/src/components/PeoplePicker/people-picker.tsx +56 -16
- package/src/components/PeoplePicker/person-display.tsx +32 -16
- package/src/components/Popover/popover.anatomy.stories.tsx +2 -2
- package/src/components/Popover/popover.tsx +3 -1
- package/src/components/ProfileCard/profile-card.anatomy.stories.tsx +12 -23
- package/src/components/ProfileCard/profile-card.spec.md +3 -3
- package/src/components/ProfileCard/profile-card.tsx +6 -6
- package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +3 -1
- package/src/components/ProgressBar/progress-bar.principles.stories.tsx +1 -1
- package/src/components/ProgressBar/progress-bar.stories.tsx +50 -42
- package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +10 -28
- package/src/components/RadioGroup/radio-group.stories.tsx +29 -32
- package/src/components/RadioGroup/radio-group.tsx +41 -15
- package/src/components/Rating/rating.spec.md +11 -3
- package/src/components/ScrollArea/scroll-area.anatomy.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.principles.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.spec.md +7 -3
- package/src/components/ScrollArea/scroll-area.stories.tsx +1 -1
- package/src/components/ScrollArea/scroll-area.tsx +17 -4
- package/src/components/Select/select.anatomy.stories.tsx +3 -3
- package/src/components/Select/select.spec.md +27 -17
- package/src/components/Select/select.stories.tsx +33 -0
- package/src/components/Select/select.tsx +190 -36
- package/src/components/SelectMenu/select-menu.anatomy.stories.tsx +4 -4
- package/src/components/SelectMenu/select-menu.spec.md +15 -7
- package/src/components/SelectMenu/select-menu.tsx +16 -3
- package/src/components/SelectionControl/boolean-value.tsx +39 -0
- package/src/components/SelectionControl/index.ts +1 -0
- package/src/components/SelectionControl/selection-item.anatomy.stories.tsx +2 -2
- package/src/components/SelectionControl/selection-item.principles.stories.tsx +2 -2
- package/src/components/SelectionControl/selection-item.spec.md +3 -3
- package/src/components/SelectionControl/selection-item.stories.tsx +3 -3
- package/src/components/Separator/separator.spec.md +2 -2
- package/src/components/Separator/separator.stories.tsx +6 -27
- package/src/components/Sheet/sheet.anatomy.stories.tsx +1 -1
- package/src/components/Sheet/sheet.principles.stories.tsx +1 -1
- package/src/components/Sheet/sheet.spec.md +2 -2
- package/src/components/Sheet/sheet.tsx +9 -5
- package/src/components/Sidebar/sidebar.anatomy.stories.tsx +16 -12
- package/src/components/Sidebar/sidebar.principles.stories.tsx +10 -8
- package/src/components/Sidebar/sidebar.spec.md +13 -15
- package/src/components/Sidebar/sidebar.stories.tsx +8 -7
- package/src/components/Sidebar/sidebar.tsx +37 -25
- package/src/components/Skeleton/skeleton.stories.tsx +4 -11
- package/src/components/Slider/slider.anatomy.stories.tsx +3 -3
- package/src/components/Slider/slider.principles.stories.tsx +2 -2
- package/src/components/Slider/slider.spec.md +5 -5
- package/src/components/Slider/slider.tsx +3 -1
- package/src/components/Steps/steps.anatomy.stories.tsx +4 -4
- package/src/components/Steps/steps.principles.stories.tsx +1 -1
- package/src/components/Steps/steps.spec.md +1 -1
- package/src/components/Switch/switch.anatomy.stories.tsx +7 -7
- package/src/components/Switch/switch.principles.stories.tsx +4 -4
- package/src/components/Switch/switch.spec.md +8 -8
- package/src/components/Switch/switch.stories.tsx +9 -24
- package/src/components/Switch/switch.tsx +17 -13
- package/src/components/Tabs/tabs.anatomy.stories.tsx +10 -7
- package/src/components/Tabs/tabs.spec.md +1 -1
- package/src/components/Tabs/tabs.tsx +21 -1
- package/src/components/Textarea/textarea.anatomy.stories.tsx +1 -1
- package/src/components/Textarea/textarea.principles.stories.tsx +1 -1
- package/src/components/Textarea/textarea.spec.md +4 -4
- package/src/components/Textarea/textarea.tsx +72 -46
- package/src/components/TimePicker/time-columns.tsx +6 -2
- package/src/components/TimePicker/time-picker.principles.stories.tsx +1 -1
- package/src/components/TimePicker/time-picker.spec.md +3 -3
- package/src/components/TimePicker/time-picker.tsx +16 -10
- package/src/components/Toast/toast.stories.tsx +7 -4
- package/src/components/Tooltip/tooltip.anatomy.stories.tsx +4 -4
- package/src/components/Tooltip/tooltip.principles.stories.tsx +3 -3
- package/src/components/Tooltip/tooltip.spec.md +1 -1
- package/src/components/Tooltip/tooltip.stories.tsx +4 -39
- package/src/components/Tooltip/tooltip.tsx +8 -6
- package/src/components/TreeView/tree-view.anatomy.stories.tsx +6 -3
- package/src/components/TreeView/tree-view.spec.md +42 -11
- package/src/components/TreeView/tree-view.stories.tsx +1 -0
- package/src/components/TreeView/tree-view.tsx +322 -17
- package/src/index.ts +584 -60
- package/src/patterns/action-bar/action-bar.spec.md +9 -0
- package/src/patterns/action-bar/action-bar.stories.tsx +6 -3
- package/src/patterns/element-anatomy/inline-action.spec.md +2 -0
- package/src/patterns/element-anatomy/item-anatomy.spec.md +14 -5
- package/src/patterns/element-anatomy/item-anatomy.stories.tsx +6 -4
- package/src/patterns/element-anatomy/item-anatomy.tsx +7 -6
- package/src/patterns/header-canonical/header-canonical.spec.md +5 -4
- package/src/patterns/overlay-surface/overlay-surface.spec.md +22 -1
- package/src/styles/tokens.css +3 -0
- package/src/tokens/README.md +1 -1
- package/src/tokens/color/color.spec.md +3 -3
- package/src/tokens/color/color.stories.tsx +3 -3
- package/src/tokens/density/density.stories.tsx +16 -3
- package/src/tokens/layoutSpace/layoutSpace.spec.md +3 -1
- package/src/tokens/motion/motion.css +33 -21
- package/src/tokens/motion/motion.spec.md +32 -15
- package/src/tokens/motion/motion.stories.tsx +58 -5
- package/src/tokens/motion/motion.ts +7 -6
- package/src/tokens/motion/overlay-motion.ts +26 -0
- package/src/tokens/orphan-tokens.spec.md +4 -4
- package/src/tokens/token-system.spec.md +1 -0
- package/src/tokens/uiSize/uiSize.spec.md +1 -1
- package/src/tokens/uiSize/uiSize.stories.tsx +4 -2
- package/src/tokens/utility-registry.json +160 -23
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
#
|
|
4
4
|
# Hook(PreToolUse Edit/Write/MultiEdit):spec.md / .tsx in packages/design-system/src/
|
|
5
5
|
# 含 world-class benchmark claim(Ant / Material / Polaris ...)必附 inline citation
|
|
6
|
-
# (URL / GitHub #L / snapshots/ / @benchmark-unverified)。違
|
|
6
|
+
# (URL / GitHub #L / snapshots/ / @benchmark-unverified)。違 P0 BLOCKER(exit 2,2026-07-07 方向 2 升級;escape marker 既有)。
|
|
7
7
|
# 整檔 escape:前 5 行含 @benchmark-citation-allow: 或 @benchmark-unverified-blanket:。
|
|
8
8
|
|
|
9
9
|
set -u
|
|
@@ -45,10 +45,10 @@ expect_pass_silent() {
|
|
|
45
45
|
|
|
46
46
|
expect_warn() {
|
|
47
47
|
local name="$1"; local needle="$2"
|
|
48
|
-
if [ "$EXIT" = "
|
|
48
|
+
if [ "$EXIT" = "2" ] && echo "$STDERR_TEXT" | grep -qF "$needle"; then
|
|
49
49
|
echo " PASS $name"; PASS=$((PASS+1))
|
|
50
50
|
else
|
|
51
|
-
echo " FAIL $name (expected exit=
|
|
51
|
+
echo " FAIL $name (expected exit=2 + needle '$needle', got exit $EXIT)"
|
|
52
52
|
echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
|
|
53
53
|
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
54
54
|
fi
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
# · bare mention(`ls .../codex` / `mycodex exec` / git commit msg 含 "codex")→ silent
|
|
9
9
|
# · `--help` / `--version` 等 introspection flag → silent
|
|
10
10
|
# - 命中 codex exec/review → 擷取 brief content(cat-pipe / $(cat) / stdin `<` / inline arg)
|
|
11
|
-
# - Brief 必含
|
|
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> (
|
|
169
|
+
expect_pass_silent "N6. bare <Dialog> (local import) → silent (over-broad guard)"
|
|
170
|
+
|
|
171
|
+
# P5. named-import 除鏽 POSITIVE(2026-07-10):bare <Dialog> 但由 DS package named-import 進來
|
|
172
|
+
# → 是真 DS Dialog(fork 慣用 named import 繞過 <DS.> 前綴)→ 無 marker 必 BLOCK
|
|
173
|
+
CONTENT_NAMED='import { Dialog, Button } from "@qijenchen/design-system";
|
|
174
|
+
export const Basic = () => <Dialog open><Button>ok</Button></Dialog>;'
|
|
175
|
+
run_hook "Write" "$CONSUMER_STORY" "$CONTENT_NAMED"
|
|
176
|
+
expect_block "P5. named-import <Dialog> from DS pkg 無 marker → BLOCK" "CONSUMER-STORY-BASELINE BLOCKER"
|
|
170
177
|
|
|
171
178
|
# N7. over-broad guard B:comment / prose mentioning "Dialog DataTable Sheet" but no JSX usage → silent
|
|
172
179
|
CONTENT_PROSE='// This story demonstrates a layout. We avoid Dialog and DataTable here.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# test_check_dynamic_tailwind_class.sh — 動態 Tailwind class 哨測試
|
|
3
|
+
# (2026-07-10 補 hook-test-coverage debt;hook 2026-07-09 建,anchor = h-table-row-${size} row 塌)
|
|
4
|
+
set -uo pipefail
|
|
5
|
+
cd "$(dirname "$0")/../../.."
|
|
6
|
+
HOOK=".claude/hooks/check_dynamic_tailwind_class.sh"
|
|
7
|
+
PASS=0; FAIL=0; FAILED_TESTS=""
|
|
8
|
+
|
|
9
|
+
TMP_DIR=$(mktemp -d)
|
|
10
|
+
trap 'rm -rf "$TMP_DIR"' EXIT
|
|
11
|
+
export CLAUDE_PROJECT_DIR="$TMP_DIR"
|
|
12
|
+
mkdir -p "$TMP_DIR/.claude/logs"
|
|
13
|
+
|
|
14
|
+
PROD_TSX="/Users/x/proj/packages/design-system/src/components/DataTable/data-table.tsx"
|
|
15
|
+
|
|
16
|
+
run_hook() {
|
|
17
|
+
local file_path="$1"; local content="$2"
|
|
18
|
+
local payload
|
|
19
|
+
payload=$(jq -n --arg fp "$file_path" --arg c "$content" \
|
|
20
|
+
'{tool_name:"Edit", tool_input:{file_path:$fp, new_string:$c}}')
|
|
21
|
+
STDERR=$(mktemp)
|
|
22
|
+
set +e
|
|
23
|
+
printf '%s' "$payload" | bash "$HOOK" >/dev/null 2>"$STDERR"
|
|
24
|
+
EXIT=$?
|
|
25
|
+
set -e
|
|
26
|
+
STDERR_TEXT=$(cat "$STDERR" 2>/dev/null); rm -f "$STDERR"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
expect_block() {
|
|
30
|
+
local name="$1"
|
|
31
|
+
if [ "$EXIT" = "2" ]; then echo " PASS $name"; PASS=$((PASS+1))
|
|
32
|
+
else echo " FAIL $name (expected exit=2, got exit=$EXIT)"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"; fi
|
|
33
|
+
}
|
|
34
|
+
expect_silent() {
|
|
35
|
+
local name="$1"
|
|
36
|
+
if [ "$EXIT" = "0" ] && [ -z "$STDERR_TEXT" ]; then echo " PASS $name"; PASS=$((PASS+1))
|
|
37
|
+
else echo " FAIL $name (expected silent exit=0, got exit=$EXIT, stderr=${STDERR_TEXT:+non-empty})"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"; fi
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# 1. POSITIVE:病根錨例 h-table-row-${size}(class 名含插值)→ BLOCK
|
|
41
|
+
run_hook "$PROD_TSX" 'const cls = `h-table-row-${size} flex`'
|
|
42
|
+
expect_block "1. h-table-row-\${size} → BLOCK"
|
|
43
|
+
|
|
44
|
+
# 2. POSITIVE:間距 utility gap-${g} → BLOCK
|
|
45
|
+
run_hook "$PROD_TSX" 'const cls = `flex gap-${g}`'
|
|
46
|
+
expect_block "2. gap-\${g} → BLOCK"
|
|
47
|
+
|
|
48
|
+
# 3. NEGATIVE:正解 literal map → silent
|
|
49
|
+
run_hook "$PROD_TSX" "const cls = { sm: 'h-table-row-sm', md: 'h-table-row-md', lg: 'h-table-row-lg' }[size]"
|
|
50
|
+
expect_silent "3. literal class 對照表 → silent"
|
|
51
|
+
|
|
52
|
+
# 4. NEGATIVE:arbitrary value 內插值(是值不是 class 名)→ silent
|
|
53
|
+
run_hook "$PROD_TSX" 'const cls = `h-[calc(100%_-_${offset}px)]`'
|
|
54
|
+
expect_silent "4. h-[calc(\${x})] arbitrary → silent"
|
|
55
|
+
|
|
56
|
+
# 5. NEGATIVE:var() 內插值 → silent
|
|
57
|
+
run_hook "$PROD_TSX" 'const cls = `w-[var(--col-${i})]`'
|
|
58
|
+
expect_silent "5. w-[var(--x-\${i})] → silent"
|
|
59
|
+
|
|
60
|
+
# 6. NEGATIVE:色彩 utility 不在 scope(hook 只鎖尺寸/間距)→ silent
|
|
61
|
+
run_hook "$PROD_TSX" 'const cls = `text-${color}`'
|
|
62
|
+
expect_silent "6. text-\${color}(非尺寸間距)→ silent"
|
|
63
|
+
|
|
64
|
+
# 7. NEGATIVE:escape 註解 → silent
|
|
65
|
+
run_hook "$PROD_TSX" 'const cls = `size-${px}` // @dynamic-tailwind-allow: 傳給 canvas 非 class'
|
|
66
|
+
expect_silent "7. @dynamic-tailwind-allow escape → silent"
|
|
67
|
+
|
|
68
|
+
# 8. NEGATIVE:非 production path(tests/)→ silent
|
|
69
|
+
run_hook "/Users/x/proj/scripts/gen-something.mjs" 'const cls = `h-${x}`'
|
|
70
|
+
expect_silent "8. 非 tsx production path → silent"
|
|
71
|
+
|
|
72
|
+
echo ""
|
|
73
|
+
echo "=== Summary ==="
|
|
74
|
+
echo "Passed: $PASS / $((PASS + FAIL))"
|
|
75
|
+
if [ "$FAIL" -gt 0 ]; then printf "Failed:%b\n" "$FAILED_TESTS"; exit 1; fi
|
|
76
|
+
exit 0
|
|
@@ -182,6 +182,30 @@ expect_not_block "N8. empty content → not blocked"
|
|
|
182
182
|
run_hook_bypass "Write" "$CONSUMER" "content" "$C_3DISTINCT"
|
|
183
183
|
expect_not_block "N9. CLAUDE_BYPASS_ESCAPE_MARKER_AUDIT=1 override → not blocked"
|
|
184
184
|
|
|
185
|
+
# ── R-series:repo 級累計 ratchet(2026-07-08 WM 戰役 R4)──────────────────────
|
|
186
|
+
# 存量 ≥10(apps/** 全 repo)後,只擋「本次 edit 再新增 marker」;無 marker edit 不 brick。
|
|
187
|
+
mkdir -p "$TMP_DIR/apps/work/src"
|
|
188
|
+
for i in 1 2 3 4 5 6; do
|
|
189
|
+
printf '// @ds-misuse-allow: seeded reason %s\n// @layout-space-magic-ok: seeded reason %sb\n' "$i" "$i" \
|
|
190
|
+
> "$TMP_DIR/apps/work/src/seed$i.tsx"
|
|
191
|
+
done
|
|
192
|
+
|
|
193
|
+
# R1. 存量 12 ≥ cap 10 + 本次新增 1 marker → BLOCK(ratchet)
|
|
194
|
+
run_hook "Write" "/repo/apps/work/src/new.tsx" "content" '<div /> // @ds-misuse-allow: one more'
|
|
195
|
+
expect_block "R1. repo 存量 12 ≥ cap + edit 加 marker → blocked (ratchet)" "ESCAPE-MARKER-REPO-RATCHET"
|
|
196
|
+
|
|
197
|
+
# R2. 存量 12 ≥ cap 但本次 edit 無 marker → not blocked(不因存量 brick 無關 edit)
|
|
198
|
+
run_hook "Write" "/repo/apps/work/src/new.tsx" "content" '<div className="flex" />'
|
|
199
|
+
expect_not_block "R2. repo 存量 ≥ cap 但 edit 無 marker → not blocked"
|
|
200
|
+
|
|
201
|
+
# R3. 存量降到 4 < cap + 本次加 1 marker → not blocked
|
|
202
|
+
rm -f "$TMP_DIR/apps/work/src/seed3.tsx" "$TMP_DIR/apps/work/src/seed4.tsx" \
|
|
203
|
+
"$TMP_DIR/apps/work/src/seed5.tsx" "$TMP_DIR/apps/work/src/seed6.tsx"
|
|
204
|
+
run_hook "Write" "/repo/apps/work/src/new.tsx" "content" '<div /> // @ds-misuse-allow: legit case'
|
|
205
|
+
expect_not_block "R3. repo 存量 4 < cap + edit 加 marker → not blocked"
|
|
206
|
+
|
|
207
|
+
rm -rf "$TMP_DIR/apps"
|
|
208
|
+
|
|
185
209
|
echo ""
|
|
186
210
|
echo "=== Summary ==="
|
|
187
211
|
echo "Passed: $PASS / $((PASS + FAIL))"
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# Tests for check_field_family_invariants.sh — merged
|
|
2
|
+
# Tests for check_field_family_invariants.sh — merged sub-rules(A.1-A.4 + A.6)
|
|
3
3
|
#
|
|
4
|
-
# Coverage(每 sub-rule pass + block 各 1 case
|
|
4
|
+
# Coverage(每 sub-rule pass + block 各 1 case):
|
|
5
5
|
# A.1 naked row-mode propagation:pass / block / allowlist
|
|
6
6
|
# A.2 FieldControlGroup wrapper child:pass / block / allowlist
|
|
7
7
|
# A.3 Field state ring SSOT:pass / 3 block(shadow inset / outline / per-control open)
|
|
8
8
|
# A.4 disabled placeholder color:pass / 1 stderr-warn(exit 0)/ allowlist
|
|
9
|
+
# A.6 空值顯示 SSOT(2026-07-08 半形 hyphen):非 owner import EMPTY_DISPLAY block /
|
|
10
|
+
# owner skip / 全形 em dash block / 半形 pass / allowlist
|
|
9
11
|
# non-target:non-tsx skip / SSOT host skip(field-wrapper.tsx)
|
|
10
12
|
|
|
11
13
|
set -u
|
|
@@ -183,6 +185,29 @@ else
|
|
|
183
185
|
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - A.4.3"
|
|
184
186
|
fi
|
|
185
187
|
|
|
188
|
+
echo ""
|
|
189
|
+
echo "=== A.6 空值顯示 SSOT(2026-07-08 半形 hyphen)==="
|
|
190
|
+
|
|
191
|
+
# 17. 非 owner import EMPTY_DISPLAY → BLOCK(應消費 useFieldEmptyDisplay hook 分流)
|
|
192
|
+
run_hook "/r/packages/design-system/src/components/Bad/bad.tsx" "import { EMPTY_DISPLAY } from '@/design-system/components/Field/field-wrapper'"
|
|
193
|
+
expect_exit "A.6.1 非 owner import EMPTY_DISPLAY → BLOCK" 2 "EMPTY_DISPLAY 直引"
|
|
194
|
+
|
|
195
|
+
# 18. owner field-context.ts import EMPTY_DISPLAY → pass(SSOT owner skip)
|
|
196
|
+
run_hook "/r/packages/design-system/src/components/Field/field-context.ts" "import { EMPTY_DISPLAY } from './field-wrapper'"
|
|
197
|
+
expect_exit "A.6.1 owner field-context.ts import → pass" 0
|
|
198
|
+
|
|
199
|
+
# 19. components tsx hardcode 全形 em dash '—' → BLOCK
|
|
200
|
+
run_hook "/r/packages/design-system/src/components/Bad/bad.tsx" "const cls = value ?? '—'"
|
|
201
|
+
expect_exit "A.6.2 hardcode 全形 em dash → BLOCK" 2 "全形 em dash"
|
|
202
|
+
|
|
203
|
+
# 20. 半形 hyphen '-' → pass(非全形,不觸發)
|
|
204
|
+
run_hook "/r/packages/design-system/src/components/Bad/bad.tsx" "const sep = '-'"
|
|
205
|
+
expect_exit "A.6.2 半形 hyphen → pass" 0
|
|
206
|
+
|
|
207
|
+
# 21. allowlist → pass
|
|
208
|
+
run_hook "/r/packages/design-system/src/components/Bad/bad.tsx" "const cls = value ?? '—' // @empty-display-allow: legacy N/A marker"
|
|
209
|
+
expect_exit "A.6 allowlist → pass" 0
|
|
210
|
+
|
|
186
211
|
echo ""
|
|
187
212
|
echo "=== Skip cases ==="
|
|
188
213
|
|
|
@@ -28,7 +28,9 @@ echo "Test 3: fork-user without plugin → inject"
|
|
|
28
28
|
TMP=$(mktemp -d); echo '{"dependencies":{"@qijenchen/design-system":"^1"}}' > "$TMP/package.json"
|
|
29
29
|
# Override HOME/CWD so plugin install detect 一定 fail
|
|
30
30
|
STDOUT=$(cd "$TMP" && HOME=/tmp/no-plugin echo '{"hook_event_name":"SessionStart"}' | bash "$HOOK")
|
|
31
|
-
|
|
31
|
+
# 2026-07-07 修 stale needle:hook 訊息 2026-06 演進為「Fork-user DS 治理鏈未就位」,
|
|
32
|
+
# 舊 needle「Fork-user plugin not installed」永 FAIL(main 既存紅;hook 行為本身正確)。
|
|
33
|
+
if echo "$STDOUT" | grep -q "Fork-user DS 治理鏈未就位"; then
|
|
32
34
|
echo " PASS"; PASS=$((PASS+1))
|
|
33
35
|
else
|
|
34
36
|
echo " FAIL: no inject (output: ${STDOUT:0:200})"; FAIL=$((FAIL+1))
|
|
@@ -47,10 +47,22 @@ expect_pass_silent() {
|
|
|
47
47
|
|
|
48
48
|
expect_warn() {
|
|
49
49
|
local name="$1"; local needle="$2"
|
|
50
|
-
if [ "$EXIT" = "
|
|
50
|
+
if [ "$EXIT" = "2" ] && echo "$STDERR_TEXT" | grep -qF "$needle"; then
|
|
51
51
|
echo " PASS $name"; PASS=$((PASS+1))
|
|
52
52
|
else
|
|
53
|
-
echo " FAIL $name (expected
|
|
53
|
+
echo " FAIL $name (expected exit=2 + needle '$needle', got exit $EXIT)"
|
|
54
|
+
echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
|
|
55
|
+
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
56
|
+
fi
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# #71 soft WARN tier(micro_gap / fraction):exit 0(不 block)+ stderr 含 'soft flag'
|
|
60
|
+
expect_soft_flag() {
|
|
61
|
+
local name="$1"
|
|
62
|
+
if [ "$EXIT" = "0" ] && echo "$STDERR_TEXT" | grep -qF "soft flag"; then
|
|
63
|
+
echo " PASS $name"; PASS=$((PASS+1))
|
|
64
|
+
else
|
|
65
|
+
echo " FAIL $name (expected exit=0 + 'soft flag', got exit=$EXIT)"
|
|
54
66
|
echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
|
|
55
67
|
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
56
68
|
fi
|
|
@@ -101,6 +113,33 @@ const b = "opacity-75"
|
|
|
101
113
|
'
|
|
102
114
|
expect_warn "7. multi opacity-N values → warn" "opacity-25"
|
|
103
115
|
|
|
116
|
+
# ── #71 micro_gap / fraction soft WARN tier(2026-07-11 接線)──────────────────
|
|
117
|
+
FP71="/repo/packages/design-system/src/components/Calendar/calendar.tsx"
|
|
118
|
+
|
|
119
|
+
# 8. gap-0.5(micro gap)→ soft flag(exit 0,非 block)
|
|
120
|
+
run_hook "$FP71" 'const a = <div className="gap-0.5" />'
|
|
121
|
+
expect_soft_flag "8. gap-0.5 micro gap → soft WARN(非 block)"
|
|
122
|
+
|
|
123
|
+
# 9. w-1/3(registry fraction)→ soft flag(exit 0)
|
|
124
|
+
run_hook "$FP71" 'const a = <div className="w-1/3" />'
|
|
125
|
+
expect_soft_flag "9. w-1/3 registry fraction → soft WARN"
|
|
126
|
+
|
|
127
|
+
# 10. w-1/2(合法,不在 registry 14 條)→ silent(不誤殺)
|
|
128
|
+
run_hook "$FP71" 'const a = <div className="w-1/2" />'
|
|
129
|
+
expect_pass_silent "10. w-1/2(合法留白)→ silent 不誤殺"
|
|
130
|
+
|
|
131
|
+
# 11. gap-2(合法)→ silent
|
|
132
|
+
run_hook "$FP71" 'const a = <div className="gap-2" />'
|
|
133
|
+
expect_pass_silent "11. gap-2(合法)→ silent"
|
|
134
|
+
|
|
135
|
+
# 12. 硬 violation + gap-0.5 → exit 2(hard block 不被 soft tier 弱化)
|
|
136
|
+
run_hook "$FP71" 'const a = <div className="text-muted-foreground gap-0.5" />'
|
|
137
|
+
expect_warn "12. 硬 violation + gap-0.5 → exit 2 block" "shadcn alias"
|
|
138
|
+
|
|
139
|
+
# 13. gap-0.5 + @token-registry-ok escape → silent
|
|
140
|
+
run_hook "$FP71" 'const a = <div className="gap-0.5" /> // @token-registry-ok: skeleton bone'
|
|
141
|
+
expect_pass_silent "13. gap-0.5 + escape → silent"
|
|
142
|
+
|
|
104
143
|
echo ""
|
|
105
144
|
echo "=== Summary ==="
|
|
106
145
|
echo "Passed: $PASS / $((PASS + FAIL))"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# test_check_ssot_header_declaration.sh — 新建 production tsx 必帶「── 消費的 SSOT ──」段
|
|
3
|
+
# (2026-07-07 治理進化方向 3 洞 a;P0 exit 2;ratchet:只攔 Write 新檔)
|
|
4
|
+
|
|
5
|
+
HOOK="$(cd "$(dirname "$0")/.." && pwd)/check_ssot_header_declaration.sh"
|
|
6
|
+
if [ ! -f "$HOOK" ]; then echo "FATAL: hook not found: $HOOK"; exit 1; fi
|
|
7
|
+
|
|
8
|
+
PASS=0; FAIL=0; FAILED_TESTS=""
|
|
9
|
+
|
|
10
|
+
run_hook() {
|
|
11
|
+
local file_path="$1"; local content="$2"; local tool="${3:-Write}"
|
|
12
|
+
STDERR_TEXT=$(jq -n --arg t "$tool" --arg f "$file_path" --arg c "$content" \
|
|
13
|
+
'{tool_name:$t, tool_input:{file_path:$f, content:$c}}' | bash "$HOOK" 2>&1 >/dev/null)
|
|
14
|
+
EXIT=$?
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
expect_block() {
|
|
18
|
+
local name="$1"
|
|
19
|
+
if [ "$EXIT" = "2" ] && echo "$STDERR_TEXT" | grep -qF "消費的 SSOT"; then
|
|
20
|
+
echo " PASS $name"; PASS=$((PASS+1))
|
|
21
|
+
else
|
|
22
|
+
echo " FAIL $name (expected exit=2, got $EXIT)"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
23
|
+
fi
|
|
24
|
+
}
|
|
25
|
+
expect_silent() {
|
|
26
|
+
local name="$1"
|
|
27
|
+
if [ "$EXIT" = "0" ]; then
|
|
28
|
+
echo " PASS $name"; PASS=$((PASS+1))
|
|
29
|
+
else
|
|
30
|
+
echo " FAIL $name (expected exit=0, got $EXIT)"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
31
|
+
fi
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
echo "=== check_ssot_header_declaration tests ==="
|
|
35
|
+
|
|
36
|
+
# 1. 新元件 tsx 無宣告段 → BLOCK
|
|
37
|
+
run_hook "/repo/packages/design-system/src/components/NewThing/new-thing.tsx" 'import * as React from "react"
|
|
38
|
+
export const NewThing = () => <div className="flex border rounded-md px-2" />'
|
|
39
|
+
expect_block "1. 新元件 tsx 無 SSOT 段 → BLOCK"
|
|
40
|
+
|
|
41
|
+
# 2. 有宣告段 → pass
|
|
42
|
+
run_hook "/repo/packages/design-system/src/components/NewThing/new-thing.tsx" '// ── 消費的 SSOT ──
|
|
43
|
+
// - Button(pill layout)/ --layout-space-tight
|
|
44
|
+
import * as React from "react"'
|
|
45
|
+
expect_silent "2. 有「── 消費的 SSOT ──」段 → pass"
|
|
46
|
+
|
|
47
|
+
# 3. escape marker → pass
|
|
48
|
+
run_hook "/repo/packages/design-system/src/components/NewThing/util.tsx" '// @ssot-header-exempt: 純型別 utility,零視覺
|
|
49
|
+
export type X = string'
|
|
50
|
+
expect_silent "3. @ssot-header-exempt escape → pass"
|
|
51
|
+
|
|
52
|
+
# 4. stories 檔 → 豁免
|
|
53
|
+
run_hook "/repo/packages/design-system/src/components/NewThing/new-thing.stories.tsx" 'export default {}'
|
|
54
|
+
expect_silent "4. stories.tsx 豁免"
|
|
55
|
+
|
|
56
|
+
# 5. 非 DS production 路徑 → 豁免
|
|
57
|
+
run_hook "/repo/apps/template/src/App.tsx" 'export const App = () => <div className="flex border px-2" />'
|
|
58
|
+
expect_silent "5. apps/ 路徑豁免"
|
|
59
|
+
|
|
60
|
+
# 6. Edit 工具(存量檔)→ 豁免(ratchet)
|
|
61
|
+
run_hook "/repo/packages/design-system/src/components/Button/button.tsx" 'whatever' "Edit"
|
|
62
|
+
expect_silent "6. Edit(存量 ratchet)豁免"
|
|
63
|
+
|
|
64
|
+
# 7. patterns/ 新檔無宣告 → BLOCK
|
|
65
|
+
run_hook "/repo/packages/design-system/src/patterns/new-pattern/new-pattern.tsx" 'export const P = () => <div className="absolute shadow px-2" />'
|
|
66
|
+
expect_block "7. patterns/ 新檔無 SSOT 段 → BLOCK"
|
|
67
|
+
|
|
68
|
+
echo ""
|
|
69
|
+
echo "=== Summary ==="
|
|
70
|
+
echo "Passed: $PASS / $((PASS+FAIL))"
|
|
71
|
+
if [ "$FAIL" -gt 0 ]; then printf "Failed:%b\n" "$FAILED_TESTS"; exit 1; fi
|
|
72
|
+
exit 0
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# test_check_tabs_content_chrome_body_double_gap.sh — overlay-body layout-space 哨測試
|
|
3
|
+
# (2026-07-10 補 hook-test-coverage debt;hook 2026-07-01 建,anchor = 專案設定 Dialog 雙 tight)
|
|
4
|
+
# 注意:本 hook 是 PostToolUse「讀完整檔」型(防 partial-edit 盲區)→ 測試必寫真實 temp 檔,
|
|
5
|
+
# 且路徑必須匹配 scope regex(packages/design-system/src/ 或 /apps/)。
|
|
6
|
+
set -uo pipefail
|
|
7
|
+
cd "$(dirname "$0")/../../.."
|
|
8
|
+
HOOK=".claude/hooks/check_tabs_content_chrome_body_double_gap.sh"
|
|
9
|
+
PASS=0; FAIL=0; FAILED_TESTS=""
|
|
10
|
+
|
|
11
|
+
TMP_DIR=$(mktemp -d)
|
|
12
|
+
trap 'rm -rf "$TMP_DIR"' EXIT
|
|
13
|
+
export CLAUDE_PROJECT_DIR="$TMP_DIR"
|
|
14
|
+
mkdir -p "$TMP_DIR/.claude/logs"
|
|
15
|
+
|
|
16
|
+
# scope 內的真實 temp 檔路徑(hook 讀 disk)
|
|
17
|
+
DS_DIR="$TMP_DIR/packages/design-system/src/components/Dialog"
|
|
18
|
+
mkdir -p "$DS_DIR"
|
|
19
|
+
|
|
20
|
+
run_hook_file() {
|
|
21
|
+
local file_path="$1"; local content="$2"
|
|
22
|
+
mkdir -p "$(dirname "$file_path")"
|
|
23
|
+
printf '%s' "$content" > "$file_path"
|
|
24
|
+
local payload
|
|
25
|
+
payload=$(jq -n --arg fp "$file_path" --arg c "$content" \
|
|
26
|
+
'{tool_name:"Edit", tool_input:{file_path:$fp, new_string:$c}}')
|
|
27
|
+
STDERR=$(mktemp)
|
|
28
|
+
set +e
|
|
29
|
+
printf '%s' "$payload" | bash "$HOOK" >/dev/null 2>"$STDERR"
|
|
30
|
+
EXIT=$?
|
|
31
|
+
set -e
|
|
32
|
+
STDERR_TEXT=$(cat "$STDERR" 2>/dev/null); rm -f "$STDERR"
|
|
33
|
+
rm -f "$file_path"
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
expect_block() {
|
|
37
|
+
local name="$1"
|
|
38
|
+
if [ "$EXIT" = "2" ]; then echo " PASS $name"; PASS=$((PASS+1))
|
|
39
|
+
else echo " FAIL $name (expected exit=2, got exit=$EXIT)"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"; fi
|
|
40
|
+
}
|
|
41
|
+
expect_silent() {
|
|
42
|
+
local name="$1"
|
|
43
|
+
if [ "$EXIT" = "0" ] && [ -z "$STDERR_TEXT" ]; then echo " PASS $name"; PASS=$((PASS+1))
|
|
44
|
+
else echo " FAIL $name (expected silent exit=0, got exit=$EXIT, stderr=${STDERR_TEXT:+non-empty})"; FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"; fi
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# 1. POSITIVE(Check 1 錨例):chrome body 內 TabsContent 無 mt-0 → 雙重 gap → BLOCK
|
|
48
|
+
run_hook_file "$DS_DIR/case1.stories.tsx" '<DialogBody><Tabs value={t}><TabsContent value="a"><p>內容</p></TabsContent></Tabs></DialogBody>'
|
|
49
|
+
expect_block "1. DialogBody 內 TabsContent 無 mt-0 → BLOCK"
|
|
50
|
+
|
|
51
|
+
# 2. NEGATIVE:TabsContent 帶 mt-0(ownership 轉移給 body)→ silent
|
|
52
|
+
run_hook_file "$DS_DIR/case2.stories.tsx" '<DialogBody><Tabs value={t}><TabsContent value="a" className="mt-0"><p>內容</p></TabsContent></Tabs></DialogBody>'
|
|
53
|
+
expect_silent "2. TabsContent className=mt-0 → silent"
|
|
54
|
+
|
|
55
|
+
# 3. NEGATIVE:TabsContent 不在 chrome body 內(頁面級 Tabs)→ silent
|
|
56
|
+
run_hook_file "$DS_DIR/case3.stories.tsx" '<Tabs value={t}><TabsList>…</TabsList><TabsContent value="a"><p>內容</p></TabsContent></Tabs>'
|
|
57
|
+
expect_silent "3. 頁面級 Tabs(無 chrome body)→ silent"
|
|
58
|
+
|
|
59
|
+
# 4. POSITIVE(Check 3 root 簽名):TabsList 手塞 DialogBody 同檔且無 tabsSlot → BLOCK
|
|
60
|
+
run_hook_file "$DS_DIR/case4.stories.tsx" '<DialogBody><TabsList size="sm"><TabsTrigger value="a">A</TabsTrigger></TabsList><TabsContent value="a" className="mt-0">x</TabsContent></DialogBody>'
|
|
61
|
+
expect_block "4. TabsList 手塞 chrome body 無 tabsSlot → BLOCK(root)"
|
|
62
|
+
|
|
63
|
+
# 5. NEGATIVE:escape 註解 → silent
|
|
64
|
+
run_hook_file "$DS_DIR/case5.stories.tsx" '{/* @tabs-content-gap-ok: 內容層分頁非 dialog chrome */}
|
|
65
|
+
<DialogBody><Tabs value={t}><TabsContent value="a">x</TabsContent></Tabs></DialogBody>'
|
|
66
|
+
expect_silent "5. @tabs-content-gap-ok escape → silent"
|
|
67
|
+
|
|
68
|
+
# 6. NEGATIVE:scope 外路徑(非 DS-src / apps)→ silent
|
|
69
|
+
run_hook_file "$TMP_DIR/docs/example.tsx" '<DialogBody><TabsContent value="a">x</TabsContent></DialogBody>'
|
|
70
|
+
expect_silent "6. scope 外路徑 → silent"
|
|
71
|
+
|
|
72
|
+
echo ""
|
|
73
|
+
echo "=== Summary ==="
|
|
74
|
+
echo "Passed: $PASS / $((PASS + FAIL))"
|
|
75
|
+
if [ "$FAIL" -gt 0 ]; then printf "Failed:%b\n" "$FAILED_TESTS"; exit 1; fi
|
|
76
|
+
exit 0
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
|
|
46
46
|
| 真缺項 | 補的形式 | Commit |
|
|
47
47
|
|---|---|---|
|
|
48
|
-
| #13 i18n 硬寫字串 |
|
|
48
|
+
| #13 i18n 硬寫字串 | `post_edit_dispatcher.sh → lib/_hardcoded_strings.sh` PostToolUse flag(2026-05-13 由獨立 hook `check_hardcoded_strings.sh` folded 進 dispatcher lib),flag DS primitive tsx(非 stories)CJK ≥ 3 chars / 英文 sentence-case label;支援 `// i18n-allow: {rationale}` 白名單 | 本次 session |
|
|
49
49
|
| #3 Controlled / Uncontrolled + #12 Form dual-mode | `design-system-audit` Dim 26(新 Group J)— 掃 form + overlay 元件 value/defaultValue / open/defaultOpen / checked/defaultChecked 的 pair 完整性;V1-V4 violation types | 本次 session |
|
|
50
50
|
| #23 edge case(null / empty / rapid / success) | `/ux-audit` Phase 5 從 3 態 → 5 態 + null-safety + rapid-interaction + edge case corollary | 本次 session |
|
|
51
51
|
|