@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
|
@@ -135,6 +135,33 @@ $(echo "$MARKERS_FOUND" | sed 's/^/ /')
|
|
|
135
135
|
EOF
|
|
136
136
|
exit 2
|
|
137
137
|
fi
|
|
138
|
+
|
|
139
|
+
# ── Repo 級累計 ratchet(2026-07-08 WM 戰役 R4)──────────────────────────────
|
|
140
|
+
# per-file gate(≥3 distinct/≥5 total)可被「每檔 1-2 個、散多檔」繞過 → repo 級 ceiling。
|
|
141
|
+
# Ratchet 精神(Polaris stylelint migrator):存量 ≥ cap 後只擋「本次 edit 再新增 marker」,
|
|
142
|
+
# 不因存量 brick 無關 edit(本次內容無 marker → 直接放行)。
|
|
143
|
+
EDIT_ADDS_MARKER=$(echo "$CONTENT" | grep -cE "$MARKER_RE" || true)
|
|
144
|
+
if [ "${EDIT_ADDS_MARKER:-0}" -gt 0 ]; then
|
|
145
|
+
APPS_ROOT="${CLAUDE_PROJECT_DIR:-.}/apps"
|
|
146
|
+
REPO_CAP=10
|
|
147
|
+
if [ -d "$APPS_ROOT" ]; then
|
|
148
|
+
REPO_TOTAL=$(grep -rhoE "$MARKER_RE" "$APPS_ROOT" --include='*.tsx' --include='*.ts' 2>/dev/null | wc -l | tr -d ' ')
|
|
149
|
+
if [ "${REPO_TOTAL:-0}" -ge "$REPO_CAP" ]; then
|
|
150
|
+
cat >&2 << EOF
|
|
151
|
+
🚨 ESCAPE-MARKER-REPO-RATCHET BLOCKER(P0,2026-07-08 WM 戰役 R4)
|
|
152
|
+
|
|
153
|
+
apps/** 全 repo escape marker 存量已 $REPO_TOTAL 個(ceiling $REPO_CAP),本次 edit 又要新增 $EDIT_ADDS_MARKER 個。
|
|
154
|
+
每檔 1-2 個散多檔 = 繞 per-file gate 的同型濫用 — repo 級 ratchet 攔。
|
|
155
|
+
|
|
156
|
+
修法 2 選 1:
|
|
157
|
+
(a) 先清既有 escape 的根因(重構走 DS canonical),存量 < $REPO_CAP 後再加真必要的
|
|
158
|
+
(b) Override env(極罕見,commit msg 必記 rationale):
|
|
159
|
+
CLAUDE_BYPASS_ESCAPE_MARKER_AUDIT=1
|
|
160
|
+
EOF
|
|
161
|
+
exit 2
|
|
162
|
+
fi
|
|
163
|
+
fi
|
|
164
|
+
fi
|
|
138
165
|
fi
|
|
139
166
|
|
|
140
167
|
exit 0
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# Field family unified invariant hook(2026-05-08 cluster A consolidation)
|
|
3
3
|
#
|
|
4
|
-
# Merges PreToolUse hooks(原各檔已 retire,合併入此)— 共
|
|
4
|
+
# Merges PreToolUse hooks(原各檔已 retire,合併入此)— 共 6 條 sub-rules:
|
|
5
5
|
# A.1 naked row-mode propagation(原 check_naked_row_mode_propagation,P0 BLOCKER)
|
|
6
6
|
# A.2 FieldControlGroup wrapper direct child(原 check_field_control_group_direct_child,P1 WARN)
|
|
7
7
|
# A.3 Field state ring SSOT(原 check_field_state_token_consume 3 sub-rules,P0 BLOCKER)
|
|
8
8
|
# A.4 disabled placeholder color(原 check_disabled_placeholder_color,P1 stderr only)
|
|
9
9
|
# A.5 _Group child fieldCtx.id 隔離(2026-05-31 折入,M4 AR34 regression detector,P0 BLOCKER)
|
|
10
|
+
# A.6 空值顯示 SSOT(2026-07-08 user 拍板半形 hyphen,P0 BLOCKER)
|
|
10
11
|
#
|
|
11
12
|
# Why merge:皆 Field 家族 invariant,共用 INPUT parsing + Edit/Write filter pattern,
|
|
12
13
|
# 分散在 4 個 hook 是「散裝 SSOT」(M17 + Anthropic ≤ 15 hook best practice 違反)。
|
|
@@ -19,6 +20,7 @@
|
|
|
19
20
|
# A.3: `// @field-state-ring-allow: <reason>`
|
|
20
21
|
# A.4: `// @disabled-color-allow: <reason>`
|
|
21
22
|
# A.5: `// @group-fieldctx-allow: <reason>`
|
|
23
|
+
# A.6: `// @empty-display-allow: <reason>`
|
|
22
24
|
|
|
23
25
|
source "$(dirname "$0")/_log-fire.sh" 2>/dev/null && log_hook_fire
|
|
24
26
|
|
|
@@ -247,4 +249,62 @@ EOF
|
|
|
247
249
|
;;
|
|
248
250
|
esac
|
|
249
251
|
|
|
252
|
+
# ── A.6 空值顯示 SSOT(P0 BLOCKER,2026-07-08 user 拍板半形 hyphen)────────────────
|
|
253
|
+
# user verbatim「我從頭到尾哪裡有說要用全形的」+ 五情境空值框架。SSOT:符號常數 =
|
|
254
|
+
# field-wrapper.tsx `EMPTY_DISPLAY = '-'`(U+002D 半形);分流 hook = field-context.ts
|
|
255
|
+
# `useFieldEmptyDisplay()`。禁 2 shape:
|
|
256
|
+
# A.6.1 非 owner 檔直接 import `EMPTY_DISPLAY` 常數(應消費 hook 分流,否則 table-cell
|
|
257
|
+
# editable→'' 分流會漏);
|
|
258
|
+
# A.6.2 components/ tsx display 路徑 hardcode 全形 em dash `'—'`/`"—"`(U+2014)字面。
|
|
259
|
+
# M7 broad-vs-narrow:spec wording 廣(「禁 hardcode 空值符號」);hook 取「quoted em dash 字面」
|
|
260
|
+
# 高信號 subset + owner skip + comment 剝離 + `@empty-display-allow` escape,零誤判導向。
|
|
261
|
+
if ! echo "$NEW_CONTENT" | grep -q '@empty-display-allow'; then
|
|
262
|
+
# A.6.1 非 owner 檔 import EMPTY_DISPLAY 常數(剝離註解行)
|
|
263
|
+
case "$FILE_PATH" in
|
|
264
|
+
*/field-context.ts|*/field-wrapper.tsx) ;; # SSOT owner(定義 + 分流 hook)skip
|
|
265
|
+
*)
|
|
266
|
+
A61_CONTENT=$(echo "$NEW_CONTENT" | grep -vE '^[[:space:]]*(//|\*|/\*)')
|
|
267
|
+
if printf '%s' "$A61_CONTENT" | grep -E "import.*EMPTY_DISPLAY|EMPTY_DISPLAY.*from" >/dev/null; then
|
|
268
|
+
cat >&2 <<EOF
|
|
269
|
+
|
|
270
|
+
┄┄┄ A.6.1 check_field_family_invariants — EMPTY_DISPLAY 直引 BLOCKER ┄┄┄
|
|
271
|
+
|
|
272
|
+
[P0] ${FILE_PATH}
|
|
273
|
+
偵測到直接 import \`EMPTY_DISPLAY\` 常數(非 field-context.ts owner)。
|
|
274
|
+
空值顯示必經 \`useFieldEmptyDisplay()\` hook 分流(table-cell 可編輯→空白 / 其餘→半形 '-'),
|
|
275
|
+
直引常數會漏 surface × editable 分流。
|
|
276
|
+
|
|
277
|
+
修法:import { useFieldEmptyDisplay } from '@/design-system/components/Field/field-context'
|
|
278
|
+
const emptyDisplay = useFieldEmptyDisplay()
|
|
279
|
+
例外:行尾 \`// @empty-display-allow: <reason>\`
|
|
280
|
+
|
|
281
|
+
EOF
|
|
282
|
+
record_worst 2
|
|
283
|
+
fi
|
|
284
|
+
;;
|
|
285
|
+
esac
|
|
286
|
+
# A.6.2 components/ tsx hardcode 全形 em dash 空值字面(剝離註解行 + owner/story skip)
|
|
287
|
+
case "$FILE_PATH" in
|
|
288
|
+
*.stories.tsx|*/field-context.ts|*/field-wrapper.tsx) ;; # doc N/A marker + SSOT owner skip
|
|
289
|
+
*components/*.tsx)
|
|
290
|
+
A62_CONTENT=$(echo "$NEW_CONTENT" | grep -vE '^[[:space:]]*(//|\*|/\*)')
|
|
291
|
+
if printf '%s' "$A62_CONTENT" | grep -E "['\"]—['\"]" >/dev/null; then
|
|
292
|
+
cat >&2 <<EOF
|
|
293
|
+
|
|
294
|
+
┄┄┄ A.6.2 check_field_family_invariants — 全形 em dash 空值 BLOCKER ┄┄┄
|
|
295
|
+
|
|
296
|
+
[P0] ${FILE_PATH}
|
|
297
|
+
偵測到 components/ 實作檔 hardcode 全形 em dash \`'—'\`(U+2014)字面。
|
|
298
|
+
user 2026-07-08 拍板:空值符號 = **半形 hyphen '-'(U+002D)**,禁全形。
|
|
299
|
+
|
|
300
|
+
修法:空值一律 \`{value ?? emptyDisplay}\`(emptyDisplay = useFieldEmptyDisplay()),不 hardcode 符號。
|
|
301
|
+
例外:行尾 \`// @empty-display-allow: <reason>\`
|
|
302
|
+
|
|
303
|
+
EOF
|
|
304
|
+
record_worst 2
|
|
305
|
+
fi
|
|
306
|
+
;;
|
|
307
|
+
esac
|
|
308
|
+
fi
|
|
309
|
+
|
|
250
310
|
exit $WORST
|
|
@@ -43,7 +43,31 @@ ESCAPE_MARKER='@layout-space-magic-ok:'
|
|
|
43
43
|
|
|
44
44
|
# Detect magic spacing classes (Tailwind class strings only — NOT JSX props like size={24})
|
|
45
45
|
# Match per line so we can check per-line escape comments
|
|
46
|
-
|
|
46
|
+
# 2026-07-08 WM 戰役 R4 擴 scope(broad-vs-narrow gap 實證修補):
|
|
47
|
+
# (a) logical properties ps-/pe-/ms-/me-(WM 6 筆 ps-4 漏網實證)
|
|
48
|
+
# (b) arbitrary bracket 固定 px:gap-[7px] / p-[13px] 類(spacing 家族)
|
|
49
|
+
# (c) 固定寬度 w-[Npx](WM w-[640px] 丟失 min() viewport clamp 實證;w-[min(...)]/var()/% 不攔)
|
|
50
|
+
# (d) grid-template 固定 px 欄寬:grid-cols-[...Npx...](WM mini-table 88px/72px 黏死實證)
|
|
51
|
+
MAGIC_LINES=$(echo "$NEW_CONTENT" | grep -nE '\b(p|px|py|pt|pb|pl|pr|ps|pe|gap|space-x|space-y|m|mx|my|mt|mb|ml|mr|ms|me)-(0\.5|[1-9][0-9]?(\.[0-9])?)\b|\b(p|px|py|pt|pb|pl|pr|ps|pe|gap|m|mx|my|mt|mb|ml|mr|ms|me)-\[[0-9]+(\.[0-9]+)?px\]|\bw-\[[0-9]+(\.[0-9]+)?px\]|\bgrid-(cols|rows)-\[[^]]*[0-9]+px[^]]*\]')
|
|
52
|
+
|
|
53
|
+
# ── 幻覺 token 攔截(2026-07-08 WM 戰役:app 自創 var(--layout-space-distant) → CSS 未定義
|
|
54
|
+
# silent 解析 0 → 區塊全黏死,PDF「全部擠在一起」根因之一。白名單 = loose|tight|bottom
|
|
55
|
+
# (layoutSpace.css SSOT 僅此三顆;新增 tier 走 DS token 流程,不在 consumer 端發明)──
|
|
56
|
+
PHANTOM=$(echo "$NEW_CONTENT" | grep -nE 'var\(--layout-space-[a-z-]+\)' | grep -vE 'var\(--layout-space-(loose|tight|bottom)\)' || true)
|
|
57
|
+
if [ -n "$PHANTOM" ]; then
|
|
58
|
+
cat >&2 <<EOF_PH
|
|
59
|
+
🚨 [P0 BLOCKER] 幻覺 layout-space token(CSS 未定義 = silent 0 = 佈局黏死):
|
|
60
|
+
$PHANTOM
|
|
61
|
+
→ 白名單只有 --layout-space-{loose,tight,bottom}(layoutSpace.css SSOT)。
|
|
62
|
+
要更大一級間距 → 用 loose;真需新 tier → 走 DS token 新增流程(layoutSpace.spec),禁 consumer 端自創。
|
|
63
|
+
Anchor:2026-07-08 WM --layout-space-distant ×4 處,整個 detail modal 區塊黏死。
|
|
64
|
+
EOF_PH
|
|
65
|
+
exit 2
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# 2026-07-10 批次 A:divider 幾何 canonical(h-6 mx-1 / h-5 mx-1,action-bar.spec.md「分隔線幾何」)
|
|
69
|
+
# 是**正解**,不該被 magic-number 攔(原本懲罰 canonical 修法、放行違規 = 治理自我打架)。
|
|
70
|
+
MAGIC_LINES=$(echo "$MAGIC_LINES" | grep -vE '(Separator|ButtonDivider)' || true)
|
|
47
71
|
|
|
48
72
|
if [ -z "$MAGIC_LINES" ]; then
|
|
49
73
|
exit 0
|
|
@@ -82,9 +106,9 @@ $(echo -e "$UNJUSTIFIED" | sed 's/^/ /' | head -10)
|
|
|
82
106
|
per app-shell.spec.md L205-219 + layoutSpace.spec.md SSOT:consumer content 必遵循
|
|
83
107
|
layoutSpace 6 條規則 + 親疏 3 級,**禁** 硬寫 Tailwind magic numbers。改用:
|
|
84
108
|
p-[var(--layout-space-loose)] /* 16px 規則 1A/1B chrome / wrap */
|
|
85
|
-
|
|
86
|
-
gap-[var(--layout-space-
|
|
87
|
-
|
|
109
|
+
gap-[var(--layout-space-tight)] /* 12px 規則 3 親 gap(跨範疇相關) */
|
|
110
|
+
gap-[var(--layout-space-loose)] /* 16px 規則 3 疏 gap(跨範疇 parallel;lg 密度自動 24px) */
|
|
111
|
+
(token 全集 = loose/tight/bottom,無其他級 — 自創 --layout-space-distant 類 = 幻覺 token,本 hook 會攔)
|
|
88
112
|
|
|
89
113
|
修法 2 選 1:
|
|
90
114
|
(a) 改 token:換成 var(--layout-space-N) N∈{loose,tight} family per 6 規則 + 親疏 3 級
|
|
@@ -136,7 +136,7 @@ case "$FILE_PATH" in
|
|
|
136
136
|
*/components/Tag/*|*/components/Avatar/*|*/components/Chart/*|*/tokens/*) ;; # codified primitive-consumer skip
|
|
137
137
|
*)
|
|
138
138
|
if ! echo "$NEW_CONTENT" | grep -q 'primitive-color-allow-blanket'; then
|
|
139
|
-
VIOLATIONS_D3=$(printf '%s' "$NEW_CONTENT" | grep -nE 'var\(--color-[a-z]
|
|
139
|
+
VIOLATIONS_D3=$(printf '%s' "$NEW_CONTENT" | grep -nE 'var\(--color-[a-z][a-z-]*-[0-9]{1,2}(-opaque)?\)' | grep -v 'primitive-color-allow' || true)
|
|
140
140
|
if [ -n "$VIOLATIONS_D3" ]; then
|
|
141
141
|
cat >&2 <<EOF
|
|
142
142
|
|
|
@@ -46,6 +46,10 @@ esac
|
|
|
46
46
|
|
|
47
47
|
NEW_CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content // .tool_input.new_string // ""')
|
|
48
48
|
[ -z "$NEW_CONTENT" ] && exit 0
|
|
49
|
+
# Per-line escape(2026-07-07 方向 2 升 P0 配套):行內含 `@token-registry-ok: <rationale>` 豁免該行
|
|
50
|
+
NEW_CONTENT=$(printf '%s
|
|
51
|
+
' "$NEW_CONTENT" | grep -v '@token-registry-ok:' || true)
|
|
52
|
+
[ -z "$NEW_CONTENT" ] && exit 0
|
|
49
53
|
|
|
50
54
|
# Resolve registry path(absolute via $CLAUDE_PROJECT_DIR or relative fallback)
|
|
51
55
|
REGISTRY="${CLAUDE_PROJECT_DIR:-}/packages/design-system/src/tokens/utility-registry.json"
|
|
@@ -131,6 +135,24 @@ if [ -n "$HITS_PRIMITIVE" ]; then
|
|
|
131
135
|
VIOLATIONS="${VIOLATIONS}\n [primitive color as utility] $(echo "$HITS_PRIMITIVE" | tr '\n' ' ')"
|
|
132
136
|
fi
|
|
133
137
|
|
|
138
|
+
# 10) 幻覺 semantic state 尾綴(2026-07-10 批次 A C1:WM hover:bg-neutral-hovered ×3 檔 silent no-op 實證。
|
|
139
|
+
# 真尾綴只有 -hover/-active/-selected(+ selected-hover/selected-active);過去式/-pressed 全幻覺,
|
|
140
|
+
# Tailwind 靜默不生成 → hover 無效果、build 不報錯)
|
|
141
|
+
HITS_PHANTOM_STATE=$(echo "$NEW_CONTENT" | grep -oE "\b(hover:|active:|focus:)?(bg|text|border|ring)-[a-z][a-z-]*-(hovered|actived|focussed|pressed)\b" | sort -u || true)
|
|
142
|
+
if [ -n "$HITS_PHANTOM_STATE" ]; then
|
|
143
|
+
VIOLATIONS="${VIOLATIONS}\n [phantom state suffix(silent no-op)] $(echo "$HITS_PHANTOM_STATE" | tr '\n' ' ')"
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
# 11) micro gap(<4px)+ registry fraction width(#71 2026-07-11 接線)——
|
|
147
|
+
# registry micro_gap / fraction 的 rationale 明寫「flag for human review」(非硬禁)→ 走
|
|
148
|
+
# SOFT WARN 非 block(避免誤殺 Calendar/Chart/FileViewer/Carousel 等 4 個既有合法 micro-gap 用途)。
|
|
149
|
+
# fraction 用 registry 明列 14 條(w-1/3.. 不含 w-1/2 = 合法留白),避免廣捕 w-N/M 誤殺。
|
|
150
|
+
HITS_MICROGAP=$(echo "$NEW_CONTENT" | grep -oE "\bgap-(px|0\.5|1\.5)\b" | sort -u || true)
|
|
151
|
+
HITS_FRACTION=$(echo "$NEW_CONTENT" | grep -oE "\bw-(1/3|2/3|1/4|3/4|1/5|2/5|3/5|4/5|1/6|5/6|1/12|5/12|7/12|11/12)\b" | sort -u || true)
|
|
152
|
+
SOFT_NOTES=""
|
|
153
|
+
[ -n "$HITS_MICROGAP" ] && SOFT_NOTES="${SOFT_NOTES}\n [micro gap <4px] $(echo "$HITS_MICROGAP" | tr '\n' ' ')"
|
|
154
|
+
[ -n "$HITS_FRACTION" ] && SOFT_NOTES="${SOFT_NOTES}\n [fraction width] $(echo "$HITS_FRACTION" | tr '\n' ' ')"
|
|
155
|
+
|
|
134
156
|
if [ -n "$VIOLATIONS" ]; then
|
|
135
157
|
cat >&2 <<'EOF_HEAD'
|
|
136
158
|
|
|
@@ -152,7 +174,21 @@ EOF_HEAD
|
|
|
152
174
|
bg-neutral-N → semantic utility(bg-surface 等)或 bg-[var(--color-neutral-N)]
|
|
153
175
|
|
|
154
176
|
詳 utility-registry.json `_meta.spec_sources` + M23「DS 內既有 canonical 優先」。
|
|
177
|
+
Per-line escape:行尾註解 `@token-registry-ok: <rationale>`(audit 可追)。
|
|
155
178
|
EOF_BODY
|
|
179
|
+
# P0 BLOCKER(2026-07-07 治理進化方向 2:對齊 user 2026-05-27「SSOT canonical 必 P0」doctrine;
|
|
180
|
+
# 檔級豁免(anatomy/principles stories / token 自家)+ 行級 escape 已備,升級不增誤殺)
|
|
181
|
+
# micro-gap/fraction soft note 附在硬 block 訊息尾(一起讓 AI 看到,但不影響 exit code 判定)
|
|
182
|
+
[ -n "$SOFT_NOTES" ] && { echo "" >&2; echo " (另有 soft flag,非 block 原因):" >&2; echo -e "$SOFT_NOTES" >&2; }
|
|
183
|
+
exit 2
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
# 只有 micro-gap / fraction soft note(無硬 violation)→ WARN 非 block(registry rationale「flag for human review」)
|
|
187
|
+
if [ -n "$SOFT_NOTES" ]; then
|
|
188
|
+
echo "" >&2
|
|
189
|
+
echo "⚠️ Dim 47 soft flag(registry micro_gap / fraction「flag for human review」— 非 block,#71 接線):" >&2
|
|
190
|
+
echo -e "$SOFT_NOTES" >&2
|
|
191
|
+
echo " <4px gap / registry fraction width 常違反 item-anatomy slot 幾何 / layout SSOT → 人工 review。合理則行尾 @token-registry-ok: <rationale>。" >&2
|
|
156
192
|
fi
|
|
157
193
|
|
|
158
194
|
exit 0
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
# `getAttribute('data-state')` / `class.includes('items-start')` attribute-existence
|
|
7
7
|
# = false-positive trap(DOM-structure-pass ≠ visual-pass)。
|
|
8
8
|
#
|
|
9
|
-
# Mechanical rule:scripts/visual-audit
|
|
9
|
+
# Mechanical rule:scripts/visual-audit*.mjs(or *.js;含 canonical scripts/visual-audit.mjs,
|
|
10
|
+
# 舊 visual-audit-<target>.mjs 家族已於 2026-05-30 a2360e99 整批 retire)若有 `getAttribute(` 但沒 paired
|
|
10
11
|
# `getBoundingClientRect(` 或 `offsetTop/.offsetHeight` 量化 measurement → warn。
|
|
11
12
|
#
|
|
12
13
|
# 對齊 Material X-DataGrid visual regression / AG Grid playwright pixel snapshot canonical。
|
|
@@ -21,7 +22,7 @@ EVENT=$(echo "$INPUT" | jq -r '.hook_event_name // ""' 2>/dev/null)
|
|
|
21
22
|
|
|
22
23
|
case "$TOOL" in Edit|Write|MultiEdit) ;; *) exit 0 ;; esac
|
|
23
24
|
case "$FILE_PATH" in
|
|
24
|
-
*/scripts/visual-audit
|
|
25
|
+
*/scripts/visual-audit*.mjs|*/scripts/visual-audit*.js) ;;
|
|
25
26
|
*) exit 0 ;;
|
|
26
27
|
esac
|
|
27
28
|
[ "$EVENT" != "PostToolUse" ] && exit 0
|
|
@@ -63,7 +63,10 @@ SSOT_COUNT=$(echo "$SSOT_DIFF" | wc -l | tr -d ' ')
|
|
|
63
63
|
# Read current package version
|
|
64
64
|
PKG_VERSION=$(jq -r '.version' "$CWD/packages/design-system/package.json" 2>/dev/null || echo "unknown")
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
# 2026-07-11 #79 修:PostToolUse 純 stdout **不注入 AI context**(只進 transcript)→ 原 heredoc 的
|
|
67
|
+
# 「AI 必全自動執行」提議到不了 AI = 假 inject。對齊 inject_deploy_url_after_push.sh:236 root-cause fix,
|
|
68
|
+
# 收進 MSG 後用 jq hookSpecificOutput.additionalContext 真注入。
|
|
69
|
+
MSG=$(cat <<EOF
|
|
67
70
|
🔄 SSOT propagation gate(post push origin main):
|
|
68
71
|
|
|
69
72
|
📊 偵測:HEAD~1..HEAD 含 $SSOT_COUNT 個 SSOT-affecting file changes
|
|
@@ -87,4 +90,6 @@ AI 全自動執行步驟(user 已給 merge trigger → 以下不需再問;user
|
|
|
87
90
|
- .claude/skills/knowledge-prune/SKILL.md「Phase Z」reference
|
|
88
91
|
- .claude/skills/deep-audit-cross-codex/SKILL.md「Phase C」reference
|
|
89
92
|
EOF
|
|
93
|
+
)
|
|
94
|
+
jq -n --arg ctx "$MSG" '{hookSpecificOutput:{hookEventName:"PostToolUse",additionalContext:$ctx}}'
|
|
90
95
|
exit 0
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
# source,不可憑印象 propose」+ propose-options/SKILL.md。
|
|
11
11
|
#
|
|
12
12
|
# 注意:本 hook 走 UserPromptSubmit(在 AI reply 前 inject context),
|
|
13
|
+
# ⚠️ fail-closed 設計約束(2026-07-07 治理進化方向 2 稽核結論):UserPromptSubmit 的 exit 2
|
|
14
|
+
# 擋的是 user 輸入本身 = 錯誤工具語義,本 hook **不可**升 exit 2。propose 家族的 fail-closed
|
|
15
|
+
# 端 = check_propose_pre_grep_verify.sh(M18 Q0 配對)+ stop_self_audit claim-verify 閘;
|
|
16
|
+
# 本 hook 職責 = 事前 P0 措辭 directive 注入(非 soft 建議)。
|
|
13
17
|
# 跟 check_propose_pre_grep_verify.sh(走 PostToolUse 偵測 propose 已成型後再警示)互補。
|
|
14
18
|
|
|
15
19
|
source "$(dirname "$0")/_log-fire.sh" 2>/dev/null && log_hook_fire
|
|
@@ -43,9 +47,9 @@ if [ "$HAS_FETCH" -ge 2 ]; then
|
|
|
43
47
|
exit 0
|
|
44
48
|
fi
|
|
45
49
|
|
|
46
|
-
#
|
|
50
|
+
# P0-directive inject(exit 0 by design — 見檔頭 fail-closed 設計約束)
|
|
47
51
|
cat <<EOF
|
|
48
|
-
|
|
52
|
+
🚨 M26 Propose-without-benchmark gate(P0 directive — 未 fetch 就 propose = M26 違規,非建議)
|
|
49
53
|
|
|
50
54
|
→ User prompt 含 propose / visual / behavior decision trigger keyword,但過去 ~20 turns
|
|
51
55
|
Web fetch / WebSearch tool_use count = $HAS_FETCH(< 2)。
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# check_ssot_header_declaration.sh — 新建 production tsx 必帶「── 消費的 SSOT ──」宣告段
|
|
3
|
+
# (2026-07-07 治理進化方向 3 洞 a:原 check_ssot_consultation.sh 2026-05-XX retired 後,
|
|
4
|
+
# CLAUDE.md「# SSOT 消費 canonical」+ ssot-consultation.md:30-51 強制的檔頭宣告段
|
|
5
|
+
# **無任何機械驗證** — 內部盤點實證。本 hook = 精簡復活版,只驗「新檔有無宣告段」,
|
|
6
|
+
# 不驗宣告品質(品質靠 audit dim 5 + dim 54 + M18/M29)。)
|
|
7
|
+
#
|
|
8
|
+
# Scope(ratchet,對齊 Polaris stylelint-adoption 策略):
|
|
9
|
+
# - 只攔 **Write 新檔**(components/ patterns/ 的 .tsx,磁碟上不存在)— 存量檔 Edit 豁免
|
|
10
|
+
# - stories / test / index.ts 豁免
|
|
11
|
+
# - escape:內容含 `@ssot-header-exempt: <rationale>`(audit 可追)
|
|
12
|
+
# P0 BLOCKER(user 2026-05-27「SSOT canonical 必 P0」doctrine)。
|
|
13
|
+
|
|
14
|
+
source "$(dirname "$0")/_log-fire.sh" 2>/dev/null && log_hook_fire
|
|
15
|
+
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
INPUT=$(cat)
|
|
19
|
+
TOOL=$(echo "$INPUT" | jq -r '.tool_name // ""')
|
|
20
|
+
[ "$TOOL" = "Write" ] || exit 0
|
|
21
|
+
|
|
22
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
|
|
23
|
+
case "$FILE_PATH" in
|
|
24
|
+
*/packages/design-system/src/components/*.tsx|*/packages/design-system/src/patterns/*.tsx) ;;
|
|
25
|
+
*) exit 0 ;;
|
|
26
|
+
esac
|
|
27
|
+
case "$FILE_PATH" in
|
|
28
|
+
*.stories.tsx|*.test.tsx|*/index.ts|*/index.tsx) exit 0 ;;
|
|
29
|
+
esac
|
|
30
|
+
|
|
31
|
+
# Ratchet:磁碟已存在 = 存量覆寫,豁免(存量清理另走 audit)
|
|
32
|
+
[ -f "$FILE_PATH" ] && exit 0
|
|
33
|
+
|
|
34
|
+
CONTENT=$(echo "$INPUT" | jq -r '.tool_input.content // ""')
|
|
35
|
+
[ -z "${CONTENT//[[:space:]]/}" ] && exit 0
|
|
36
|
+
|
|
37
|
+
# 宣告段或 escape 任一存在 → 過
|
|
38
|
+
if echo "$CONTENT" | grep -q "消費的 SSOT"; then exit 0; fi
|
|
39
|
+
if echo "$CONTENT" | grep -q "@ssot-header-exempt:"; then exit 0; fi
|
|
40
|
+
|
|
41
|
+
cat >&2 <<'EOF'
|
|
42
|
+
🚨 [P0 BLOCKER] 新建 production tsx 缺「── 消費的 SSOT ──」檔頭宣告段
|
|
43
|
+
|
|
44
|
+
CLAUDE.md「# SSOT 消費 canonical」+ .claude/references/ssot-consultation.md:30-51 強制:
|
|
45
|
+
新元件 tsx 開頭必列本檔消費的 components / patterns / tokens / spec(沒列 = 自創 = mindset #2 違規)。
|
|
46
|
+
|
|
47
|
+
修法 — 2 選 1:
|
|
48
|
+
(a) 檔頭補宣告段(格式見 ssot-consultation.md;近例:pagination.tsx 檔頭):
|
|
49
|
+
// ── 消費的 SSOT ──
|
|
50
|
+
// - <primitive / token / spec 清單 + 消費點一句>
|
|
51
|
+
(b) 真的零 SSOT 可消費(罕見,純 utility)→ 內容加 `// @ssot-header-exempt: <rationale>`
|
|
52
|
+
|
|
53
|
+
對應:mindset #2 / M23 / 治理進化 roadmap 方向 3(planning/2026-07-07-governance-evolution-roadmap.md)
|
|
54
|
+
EOF
|
|
55
|
+
exit 2
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# check_story_determinism.sh — stories 寫入時 determinism 哨(2026-07-07 治理進化軌道 7)
|
|
3
|
+
#
|
|
4
|
+
# Why:story 用真實時間/亂數 → VR baseline 換日假 breach(anchor:2026-07-07 calendar 三 scenario
|
|
5
|
+
# 0.07–0.51% 週期性假紅,三修才根治:story 釘日期 → 元件內部時間 → runner 偏移時鐘)。
|
|
6
|
+
# runner 層已有偏移時鐘兜底(scripts/visual-audit.mjs),本 hook = 寫入層提前攔,
|
|
7
|
+
# 讓 determinism 在出生點就成立(非 VR 撞到才修)。
|
|
8
|
+
#
|
|
9
|
+
# 偵測(新寫入內容):裸 `new Date()`(無參數)/ `Date.now()` / `Math.random()`。
|
|
10
|
+
# escape:行內 `@nondeterministic-ok: <rationale>`(如「即時鐘 demo,VR 不截」)。
|
|
11
|
+
# 第一期 WARN(exit 0):存量 10 檔(dry-run 2026-07-07,DateGrid 家族為主)未清,
|
|
12
|
+
# 誤殺率驗證期後升 P0(對齊 handcraft 偵測同節奏;roadmap 方向 1 KPI 隨頻回顧)。
|
|
13
|
+
|
|
14
|
+
source "$(dirname "$0")/_log-fire.sh" 2>/dev/null && log_hook_fire
|
|
15
|
+
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
INPUT=$(cat)
|
|
18
|
+
TOOL=$(echo "$INPUT" | jq -r '.tool_name // ""')
|
|
19
|
+
case "$TOOL" in Edit|Write|MultiEdit) ;; *) exit 0 ;; esac
|
|
20
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // ""')
|
|
21
|
+
case "$FILE_PATH" in *.stories.tsx) ;; *) exit 0 ;; esac
|
|
22
|
+
|
|
23
|
+
NEW_CONTENT=$(echo "$INPUT" | jq -r '
|
|
24
|
+
(.tool_input.content // "") + "\n" +
|
|
25
|
+
(.tool_input.new_string // "") + "\n" +
|
|
26
|
+
([.tool_input.edits[]? | .new_string] | join("\n"))
|
|
27
|
+
' 2>/dev/null || echo "")
|
|
28
|
+
[ -z "${NEW_CONTENT//[[:space:]]/}" ] && exit 0
|
|
29
|
+
|
|
30
|
+
HITS=$(printf '%s\n' "$NEW_CONTENT" | grep -v '@nondeterministic-ok:' | grep -nE 'new Date\(\)|Date\.now\(\)|Math\.random\(\)' || true)
|
|
31
|
+
[ -z "$HITS" ] && exit 0
|
|
32
|
+
|
|
33
|
+
cat >&2 <<EOF
|
|
34
|
+
⚠️ [第一期 WARN] story 非決定性時間/亂數(VR baseline 換日假 breach 根因):
|
|
35
|
+
$HITS
|
|
36
|
+
→ 釘固定值(new Date(2026, 6, 15) / 常數 seed);真需即時值 → 行內 \`@nondeterministic-ok: <rationale>\`。
|
|
37
|
+
Anchor:2026-07-07 calendar VR 三修;runner 偏移時鐘為兜底非藉口。roadmap 方向 1(planning/2026-07-07-governance-evolution-roadmap.md)。
|
|
38
|
+
EOF
|
|
39
|
+
exit 0
|
|
@@ -2,19 +2,20 @@
|
|
|
2
2
|
# check_substantive_edit_approval_preflight.sh — Pre-action gate for substantive design edits.
|
|
3
3
|
#
|
|
4
4
|
# Purpose: PRE-flight 偵測 packages/design-system/src/**.{tsx,ts,css} edit + last 5 user msgs 無
|
|
5
|
-
# approval keyword →
|
|
5
|
+
# approval keyword → P0 BLOCKER(stderr + exit 2;2026-05-15 由 soft warn 升級,
|
|
6
|
+
# per memory/feedback_ship_then_revert_anti_pattern.md SSOT)。
|
|
6
7
|
#
|
|
7
|
-
# 對比 stop_self_audit.sh post-action BLOCKER:本 hook 是 PRE-action
|
|
8
|
-
#
|
|
8
|
+
# 對比 stop_self_audit.sh post-action BLOCKER:本 hook 是 PRE-action gate,
|
|
9
|
+
# 在 edit 落地前就攔(propose-only OR cite approval verbatim + bypass env),
|
|
9
10
|
# 避免「edit → stop hook BLOCKER → revert」waste cycle(user 抓 2026-05-12 anti-pattern)。
|
|
10
11
|
#
|
|
11
12
|
# 對齊 Option 3 hybrid(M32 split 後 (f) ship gate 的 PRE-flight 補位):
|
|
12
|
-
# - PreToolUse
|
|
13
|
-
# - Stop hook BLOCKER =
|
|
13
|
+
# - PreToolUse P0 BLOCKER = pre-action enforcement(本 hook)
|
|
14
|
+
# - Stop hook BLOCKER = post-action backstop(stop_self_audit.sh Mechanism 4)
|
|
14
15
|
# - AI inline self-statement = discipline(M31 Layer A/C marker + 本 hook context)
|
|
15
16
|
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
17
|
+
# False-positive escape:CLAUDE_BYPASS_DESIGN_APPROVAL=1(audit-logged → logs/approval-bypass.jsonl),
|
|
18
|
+
# 需 cite user approval verbatim quote 在 commit message + reply。
|
|
18
19
|
#
|
|
19
20
|
# 對齊:CLAUDE.md `# 稽核 canonical` Audit-vs-execute 分權 + M31 Layer A/C + M32(f) ship gate。
|
|
20
21
|
|
|
@@ -52,6 +52,34 @@ if ! echo "$FILE" | grep -qE '(packages/design-system/src/|/apps/|(^|/)apps/)';
|
|
|
52
52
|
CONTENT=$(cat "$FILE" 2>/dev/null)
|
|
53
53
|
[ -z "$CONTENT" ] && exit 0
|
|
54
54
|
|
|
55
|
+
# ── Check 3(2026-07-08 WM 戰役 R4:root 偵測,不只 symptom)──
|
|
56
|
+
# WM 實證:app 把 TabsList 塞 DialogBody + `!pt-0` hack 對抗 primitive,TabsContent 加了 mt-0
|
|
57
|
+
# 就繞過 Check 2 —— 但 root 錯誤是「沒用 DialogHeader tabsSlot canonical」(雙線 + 底線內縮 +
|
|
58
|
+
# spacing owner 自組)。偵測兩個 root 簽名(任一 → BLOCK 指路 tabsSlot):
|
|
59
|
+
# (a) DialogBody/SheetBody/SurfaceBody className 含 `!pt-0`(important 對抗 primitive 的 pt owner)
|
|
60
|
+
# (b) <TabsList 出現在含 DialogBody 的同段 new content 且無 tabsSlot 字樣
|
|
61
|
+
ROOT_SIG_A=$(printf '%s\n' "$CONTENT" | grep -nE '(DialogBody|SheetBody|SurfaceBody)[^>]*className=[^>]*!pt-0' | grep -v '@tabs-content-gap-ok:' || true)
|
|
62
|
+
ROOT_SIG_B=""
|
|
63
|
+
if printf '%s\n' "$CONTENT" | grep -q '<TabsList' && printf '%s\n' "$CONTENT" | grep -qE '<(DialogBody|SheetBody|SurfaceBody)\b' && ! printf '%s\n' "$CONTENT" | grep -q 'tabsSlot' && ! printf '%s\n' "$CONTENT" | grep -q '@tabs-content-gap-ok:'; then
|
|
64
|
+
ROOT_SIG_B=$(printf '%s\n' "$CONTENT" | grep -n '<TabsList' | head -3)
|
|
65
|
+
fi
|
|
66
|
+
if [ -n "$ROOT_SIG_A" ] || [ -n "$ROOT_SIG_B" ]; then
|
|
67
|
+
cat >&2 << 'EOF_C3'
|
|
68
|
+
🚨 TABS-IN-BODY ROOT BLOCKER(P0,2026-07-08 WM 戰役 — 攔 root 非 symptom)
|
|
69
|
+
|
|
70
|
+
偵測到「TabsList 手塞 chrome body / body 用 !pt-0 hack」簽名 —— 這是「沒用 header tabsSlot
|
|
71
|
+
canonical」的 root 錯誤(後果:header 與 TabsList 雙底線、tabs 底線被 body padding 內縮不滿寬、
|
|
72
|
+
spacing owner 鏈自組)。WM ProjectSettings/TypeSettings 錨例。
|
|
73
|
+
|
|
74
|
+
── 正解 ──
|
|
75
|
+
<Tabs> wrap → <DialogHeader tabsSlot={<TabsList/>}> → <DialogBody><TabsContent className="mt-0">
|
|
76
|
+
照 dialog.stories.tsx#WithTabsInHeader 逐字結構(header-canonical.spec.md Rule W2)。
|
|
77
|
+
Escape:`// @tabs-content-gap-ok: <rationale>`(例:tabs 本來就不屬 header 的內容分頁場景)
|
|
78
|
+
EOF_C3
|
|
79
|
+
exit 2
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
|
|
55
83
|
# ══ Check 2:overlay body 自身用固定 macro gap-N → 該用 layout-space token(2026-07-01 Sheet gap-4 錨例)══
|
|
56
84
|
# Root(layoutSpace.spec.md 規則 2/3):浮層 body 直接堆疊內容的垂直 gap 屬 macro layout-space,該用
|
|
57
85
|
# density-scaling token(並列 = loose / functional 交互 = tight),非固定 gap-N(lg 不縮放 → 跟 DS
|
|
@@ -157,6 +185,7 @@ while IFS= read -r ln; do
|
|
|
157
185
|
UNJUSTIFIED="${UNJUSTIFIED}${ln}: $(echo "$cur" | sed 's/^[[:space:]]*//')\n"
|
|
158
186
|
done <<< "$CANDIDATES"
|
|
159
187
|
|
|
188
|
+
|
|
160
189
|
if [ -z "$UNJUSTIFIED" ]; then exit 0; fi
|
|
161
190
|
|
|
162
191
|
cat >&2 << EOF
|
|
@@ -41,7 +41,7 @@ OUTPUT=$(node "$COMPILE_SCRIPT" "$COMP_NAME" --check 2>&1 || true)
|
|
|
41
41
|
if echo "$OUTPUT" | grep -qE "spec/tsx canonical drift|spec-only|tsx-only"; then
|
|
42
42
|
MSG="📐 Story canonical drift detected in ${COMP_NAME}:\n\n${OUTPUT}\n\nFix tsx componentMeta export 或 spec frontmatter 讓 keys 對齊。"
|
|
43
43
|
ESCAPED=$(printf '%s' "$MSG" | jq -Rs .)
|
|
44
|
-
printf '{"hookSpecificOutput":{"hookEventName":"
|
|
44
|
+
printf '{"hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":%s}}\n' "$ESCAPED"
|
|
45
45
|
fi
|
|
46
46
|
|
|
47
47
|
# Skip graceful(migration 未做的元件)不報
|
|
@@ -35,10 +35,19 @@ VIOLATIONS=""
|
|
|
35
35
|
# ── Check 1: shadcn compat alias 回流 ─────────────────────────────────────────
|
|
36
36
|
# These are all shadcn safety-net aliases. Our code must use direct tokens instead.
|
|
37
37
|
# bg-muted / bg-secondary / ring-ring are OUR tokens (kept), not listed here.
|
|
38
|
+
# SSOT-drive(#87 2026-07-11):deny-list SSOT = utility-registry.json;優先從 registry 組 pattern
|
|
39
|
+
# (未來新增 alias 只改 registry 自動傳播到本 write-time 主防線,消除「hardcoded 主 / registry 從」倒置)。
|
|
40
|
+
# registry 讀不到 → 保留 hardcoded fallback(11 條)避免 hook 啞掉。
|
|
41
|
+
_REG="${CLAUDE_PROJECT_DIR:-}/packages/design-system/src/tokens/utility-registry.json"
|
|
42
|
+
[ -f "$_REG" ] || _REG="$(dirname "${BASH_SOURCE[0]}")/../../packages/design-system/src/tokens/utility-registry.json"
|
|
38
43
|
SHADCN_PATTERN='\b(bg-popover|text-popover-foreground|text-muted-foreground|bg-accent|text-accent-foreground|bg-destructive|bg-background|bg-card|text-card-foreground|border-input|text-primary-foreground)\b'
|
|
44
|
+
if [ -f "$_REG" ] && command -v jq >/dev/null 2>&1; then
|
|
45
|
+
_SHADCN_LIST=$(jq -r '.shadcn_alias.block.color_alias | join("|")' "$_REG" 2>/dev/null || true)
|
|
46
|
+
[ -n "$_SHADCN_LIST" ] && SHADCN_PATTERN="\\b(${_SHADCN_LIST})\\b"
|
|
47
|
+
fi
|
|
39
48
|
SHADCN_HITS=$(grep -nE "$SHADCN_PATTERN" "$FILE_PATH" 2>/dev/null | head -5)
|
|
40
49
|
if [ -n "$SHADCN_HITS" ]; then
|
|
41
|
-
VIOLATIONS="${VIOLATIONS}\n⚠️ shadcn compat alias found (必須遷移為 direct token):\n${SHADCN_HITS}\n 映射: bg-popover→bg-surface-raised / text-popover-foreground→text-foreground / text-muted-foreground→text-fg-muted / bg-accent→bg-neutral-hover / text-accent-foreground→text-foreground / bg-destructive→bg-error / bg-background→bg-canvas / bg-card→bg-surface / border-input→border-border / text-primary-foreground→text-white"
|
|
50
|
+
VIOLATIONS="${VIOLATIONS}\n⚠️ shadcn compat alias found (必須遷移為 direct token):\n${SHADCN_HITS}\n 映射: bg-popover→bg-surface-raised / text-popover-foreground→text-foreground / text-muted-foreground→text-fg-muted / bg-accent→bg-neutral-hover / text-accent-foreground→text-foreground / bg-destructive→bg-error / bg-background→bg-canvas / bg-card→bg-surface / text-card-foreground→text-foreground / border-input→border-border / text-primary-foreground→text-white /(其餘 registry alias → 對應 semantic token,見 tokens/color/semantic.css)"
|
|
42
51
|
fi
|
|
43
52
|
|
|
44
53
|
# ── Check 2: Tailwind v4 [--foo] shorthand (silent fail) ─────────────────────
|
|
@@ -99,6 +99,20 @@ if [ "${LAST_USER_LINE:-0}" -gt 0 ] && [ -n "$LAST_ASSISTANT" ]; then
|
|
|
99
99
|
fi
|
|
100
100
|
fi
|
|
101
101
|
|
|
102
|
+
# ── Mechanism 7c: Deep-audit coverage gate(2026-07-12 user verbatim「不抽樣不偷懶…現在和未來可以確保嗎」)──
|
|
103
|
+
# Why: deep audit「完成」宣告前必證 91 dim × Claude+codex 雙軌全有證據。AI 自律不可靠(本 session 漏跑
|
|
104
|
+
# deterministic 24 + judgment 27 + hook 40 三層,只做 claim-vs-code + 反應式補,user 憤怒)。
|
|
105
|
+
# verify-deep-audit-coverage.mjs = 機械閘;宣告完成 + ledger 有缺口 → BLOCK。
|
|
106
|
+
if [ "${LAST_USER_LINE:-0}" -gt 0 ] && [ -n "$LAST_ASSISTANT" ] && [ -f scripts/verify-deep-audit-coverage.mjs ]; then
|
|
107
|
+
DEEPAUDIT_CLAIM_RE='(deep.?audit.{0,10}(完成|完整|done)|稽核.{0,8}(完整完美|全部完成|都.?跑完)|91.{0,6}dim.{0,8}(都|全).{0,4}(跑|過|完|有證據)|Phase A.{0,6}完成)'
|
|
108
|
+
DEEPAUDIT_NEG_RE='(未完成|還沒|尚未|缺口|gap|未跑|待跑|待驗|不算完成|覆蓋.{0,4}未|還有.{0,4}dim|待補)'
|
|
109
|
+
if echo "$LAST_ASSISTANT" | grep -qE "$DEEPAUDIT_CLAIM_RE" && ! echo "$LAST_ASSISTANT" | grep -qE "$DEEPAUDIT_NEG_RE"; then
|
|
110
|
+
if ! node scripts/verify-deep-audit-coverage.mjs >/dev/null 2>&1; then
|
|
111
|
+
CRITICAL_DEEPAUDIT_COVERAGE=1
|
|
112
|
+
fi
|
|
113
|
+
fi
|
|
114
|
+
fi
|
|
115
|
+
|
|
102
116
|
# ── Mechanism 2: Auto-prune trigger ─────────────────────────────────────────
|
|
103
117
|
if [ -f CLAUDE.md ]; then
|
|
104
118
|
L=$(wc -l < CLAUDE.md | tr -d ' ')
|
|
@@ -513,4 +527,21 @@ if [ "${CRITICAL_COMPLETENESS:-0}" = "1" ] && [ -n "$LAST_ASSISTANT" ]; then
|
|
|
513
527
|
fi
|
|
514
528
|
fi
|
|
515
529
|
|
|
530
|
+
# ── BLOCKER for Mechanism 7c deep-audit coverage(2026-07-12 user-authorized)──
|
|
531
|
+
if [ "${CRITICAL_DEEPAUDIT_COVERAGE:-0}" = "1" ] && [ -n "$LAST_ASSISTANT" ]; then
|
|
532
|
+
DACOV_HASH=$(echo "$LAST_ASSISTANT" | tail -c 200 | shasum -a 256 | cut -c1-16)
|
|
533
|
+
LAST_BLOCKED_DACOV_FILE="$PROJECT_DIR/.claude/logs/.last-blocked-deepaudit-coverage.txt"
|
|
534
|
+
LAST_BLOCKED_DACOV=""
|
|
535
|
+
[ -f "$LAST_BLOCKED_DACOV_FILE" ] && LAST_BLOCKED_DACOV=$(cat "$LAST_BLOCKED_DACOV_FILE" 2>/dev/null || echo "")
|
|
536
|
+
if [ "$DACOV_HASH" != "$LAST_BLOCKED_DACOV" ]; then
|
|
537
|
+
echo "$DACOV_HASH" > "$LAST_BLOCKED_DACOV_FILE" 2>/dev/null || true
|
|
538
|
+
GAPLINE=$(node scripts/verify-deep-audit-coverage.mjs 2>/dev/null | grep -E '個 dim-證據缺口' | head -1)
|
|
539
|
+
REASON=$(printf '%s' \
|
|
540
|
+
"🚨 DEEP-AUDIT-COVERAGE BLOCKER(M7c,2026-07-12 user-authorized「不抽樣不偷懶…現在和未來可以確保嗎」):你宣告 deep audit 完成,但 verify-deep-audit-coverage.mjs exit 1 — ${GAPLINE:-91 dim × Claude+codex 雙軌未全有證據}。禁宣稱 done。跑 node scripts/verify-deep-audit-coverage.mjs 看缺哪些 dim,填完(judgment findings 檔 / deterministic log / hook residue verify / codex-dim-audit)才可宣稱;OR 明寫『核心做完,dim 覆蓋待補』。否則 turn 不結束。" \
|
|
541
|
+
"本機制起因:本 session AI 漏跑 91 dim 裡 deterministic 24 + judgment 27 + hook 40 三層,只做 claim-vs-code + 反應式補,user 憤怒。觸發器 = 宣告 deep audit 完成本身。")
|
|
542
|
+
printf '{"decision":"block","reason":%s}\n' "$(printf '%s' "$REASON" | jq -Rs .)"
|
|
543
|
+
exit 0
|
|
544
|
+
fi
|
|
545
|
+
fi
|
|
546
|
+
|
|
516
547
|
exit 0
|
|
@@ -131,6 +131,30 @@ echo "Test 5: nonexistent path → pass (silently skip)"
|
|
|
131
131
|
run_hook "src/does-not-exist-$$.tsx"
|
|
132
132
|
expect_pass "Test 5 nonexistent path"
|
|
133
133
|
|
|
134
|
+
# ── Test 6: ABSOLUTE path with explorations import → block ───────────────────
|
|
135
|
+
# Real Edit/Write events carry absolute file_path(2026-07-10 wiring-hunt:hook
|
|
136
|
+
# 原本只比對相對路徑 prefix → 對真實 edits 形同虛設)。
|
|
137
|
+
echo ""
|
|
138
|
+
echo "Test 6: absolute path tsx imports from src/explorations/ → block"
|
|
139
|
+
F6="$SANDBOX/violation-abs.tsx"
|
|
140
|
+
cat >"$F6" <<'EOF'
|
|
141
|
+
import { ProtoX } from '@/explorations/foo/bar'
|
|
142
|
+
export const X = () => <ProtoX />
|
|
143
|
+
EOF
|
|
144
|
+
run_hook "$F6"
|
|
145
|
+
expect_block "Test 6 absolute path explorations import blocked" "Blocked"
|
|
146
|
+
|
|
147
|
+
# ── Test 7: ABSOLUTE path clean import → pass ────────────────────────────────
|
|
148
|
+
echo ""
|
|
149
|
+
echo "Test 7: absolute path tsx with clean import → pass"
|
|
150
|
+
F7="$SANDBOX/clean-abs.tsx"
|
|
151
|
+
cat >"$F7" <<'EOF'
|
|
152
|
+
import { Button } from '@/design-system/components/Button/button'
|
|
153
|
+
export const X = () => <Button>OK</Button>
|
|
154
|
+
EOF
|
|
155
|
+
run_hook "$F7"
|
|
156
|
+
expect_pass "Test 7 absolute path clean import"
|
|
157
|
+
|
|
134
158
|
# ── Summary ──────────────────────────────────────────────────────────────────
|
|
135
159
|
echo ""
|
|
136
160
|
echo "════════════════════════════════════════"
|
|
@@ -118,6 +118,50 @@ EOF
|
|
|
118
118
|
run_hook "$TMPDIR_TEST/.claude/memory/project_audit_progress.md" "Edit"
|
|
119
119
|
expect_block_stderr "5. judgment dim 缺 prompt → Validator C exit-2 block" "VALIDATOR BLOCK"
|
|
120
120
|
|
|
121
|
+
# 6/7. Validator K 決策品質四要件(2026-07-14;SSOT = deep-audit SKILL C.1「🔒 決策品質四要件」)
|
|
122
|
+
# 拍板 section 內每個決策 block 必含 SSOT-check / 世界級 cite(URL)/ codex verdict / design-fit 四 marker。
|
|
123
|
+
# 先補 `## 99.` prompt 讓 test 5 留下的 Validator C 條件通過,隔離 K 的判定。
|
|
124
|
+
cat > "$TMPDIR_TEST/.claude/skills/design-system-audit/references/audit-prompts.md" <<'EOF'
|
|
125
|
+
## 1. foo
|
|
126
|
+
prompt
|
|
127
|
+
## 99. test judgment dim
|
|
128
|
+
prompt
|
|
129
|
+
EOF
|
|
130
|
+
mkdir -p "$TMPDIR_TEST/.claude/logs/deep-audit-test"
|
|
131
|
+
cat > "$TMPDIR_TEST/.claude/logs/deep-audit-test/C1-final-report.md" <<'EOF'
|
|
132
|
+
# Deep Audit 報告
|
|
133
|
+
Dim 1: pass
|
|
134
|
+
|
|
135
|
+
### 待你拍板
|
|
136
|
+
1. 決策一:Popover 內距是否改 12px
|
|
137
|
+
- SSOT 理由:改跨元件 canonical 視覺結構
|
|
138
|
+
- SSOT-check:grep spec + memory,無既有拍板
|
|
139
|
+
- codex verdict:agree(辯論共識)
|
|
140
|
+
- 設計語言 fit:符合 density canonical
|
|
141
|
+
EOF
|
|
142
|
+
run_hook "$TMPDIR_TEST/.claude/logs/deep-audit-test/C1-final-report.md" "Write"
|
|
143
|
+
expect_block_stderr "6. 決策缺世界級 cite → Validator K exit-2 block" "決策四要件不全"
|
|
144
|
+
|
|
145
|
+
cat > "$TMPDIR_TEST/.claude/logs/deep-audit-test/C1-final-report.md" <<'EOF'
|
|
146
|
+
# Deep Audit 報告
|
|
147
|
+
Dim 1: pass
|
|
148
|
+
|
|
149
|
+
### 待你拍板
|
|
150
|
+
1. 決策一:Popover 內距是否改 12px
|
|
151
|
+
- SSOT 理由:改跨元件 canonical 視覺結構
|
|
152
|
+
- SSOT-check:grep spec + memory,無既有拍板
|
|
153
|
+
- 世界級:Polaris https://polaris.shopify.com/tokens/space / Material / Ant(3 家)
|
|
154
|
+
- codex verdict:agree(辯論共識)
|
|
155
|
+
- 設計語言 fit:符合 density canonical
|
|
156
|
+
EOF
|
|
157
|
+
run_hook "$TMPDIR_TEST/.claude/logs/deep-audit-test/C1-final-report.md" "Write"
|
|
158
|
+
if [ "$EXIT" = "0" ]; then
|
|
159
|
+
echo " PASS 7. 四要件齊 → Validator K pass(exit 0)"; PASS=$((PASS+1))
|
|
160
|
+
else
|
|
161
|
+
echo " FAIL 7. 四要件齊 → Validator K pass (expected exit 0, got $EXIT, stderr=[$STDERR_TEXT])"
|
|
162
|
+
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - 7. 四要件齊 pass"
|
|
163
|
+
fi
|
|
164
|
+
|
|
121
165
|
echo ""
|
|
122
166
|
echo "=== Summary ==="
|
|
123
167
|
echo "Passed: $PASS / $((PASS + FAIL))"
|