@qijenchen/design-system 0.1.0-beta.10 → 0.1.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +201 -0
- package/README.md +7 -15
- package/cli-init.mjs +90 -0
- package/ds-canonical/commands/README.md +26 -0
- package/ds-canonical/commands/gov-status.md +79 -0
- package/ds-canonical/hooks/README.md +145 -0
- package/ds-canonical/hooks/_log-fire.sh +44 -0
- package/ds-canonical/hooks/block_prototype_imports.py +111 -0
- package/ds-canonical/hooks/check_app_shell_primary_header_consistency.sh +68 -0
- package/ds-canonical/hooks/check_audit_post_report_validator.sh +88 -0
- package/ds-canonical/hooks/check_audit_sample_escape.sh +73 -0
- package/ds-canonical/hooks/check_benchmark_citation.sh +106 -0
- package/ds-canonical/hooks/check_canonical_propagation.sh +189 -0
- package/ds-canonical/hooks/check_chrome_header_handcraft.sh +70 -0
- package/ds-canonical/hooks/check_codex_brief_invariants.sh +83 -0
- package/ds-canonical/hooks/check_codex_collab_5step.sh +108 -0
- package/ds-canonical/hooks/check_datatable_invariants.sh +117 -0
- package/ds-canonical/hooks/check_dim_count_drift.sh +72 -0
- package/ds-canonical/hooks/check_field_controls_contracts.sh +110 -0
- package/ds-canonical/hooks/check_field_family_invariants.sh +205 -0
- package/ds-canonical/hooks/check_file_size_budget.sh +60 -0
- package/ds-canonical/hooks/check_header_with_tabs_border.sh +87 -0
- package/ds-canonical/hooks/check_main_branch_workbench.sh +93 -0
- package/ds-canonical/hooks/check_naming_and_abstraction.sh +165 -0
- package/ds-canonical/hooks/check_opacity_token_usage.sh +149 -0
- package/ds-canonical/hooks/check_pattern_invariants.sh +194 -0
- package/ds-canonical/hooks/check_peoplepicker_ssot_drift.sh +56 -0
- package/ds-canonical/hooks/check_pixel_quantified_audit.sh +53 -0
- package/ds-canonical/hooks/check_propose_plain_chinese.sh +74 -0
- package/ds-canonical/hooks/check_propose_pre_grep_verify.sh +70 -0
- package/ds-canonical/hooks/check_select_all_canonical.sh +58 -0
- package/ds-canonical/hooks/check_solo_workflow.sh +258 -0
- package/ds-canonical/hooks/check_spec_class_drift.sh +88 -0
- package/ds-canonical/hooks/check_story_invariants.sh +612 -0
- package/ds-canonical/hooks/check_substantive_edit_approval_preflight.sh +105 -0
- package/ds-canonical/hooks/check_tab_lg_chrome_header_equal.sh +66 -0
- package/ds-canonical/hooks/check_wrapper_primitive_schema_drift.sh +104 -0
- package/ds-canonical/hooks/enforce_home_charter.sh +44 -0
- package/ds-canonical/hooks/inject_pending_self_audit.sh +204 -0
- package/ds-canonical/hooks/lib/_approval_re.sh +33 -0
- package/ds-canonical/hooks/lib/_code_quality.sh +73 -0
- package/ds-canonical/hooks/lib/_cva_default_sync.sh +69 -0
- package/ds-canonical/hooks/lib/_governance_coverage_check.sh +49 -0
- package/ds-canonical/hooks/lib/_hardcoded_strings.sh +163 -0
- package/ds-canonical/hooks/lib/_layout_space_canonical.sh +56 -0
- package/ds-canonical/hooks/lib/_overlay_handcraft.sh +141 -0
- package/ds-canonical/hooks/lib/_person_data_richness.sh +42 -0
- package/ds-canonical/hooks/lib/_story_compile_drift.sh +48 -0
- package/ds-canonical/hooks/lib/_token_hygiene.sh +95 -0
- package/ds-canonical/hooks/log_governance_fires.sh +50 -0
- package/ds-canonical/hooks/log_skill_invokes.sh +41 -0
- package/ds-canonical/hooks/post_edit_dispatcher.sh +62 -0
- package/ds-canonical/hooks/retired/check_anatomy_section_numbering.sh +106 -0
- package/ds-canonical/hooks/retired/check_avatar_hovercard.sh +90 -0
- package/ds-canonical/hooks/retired/check_button_icon_literal.sh.retired-2026-04-28 +38 -0
- package/ds-canonical/hooks/retired/check_container_breathing.sh +142 -0
- package/ds-canonical/hooks/retired/check_governance_compliance.sh +61 -0
- package/ds-canonical/hooks/retired/check_icon_only_padding_formula.sh +104 -0
- package/ds-canonical/hooks/retired/check_item_content_primitive.sh +150 -0
- package/ds-canonical/hooks/retired/check_item_list_gap.sh +153 -0
- package/ds-canonical/hooks/retired/check_sideoffset_canonical.sh +65 -0
- package/ds-canonical/hooks/retired/check_spec_iteration_tag.sh +87 -0
- package/ds-canonical/hooks/retired/check_ssot_consultation.sh +88 -0
- package/ds-canonical/hooks/retired/check_sync_update.sh +20 -0
- package/ds-canonical/hooks/retired/check_third_party_dom_verified.sh +95 -0
- package/ds-canonical/hooks/retired/enforce_home_charter.sh +125 -0
- package/ds-canonical/hooks/retired/post_edit_canonical_interrogate.sh +109 -0
- package/ds-canonical/hooks/retired/pre_edit_spec_check.sh +68 -0
- package/ds-canonical/hooks/retired/pre_new_component_spec.sh +39 -0
- package/ds-canonical/hooks/retired/pre_write_subsumption_check.sh +112 -0
- package/ds-canonical/hooks/retired/stop_meta_self_audit.sh.retired-2026-05-13 +76 -0
- package/ds-canonical/hooks/retired/tests/test_check_anatomy_section_numbering.sh +14 -0
- package/ds-canonical/hooks/retired/tests/test_check_avatar_hovercard.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_container_breathing.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_governance_compliance.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_icon_only_padding_formula.sh +79 -0
- package/ds-canonical/hooks/retired/tests/test_check_item_content_primitive.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_item_list_gap.sh +163 -0
- package/ds-canonical/hooks/retired/tests/test_check_sideoffset_canonical.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_spec_iteration_tag.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_ssot_consultation.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_check_sync_update.sh +14 -0
- package/ds-canonical/hooks/retired/tests/test_check_third_party_dom_verified.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_enforce_home_charter.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_pre_edit_spec_check.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_pre_new_component_spec.sh +15 -0
- package/ds-canonical/hooks/retired/tests/test_pre_write_subsumption_check.sh +63 -0
- package/ds-canonical/hooks/session_start_governance_check.sh +263 -0
- package/ds-canonical/hooks/stop_passive_logging.sh +322 -0
- package/ds-canonical/hooks/stop_self_audit.sh +450 -0
- package/ds-canonical/hooks/tests/KNOWN-BROKEN.md +15 -0
- package/ds-canonical/hooks/tests/run-all.sh +76 -0
- package/ds-canonical/hooks/tests/test_block_prototype_imports.sh +143 -0
- package/ds-canonical/hooks/tests/test_check_app_shell_primary_header_consistency.sh +140 -0
- package/ds-canonical/hooks/tests/test_check_audit_post_report_validator.sh +115 -0
- package/ds-canonical/hooks/tests/test_check_audit_sample_escape.sh +93 -0
- package/ds-canonical/hooks/tests/test_check_benchmark_citation.sh +115 -0
- package/ds-canonical/hooks/tests/test_check_canonical_propagation.sh +133 -0
- package/ds-canonical/hooks/tests/test_check_chrome_header_handcraft.sh +123 -0
- package/ds-canonical/hooks/tests/test_check_code_quality.sh +15 -0
- package/ds-canonical/hooks/tests/test_check_codex_collab_5step.sh +96 -0
- package/ds-canonical/hooks/tests/test_check_cva_default_sync.sh +15 -0
- package/ds-canonical/hooks/tests/test_check_datatable_invariants.sh +122 -0
- package/ds-canonical/hooks/tests/test_check_dim_count_drift.sh +98 -0
- package/ds-canonical/hooks/tests/test_check_field_controls_contracts.sh +126 -0
- package/ds-canonical/hooks/tests/test_check_field_family_invariants.sh +194 -0
- package/ds-canonical/hooks/tests/test_check_file_size_budget.sh +32 -0
- package/ds-canonical/hooks/tests/test_check_hardcoded_strings.sh +14 -0
- package/ds-canonical/hooks/tests/test_check_header_with_tabs_border.sh +110 -0
- package/ds-canonical/hooks/tests/test_check_layout_space_canonical.sh +73 -0
- package/ds-canonical/hooks/tests/test_check_main_branch_workbench.sh +147 -0
- package/ds-canonical/hooks/tests/test_check_naming_and_abstraction.sh +136 -0
- package/ds-canonical/hooks/tests/test_check_opacity_token_usage.sh +110 -0
- package/ds-canonical/hooks/tests/test_check_overlay_handcraft.sh +126 -0
- package/ds-canonical/hooks/tests/test_check_pattern_invariants.sh +148 -0
- package/ds-canonical/hooks/tests/test_check_peoplepicker_ssot_drift.sh +108 -0
- package/ds-canonical/hooks/tests/test_check_person_data_richness.sh +58 -0
- package/ds-canonical/hooks/tests/test_check_pixel_quantified_audit.sh +142 -0
- package/ds-canonical/hooks/tests/test_check_propose_plain_chinese.sh +126 -0
- package/ds-canonical/hooks/tests/test_check_propose_pre_grep_verify.sh +117 -0
- package/ds-canonical/hooks/tests/test_check_select_all_canonical.sh +125 -0
- package/ds-canonical/hooks/tests/test_check_solo_workflow.sh +201 -0
- package/ds-canonical/hooks/tests/test_check_spec_class_drift.sh +135 -0
- package/ds-canonical/hooks/tests/test_check_story_anatomy.sh.broken +197 -0
- package/ds-canonical/hooks/tests/test_check_story_category.sh.broken +187 -0
- package/ds-canonical/hooks/tests/test_check_story_compile_drift.sh +15 -0
- package/ds-canonical/hooks/tests/test_check_story_invariants.sh +209 -0
- package/ds-canonical/hooks/tests/test_check_story_name_jargon.sh.broken +53 -0
- package/ds-canonical/hooks/tests/test_check_story_slot_split.sh +156 -0
- package/ds-canonical/hooks/tests/test_check_substantive_edit_approval_preflight.sh +176 -0
- package/ds-canonical/hooks/tests/test_check_tab_lg_chrome_header_equal.sh +138 -0
- package/ds-canonical/hooks/tests/test_check_token_hygiene.sh +21 -0
- package/ds-canonical/hooks/tests/test_check_wrapper_primitive_schema_drift.sh +169 -0
- package/ds-canonical/hooks/tests/test_enforce_home_charter.sh +77 -0
- package/ds-canonical/hooks/tests/test_inject_pending_self_audit.sh +125 -0
- package/ds-canonical/hooks/tests/test_log_governance_fires.sh +10 -0
- package/ds-canonical/hooks/tests/test_log_skill_invokes.sh +7 -0
- package/ds-canonical/hooks/tests/test_post_edit_dispatcher.sh +108 -0
- package/ds-canonical/hooks/tests/test_session_start_governance_check.sh +143 -0
- package/ds-canonical/hooks/tests/test_stop_capture_metrics.sh +95 -0
- package/ds-canonical/hooks/tests/test_stop_governance_drift_check.sh.broken +125 -0
- package/ds-canonical/hooks/tests/test_stop_harvest_corrections.sh +10 -0
- package/ds-canonical/hooks/tests/test_stop_passive_logging.sh +100 -0
- package/ds-canonical/hooks/tests/test_stop_self_audit.sh +76 -0
- package/ds-canonical/hooks/tests/test_stop_tsc_sanity.sh +10 -0
- package/ds-canonical/references/README.md +43 -0
- package/ds-canonical/references/audit-coverage-vs-24-checklist.md +74 -0
- package/ds-canonical/references/build-ui-canonicals.md +69 -0
- package/ds-canonical/references/cva-patterns.md +41 -0
- package/ds-canonical/references/drag-canonical.md +331 -0
- package/ds-canonical/references/item-anatomy-recipe.md +225 -0
- package/ds-canonical/references/naming-conventions.md +56 -0
- package/ds-canonical/references/principle-dim-map.json +515 -0
- package/ds-canonical/references/props-naming.md +45 -0
- package/ds-canonical/references/spec-rules.md +58 -0
- package/ds-canonical/references/ssot-consultation.md +63 -0
- package/ds-canonical/references/ssot-index.md +40 -0
- package/ds-canonical/references/story-baseline-registry.json +79 -0
- package/ds-canonical/references/structural-token-retention.md +42 -0
- package/ds-canonical/references/tailwind-gotchas.md +87 -0
- package/ds-canonical/references/ui-dev-rules.md +60 -0
- package/ds-canonical/rules/README.md +34 -0
- package/ds-canonical/rules/meta-patterns.md +87 -0
- package/ds-canonical/rules/self-verify.md +53 -0
- package/ds-canonical/rules/spec-rules.md +25 -0
- package/ds-canonical/rules/story-rules.md +56 -0
- package/ds-canonical/rules/ui-development.md +87 -0
- package/ds-canonical/skills/README.md +88 -0
- package/ds-canonical/skills/bug-fix-rhythm/SKILL.md +181 -0
- package/ds-canonical/skills/code-quality-audit/SKILL.md +63 -0
- package/ds-canonical/skills/codex-collab/SKILL.md +249 -0
- package/ds-canonical/skills/codex-collab/references/brief-template.md +48 -0
- package/ds-canonical/skills/codex-collab/references/transport.md +58 -0
- package/ds-canonical/skills/codify-corrections/SKILL.md +184 -0
- package/ds-canonical/skills/codify-principle/SKILL.md +151 -0
- package/ds-canonical/skills/component-quality-gate/SKILL.md +102 -0
- package/ds-canonical/skills/component-quality-gate/references/checklist.md +79 -0
- package/ds-canonical/skills/deep-audit-cross-codex/SKILL.md +247 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-a-workflow.md +123 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/phase-b-codex-brief.md +165 -0
- package/ds-canonical/skills/deep-audit-cross-codex/references/triage-rubric.md +91 -0
- package/ds-canonical/skills/delivery-handoff/SKILL.md +229 -0
- package/ds-canonical/skills/delivery-handoff/references/flow-diagram.md +180 -0
- package/ds-canonical/skills/delivery-handoff/references/handoff-template.md +177 -0
- package/ds-canonical/skills/delivery-handoff/references/inventory-checklist.md +196 -0
- package/ds-canonical/skills/design-system-audit/SKILL.md +343 -0
- package/ds-canonical/skills/design-system-audit/references/audit-prompts.md +1260 -0
- package/ds-canonical/skills/design-system-audit/references/checkpoints.md +240 -0
- package/ds-canonical/skills/design-system-audit/references/historical-bugs.md +240 -0
- package/ds-canonical/skills/design-system-audit/references/principle-audit-protocol.md +364 -0
- package/ds-canonical/skills/design-system-audit/references/rule-placement.md +175 -0
- package/ds-canonical/skills/design-system-audit/references/spec-template.md +66 -0
- package/ds-canonical/skills/ensure-canonical/SKILL.md +196 -0
- package/ds-canonical/skills/governance-health/SKILL.md +146 -0
- package/ds-canonical/skills/knowledge-prune/SKILL.md +303 -0
- package/ds-canonical/skills/new-component/SKILL.md +170 -0
- package/ds-canonical/skills/new-component/references/new-component-checklist.md +85 -0
- package/ds-canonical/skills/performance-audit/SKILL.md +107 -0
- package/ds-canonical/skills/product-ui-audit/SKILL.md +230 -0
- package/ds-canonical/skills/product-ui-audit/references/audit-checks.md +246 -0
- package/ds-canonical/skills/product-ui-audit/references/common-misuses.md +329 -0
- package/ds-canonical/skills/product-ui-audit/references/report-template.md +159 -0
- package/ds-canonical/skills/propose-options/SKILL.md +177 -0
- package/ds-canonical/skills/prototype/SKILL.md +244 -0
- package/ds-canonical/skills/prototype/references/audit-checks.md +37 -0
- package/ds-canonical/skills/prototype/references/benchmark-sources.md +94 -0
- package/ds-canonical/skills/prototype/references/checkpoints.md +191 -0
- package/ds-canonical/skills/prototype/references/evaluation-matrix.md +141 -0
- package/ds-canonical/skills/prototype/references/ooux-template.md +198 -0
- package/ds-canonical/skills/prototype/references/proposal-template.md +229 -0
- package/ds-canonical/skills/scan-similar-bugs/SKILL.md +198 -0
- package/ds-canonical/skills/story-auto-compile-migrate/SKILL.md +159 -0
- package/ds-canonical/skills/story-writing/SKILL.md +122 -0
- package/ds-canonical/skills/story-writing/references/anatomy-standard.md +217 -0
- package/ds-canonical/skills/story-writing/references/category-templates.md +174 -0
- package/ds-canonical/skills/story-writing/references/example-selection.md +70 -0
- package/ds-canonical/skills/story-writing/references/self-check.md +20 -0
- package/ds-canonical/skills/ux-audit/SKILL.md +130 -0
- package/ds-canonical/skills/visual-audit/SKILL.md +245 -0
- package/ds-canonical/skills/visual-audit/output/.gitkeep +0 -0
- package/ds-canonical/skills/visual-audit/references/audit-architecture.md +100 -0
- package/ds-canonical/skills/visual-audit/references/visual-checklist.md +297 -0
- package/ds-canonical/skills/visual-audit/references/world-class-benchmarks.md +198 -0
- package/package.json +9 -5
- package/src/components/Accordion/accordion.spec.md +114 -0
- package/src/components/Alert/alert.spec.md +197 -0
- package/src/components/AppShell/app-shell.spec.md +331 -0
- package/src/components/AspectRatio/aspect-ratio.spec.md +134 -0
- package/src/components/Avatar/avatar.spec.md +329 -0
- package/src/components/Badge/badge.spec.md +380 -0
- package/src/components/Breadcrumb/breadcrumb.spec.md +257 -0
- package/src/components/BulkActionBar/bulk-action-bar.spec.md +210 -0
- package/src/components/Button/button.spec.md +460 -0
- package/src/components/Calendar/calendar.spec.md +242 -0
- package/src/components/Carousel/carousel.spec.md +253 -0
- package/src/components/Chart/chart.spec.md +155 -0
- package/src/components/Checkbox/checkbox.spec.md +344 -0
- package/src/components/Chip/chip.spec.md +237 -0
- package/src/components/CircularProgress/circular-progress.spec.md +268 -0
- package/src/components/Coachmark/coachmark.spec.md +230 -0
- package/src/components/Combobox/combobox.spec.md +180 -0
- package/src/components/Command/command.spec.md +171 -0
- package/src/components/DataTable/data-table.spec.md +525 -0
- package/src/components/DateGrid/date-grid.spec.md +215 -0
- package/src/components/DatePicker/date-picker.spec.md +334 -0
- package/src/components/DescriptionList/description-list.spec.md +214 -0
- package/src/components/Dialog/dialog.spec.md +202 -0
- package/src/components/DropdownMenu/dropdown-menu.spec.md +250 -0
- package/src/components/Empty/empty.spec.md +214 -0
- package/src/components/Field/field-controls.spec.md +338 -0
- package/src/components/Field/field.spec.md +438 -0
- package/src/components/Field/form-validation.spec.md +152 -0
- package/src/components/FieldControlGroup/field-control-group.spec.md +176 -0
- package/src/components/FileItem/file-item.spec.md +467 -0
- package/src/components/FileUpload/file-upload.spec.md +123 -0
- package/src/components/FileViewer/file-viewer.spec.md +373 -0
- package/src/components/HoverCard/hover-card.spec.md +157 -0
- package/src/components/Input/input.spec.md +193 -0
- package/src/components/LinkInput/link-input.spec.md +130 -0
- package/src/components/Menu/menu-item.spec.md +290 -0
- package/src/components/NameCard/name-card.spec.md +171 -0
- package/src/components/Notice/notice.spec.md +149 -0
- package/src/components/NumberInput/number-input.spec.md +126 -0
- package/src/components/OverflowIndicator/overflow-indicator.spec.md +120 -0
- package/src/components/PeoplePicker/people-picker.spec.md +263 -0
- package/src/components/Popover/popover.spec.md +198 -0
- package/src/components/ProgressBar/progress-bar.spec.md +232 -0
- package/src/components/RadioGroup/radio-group.spec.md +141 -0
- package/src/components/Rating/rating.spec.md +208 -0
- package/src/components/ScrollArea/scroll-area.spec.md +145 -0
- package/src/components/SegmentedControl/segmented-control.spec.md +295 -0
- package/src/components/Select/select.spec.md +299 -0
- package/src/components/SelectMenu/select-menu.spec.md +220 -0
- package/src/components/SelectionControl/selection-item.spec.md +128 -0
- package/src/components/Separator/separator.spec.md +109 -0
- package/src/components/Sheet/sheet.spec.md +148 -0
- package/src/components/Sidebar/sidebar.spec.md +713 -0
- package/src/components/Skeleton/skeleton.spec.md +104 -0
- package/src/components/Slider/slider.spec.md +353 -0
- package/src/components/Steps/steps.spec.md +465 -0
- package/src/components/Switch/switch.spec.md +215 -0
- package/src/components/Tabs/tabs.spec.md +314 -0
- package/src/components/Tag/tag.spec.md +282 -0
- package/src/components/Textarea/textarea.spec.md +151 -0
- package/src/components/TimePicker/time-picker.spec.md +279 -0
- package/src/components/Toast/toast.spec.md +177 -0
- package/src/components/Tooltip/tooltip.spec.md +139 -0
- package/src/components/TreeView/tree-view.spec.md +374 -0
- package/src/patterns/action-bar/action-bar.spec.md +458 -0
- package/src/patterns/element-anatomy/element-anatomy.spec.md +215 -0
- package/src/patterns/element-anatomy/inline-action.spec.md +315 -0
- package/src/patterns/element-anatomy/item-anatomy.spec.md +1042 -0
- package/src/patterns/header-canonical/header-canonical.spec.md +285 -0
- package/src/patterns/horizontal-overflow/horizontal-overflow.spec.md +191 -0
- package/src/patterns/overlay-surface/overlay-surface.spec.md +428 -0
- package/src/patterns/resize-handle/resize-handle.spec.md +109 -0
- package/src/tokens/color/color.spec.md +804 -0
- package/src/tokens/density/density.spec.md +127 -0
- package/src/tokens/elevation/elevation.spec.md +81 -0
- package/src/tokens/layoutSpace/layoutSpace.spec.md +314 -0
- package/src/tokens/motion/motion.spec.md +97 -0
- package/src/tokens/opacity/opacity.spec.md +78 -0
- package/src/tokens/orphan-tokens.spec.md +117 -0
- package/src/tokens/radius/radius.spec.md +123 -0
- package/src/tokens/typography/typography.spec.md +202 -0
- package/src/tokens/uiSize/uiSize.spec.md +438 -0
- package/src/styles/preset.css +0 -31
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for stop_passive_logging.sh — Stop hook orchestrator(5 internal rules:tsc_sanity / harvest_corrections / capture_metrics / governance_drift / infra_best_practice_score)
|
|
3
|
+
#
|
|
4
|
+
# Orchestrator smoke test only — all 5 internal rules are passive(silent log to .claude/logs/*.jsonl,no stderr / no exit non-zero)。
|
|
5
|
+
# Detailed rule tests are within their original lib hooks(now folded into this dispatcher,unit tests at lib level historically)。
|
|
6
|
+
#
|
|
7
|
+
# 2026-05-23 ship per Phase D4 sub-threshold cleanup(15+1 hook tests batch)。
|
|
8
|
+
|
|
9
|
+
set -u
|
|
10
|
+
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
12
|
+
HOOK="$SCRIPT_DIR/../stop_passive_logging.sh"
|
|
13
|
+
|
|
14
|
+
if [ ! -x "$HOOK" ]; then
|
|
15
|
+
echo "FATAL: hook not executable: $HOOK"
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
PASS=0
|
|
20
|
+
FAIL=0
|
|
21
|
+
FAILED_TESTS=""
|
|
22
|
+
|
|
23
|
+
run_hook() {
|
|
24
|
+
local payload="$1"
|
|
25
|
+
STDOUT=$(mktemp); STDERR=$(mktemp)
|
|
26
|
+
set +e
|
|
27
|
+
printf '%s' "$payload" | bash "$HOOK" >"$STDOUT" 2>"$STDERR"
|
|
28
|
+
EXIT=$?
|
|
29
|
+
set -e
|
|
30
|
+
STDOUT_TEXT=$(cat "$STDOUT")
|
|
31
|
+
STDERR_TEXT=$(cat "$STDERR")
|
|
32
|
+
rm -f "$STDOUT" "$STDERR"
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
expect_pass_silent() {
|
|
36
|
+
local name="$1"
|
|
37
|
+
if [ "$EXIT" = "0" ] && [ -z "$STDOUT_TEXT" ] && [ -z "$STDERR_TEXT" ]; then
|
|
38
|
+
echo " PASS $name"; PASS=$((PASS+1))
|
|
39
|
+
else
|
|
40
|
+
echo " FAIL $name (exit=$EXIT, stdout='$STDOUT_TEXT', stderr='$STDERR_TEXT')"
|
|
41
|
+
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
42
|
+
fi
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
expect_exit_0() {
|
|
46
|
+
local name="$1"
|
|
47
|
+
if [ "$EXIT" = "0" ]; then
|
|
48
|
+
echo " PASS $name (exit 0)"; PASS=$((PASS+1))
|
|
49
|
+
else
|
|
50
|
+
echo " FAIL $name (expected exit 0, got $EXIT)"
|
|
51
|
+
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
52
|
+
fi
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
echo "=== stop_passive_logging tests(orchestrator smoke)==="
|
|
56
|
+
|
|
57
|
+
# 1. bash -n syntax check
|
|
58
|
+
bash -n "$HOOK"
|
|
59
|
+
if [ $? = 0 ]; then echo " PASS 1. syntax OK"; PASS=$((PASS+1)); else echo " FAIL 1. syntax broke"; FAIL=$((FAIL+1)); fi
|
|
60
|
+
|
|
61
|
+
# 2. empty JSON input → exit 0 silent
|
|
62
|
+
run_hook '{}'
|
|
63
|
+
expect_exit_0 "2. empty JSON input → exit 0"
|
|
64
|
+
|
|
65
|
+
# 3. session_id only → exit 0
|
|
66
|
+
run_hook '{"session_id":"test-session-abc"}'
|
|
67
|
+
expect_exit_0 "3. session_id input → exit 0"
|
|
68
|
+
|
|
69
|
+
# 4. transcript_path nonexistent → exit 0(graceful)
|
|
70
|
+
run_hook '{"transcript_path":"/tmp/nonexistent-test-transcript.jsonl","session_id":"test"}'
|
|
71
|
+
expect_exit_0 "4. nonexistent transcript → exit 0 graceful"
|
|
72
|
+
|
|
73
|
+
# 5. invalid JSON → exit 0(jq fail handled)
|
|
74
|
+
run_hook 'not-valid-json'
|
|
75
|
+
expect_exit_0 "5. malformed JSON input → exit 0"
|
|
76
|
+
|
|
77
|
+
# 6. valid empty transcript → exit 0
|
|
78
|
+
TMP_TRANSCRIPT=$(mktemp)
|
|
79
|
+
echo '' > "$TMP_TRANSCRIPT"
|
|
80
|
+
run_hook "{\"transcript_path\":\"$TMP_TRANSCRIPT\",\"session_id\":\"test\"}"
|
|
81
|
+
rm -f "$TMP_TRANSCRIPT"
|
|
82
|
+
expect_exit_0 "6. empty transcript file → exit 0"
|
|
83
|
+
|
|
84
|
+
# 7. realistic Stop event payload → exit 0(R3 capture_metrics may write log file,but exit 0 invariant)
|
|
85
|
+
TMP_TRANSCRIPT=$(mktemp)
|
|
86
|
+
cat > "$TMP_TRANSCRIPT" << 'EOF'
|
|
87
|
+
{"type":"user","message":{"role":"user","content":"test"}}
|
|
88
|
+
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"reply"}]}}
|
|
89
|
+
EOF
|
|
90
|
+
run_hook "{\"transcript_path\":\"$TMP_TRANSCRIPT\",\"session_id\":\"test-smoke\"}"
|
|
91
|
+
rm -f "$TMP_TRANSCRIPT"
|
|
92
|
+
expect_exit_0 "7. realistic Stop event payload → exit 0"
|
|
93
|
+
|
|
94
|
+
echo ""
|
|
95
|
+
echo "=== Summary ==="
|
|
96
|
+
echo "Passed: $PASS / $((PASS+FAIL))"
|
|
97
|
+
if [ $FAIL -gt 0 ]; then
|
|
98
|
+
echo -e "Failed:$FAILED_TESTS"
|
|
99
|
+
exit 1
|
|
100
|
+
fi
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Smoke + behavior test for stop_self_audit.sh
|
|
3
|
+
# 2026-04-30:升 BLOCKER 行為(Mechanism 1 claim-verify gap)後加 case 2-4
|
|
4
|
+
set -u
|
|
5
|
+
HOOK="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../stop_self_audit.sh"
|
|
6
|
+
[ -x "$HOOK" ] || { echo "FATAL: hook not executable"; exit 1; }
|
|
7
|
+
|
|
8
|
+
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
|
9
|
+
TMPDIR=$(mktemp -d)
|
|
10
|
+
trap 'rm -rf "$TMPDIR"' EXIT
|
|
11
|
+
|
|
12
|
+
PASS=0; FAIL=0
|
|
13
|
+
run_test() {
|
|
14
|
+
local name="$1"; local expect_block="$2"; local transcript_content="$3"
|
|
15
|
+
local transcript="$TMPDIR/transcript-$$.jsonl"
|
|
16
|
+
printf '%s\n' "$transcript_content" > "$transcript"
|
|
17
|
+
local input
|
|
18
|
+
input=$(printf '{"transcript_path":"%s","session_id":"test"}' "$transcript")
|
|
19
|
+
# Reset state to avoid block-once dedup interference
|
|
20
|
+
rm -f "$PROJECT_DIR/.claude/logs/.last-blocked-claim.txt" 2>/dev/null
|
|
21
|
+
local stdout; stdout=$(echo "$input" | bash "$HOOK" 2>/dev/null)
|
|
22
|
+
if [ "$expect_block" = "1" ]; then
|
|
23
|
+
if echo "$stdout" | grep -q '"decision":"block"'; then
|
|
24
|
+
echo " PASS $name (blocked as expected)"; PASS=$((PASS+1))
|
|
25
|
+
else
|
|
26
|
+
echo " FAIL $name (expected block, got: ${stdout:0:120})"; FAIL=$((FAIL+1))
|
|
27
|
+
fi
|
|
28
|
+
else
|
|
29
|
+
if echo "$stdout" | grep -q '"decision":"block"'; then
|
|
30
|
+
echo " FAIL $name (unexpected block: ${stdout:0:120})"; FAIL=$((FAIL+1))
|
|
31
|
+
else
|
|
32
|
+
echo " PASS $name (no block)"; PASS=$((PASS+1))
|
|
33
|
+
fi
|
|
34
|
+
fi
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
echo "Test 1: minimal payload → no crash"
|
|
38
|
+
out=$(echo '{}' | bash "$HOOK" 2>&1); exit_code=$?
|
|
39
|
+
[ "$exit_code" -le 2 ] && echo " PASS exit=$exit_code" && PASS=$((PASS+1)) || { echo " FAIL exit=$exit_code"; FAIL=$((FAIL+1)); }
|
|
40
|
+
|
|
41
|
+
# Test 2: claim「verified」+ no tsc → BLOCK
|
|
42
|
+
# NOTE(2026-05-01): hook find last 真 user prompt(role=user 且 content
|
|
43
|
+
# 非 tool_result),fixtures 必有 user msg 在 assistant 之前反映真實
|
|
44
|
+
# transcript 結構。
|
|
45
|
+
USER_MSG='{"message":{"role":"user","content":[{"type":"text","text":"幫我修 bug"}]}}'
|
|
46
|
+
|
|
47
|
+
T2="$USER_MSG
|
|
48
|
+
"'{"message":{"role":"assistant","content":[{"type":"text","text":"已修完,verified ✓ 全部 done"}]}}'
|
|
49
|
+
run_test "Test 2: claim+no-verify → block" 1 "$T2"
|
|
50
|
+
|
|
51
|
+
# Test 3: claim「verified」+ tsc 跑過 → no block
|
|
52
|
+
T3="$USER_MSG
|
|
53
|
+
"'{"message":{"role":"assistant","content":[{"type":"text","text":"已修完,verified"}]}}
|
|
54
|
+
{"message":{"role":"assistant","content":[{"type":"tool_use","name":"Bash","input":{"command":"npx tsc -b"}}]}}'
|
|
55
|
+
run_test "Test 3: claim+tsc → no block" 0 "$T3"
|
|
56
|
+
|
|
57
|
+
# Test 4: claim「verified」+「撤回 claim」escape → no block
|
|
58
|
+
T4="$USER_MSG
|
|
59
|
+
"'{"message":{"role":"assistant","content":[{"type":"text","text":"先前 verified 說錯,撤回 claim,實際未修好"}]}}'
|
|
60
|
+
run_test "Test 4: claim+retract escape → no block" 0 "$T4"
|
|
61
|
+
|
|
62
|
+
# Test 5: 純對話無 claim → no block
|
|
63
|
+
T5="$USER_MSG
|
|
64
|
+
"'{"message":{"role":"assistant","content":[{"type":"text","text":"我來看看這個 bug 是怎麼回事"}]}}'
|
|
65
|
+
run_test "Test 5: no claim → no block" 0 "$T5"
|
|
66
|
+
|
|
67
|
+
# Test 6: claim-denial「明確不 claim verified」preemptive denial → no block
|
|
68
|
+
T6="$USER_MSG
|
|
69
|
+
"'{"message":{"role":"assistant","content":[{"type":"text","text":"我這次明確不 claim verified,只 tsc 過,實際 browser 行為要 user 驗"}]}}'
|
|
70
|
+
run_test "Test 6: preemptive claim denial → no block" 0 "$T6"
|
|
71
|
+
|
|
72
|
+
# Cleanup state file
|
|
73
|
+
rm -f "$PROJECT_DIR/.claude/logs/.last-blocked-claim.txt" 2>/dev/null
|
|
74
|
+
|
|
75
|
+
echo "Results: $PASS PASS, $FAIL FAIL"
|
|
76
|
+
[ "$FAIL" -eq 0 ] || exit 1
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Smoke test for stop_tsc_sanity.sh
|
|
3
|
+
set -u
|
|
4
|
+
# Cluster B merge(2026-05-10):stop_tsc_sanity.sh fold 進 stop_passive_logging.sh dispatcher R1。
|
|
5
|
+
HOOK="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../stop_passive_logging.sh"
|
|
6
|
+
[ -x "$HOOK" ] || { echo "FATAL"; exit 1; }
|
|
7
|
+
echo "Test 1: minimal payload → no crash"
|
|
8
|
+
STDOUT=$(echo '{}' | bash "$HOOK" 2>&1); EXIT=$?
|
|
9
|
+
[ "$EXIT" -le 2 ] && echo " PASS exit=$EXIT" || { echo " FAIL exit=$EXIT out=${STDOUT:0:100}"; exit 1; }
|
|
10
|
+
echo "Results: 1 PASS, 0 FAIL"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# .claude/references/ Charter
|
|
2
|
+
|
|
3
|
+
## 這裡只收:**agent infrastructure reference**(非 product canonical)
|
|
4
|
+
|
|
5
|
+
Agent 在執行時按需讀的深度 reference 檔 — audit protocol / FP 記憶 / workflow recipe / lookup tables。**不是 product design canonical**(那該進 spec.md / CLAUDE.md)。
|
|
6
|
+
|
|
7
|
+
## 當前居民(15 檔,2026-05-18 update)
|
|
8
|
+
|
|
9
|
+
| Ref | 用途 |
|
|
10
|
+
|-----|------|
|
|
11
|
+
| `audit-coverage-vs-24-checklist.md` | 業界 24-checklist 對照 + 為何不平行 audit 24 dim rationale |
|
|
12
|
+
| `build-ui-canonicals.md` | 建 UI 前 12 情境 + 8 layout primitive lookup |
|
|
13
|
+
| `cva-patterns.md` | cva 適用 / 不適用 + 例外清單(跟 CLAUDE.md shadcn 規範互補) |
|
|
14
|
+
| `drag-canonical.md` | 世界級 drag impl 對照 + dnd-kit collision strategy + Phase 1/2 fix plan |
|
|
15
|
+
| `item-anatomy-recipe.md` | 7 步建立新 row primitive workflow + audit grep guard |
|
|
16
|
+
| `naming-conventions.md` | 命名詳表 + 禁止清單(CLAUDE.md # 命名一致性 pointer) |
|
|
17
|
+
| `principle-dim-map.json` | M-rule / trait / hook → audit dim explicit mapping(SSOT for dim coverage) |
|
|
18
|
+
| `props-naming.md` | Props callback / Badge / icon canonical 詳表 |
|
|
19
|
+
| `spec-rules.md` | SSOT 機制 / 邊界案例 scope default 詳展 |
|
|
20
|
+
| `ssot-consultation.md` | SSOT 消費完整對照表 |
|
|
21
|
+
| `ssot-index.md` | High-risk interface ownership map(propose 前 grep 找 owner) |
|
|
22
|
+
| `structural-token-retention.md` | 6 類結構性保留 token canonical(audit Dim 48 triple-verify) |
|
|
23
|
+
| `tailwind-gotchas.md` | Tailwind v4 / tailwind-merge 技術陷阱深展 |
|
|
24
|
+
| `ui-dev-rules.md` | flex slot 幾何 / 數值前先查 / Padding 三層 / Icon size 三類 |
|
|
25
|
+
|
|
26
|
+
## 這裡**不收**(反例 + 正確去處)
|
|
27
|
+
|
|
28
|
+
| 疑似要放這但其實不是 | 正確去處 | 為什麼 |
|
|
29
|
+
|---------------------|---------|--------|
|
|
30
|
+
| 設計 canonical judgment(non-programmable)| `spec.md` 或 CLAUDE.md | 2-home 架構:spec / tsx 才是 canonical home。AI 做產品時**必讀** spec,不會必讀 references |
|
|
31
|
+
| 實作值 / 計算公式 | tsx / cva / CSS | programmable rule 進 code |
|
|
32
|
+
| 跨 session 狀態 | `memory/` | references 不是 state 檔 |
|
|
33
|
+
| 多步驟 workflow + checkpoint | `.claude/skills/` | skill 管 workflow,reference 是 skill 按需讀的 |
|
|
34
|
+
|
|
35
|
+
## 新 reference 的 criteria
|
|
36
|
+
|
|
37
|
+
1. **Audit / skill 按需查的 lookup data**(表格 / 詳細對照 / 反例清單)
|
|
38
|
+
2. **不含 canonical judgment**(判斷 rule 在 spec / CLAUDE.md)
|
|
39
|
+
3. **被 ≥ 1 skill / CLAUDE.md / spec cite**(orphan file 不收,定期 prune 會 retire)
|
|
40
|
+
|
|
41
|
+
## 2026-04-24 Lesson
|
|
42
|
+
|
|
43
|
+
前曾把 canonical judgment(24px threshold / disabled state 策略 / primitive exposure 3 題)錯搬到 references,違反 2-home 架構(spec 該是 canonical home 讓 AI 做產品時讀)。Restored 回 spec。references 現在嚴格只收 agent-use lookup。
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Audit 覆蓋 vs 業界 24 節 checklist —— 對照 + 決策
|
|
2
|
+
|
|
3
|
+
**Date**: 2026-04-24
|
|
4
|
+
**Trigger**: User 問「我們稽核缺了哪些?」→ 用業界通用 24 節 checklist 做 gap 分析
|
|
5
|
+
**本 doc 目的**: 釘住「為什麼不補某些項」的 rationale,避免下次又被誤認為缺口
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 核心洞察 — Dim 9 是 multiplier
|
|
10
|
+
|
|
11
|
+
**「符合 shadcn / Radix primitive 框架」這條 audit(`/design-system-audit` Dim 9)驗過 → 自動吃掉 24 節中 8 節大部分**。
|
|
12
|
+
|
|
13
|
+
這是 M1「SSOT」+ mindset #2「優先消費既有」在 meta 層的體現:shadcn + Radix = 我們的 framework SSOT,它一致 = 下游一致,不必平行補 24 dim。
|
|
14
|
+
|
|
15
|
+
| 24-checklist # | 被 Dim 9 / Radix 吸收的原因 |
|
|
16
|
+
|---|---|
|
|
17
|
+
| #4 Ref | shadcn 強制 `forwardRef` + `displayName`,Dim 9 必驗 |
|
|
18
|
+
| #5 Composition | shadcn 強制 `asChild` + Slot + `{...props}` spread |
|
|
19
|
+
| #6 HTML 語意 | Radix primitive 用對 `<button>` / `<a>` / `[role]` |
|
|
20
|
+
| #7 A11y 核心 | Radix 內建 keyboard / ARIA / SR |
|
|
21
|
+
| #8 state 大半 | Radix forwards `data-state="open/closed/checked"` |
|
|
22
|
+
| #11 Overlay focus trap / portal | Radix DialogPortal / Popover 內建 |
|
|
23
|
+
| #12 form native props | `{...props}` spread 到 native input |
|
|
24
|
+
| #1 native HTML attributes | `{...props}` spread 解 |
|
|
25
|
+
|
|
26
|
+
## 被 tsconfig + Vite + ESM 架構吸收
|
|
27
|
+
|
|
28
|
+
| 項目 | 吸收者 |
|
|
29
|
+
|---|---|
|
|
30
|
+
| #2 TS 大半 | `strict / noUnusedLocals / noUnusedParameters / noFallthroughCasesInSwitch / noUncheckedSideEffectImports` |
|
|
31
|
+
| #19 Package export | `type: module` + Vite dev/build + 無 barrel |
|
|
32
|
+
| #16 SSR | **不適用**(Vite SPA 不是 Next/Remix) |
|
|
33
|
+
| #14 unmount / listener cleanup 大半 | React strict mode dev 雙 mount + tsc useEffect deps |
|
|
34
|
+
|
|
35
|
+
## 刻意不補 — 架構決策
|
|
36
|
+
|
|
37
|
+
| 項目 | 不補的 rationale |
|
|
38
|
+
|---|---|
|
|
39
|
+
| #17 unit test | 走 **story-as-test + visual-regression**(stories + `/visual-audit` Layer A + M11 interactive state walk)。補 unit = 重複 story 覆蓋,`/story-writing` earn-existence 原則視其為 noise |
|
|
40
|
+
| #19 CJS 輸出 | 內部 DS 非發 npm package,CJS 是 dead requirement |
|
|
41
|
+
| #22 cross-browser full matrix | Firefox / IE 不是我們受眾;iOS Safari 有 Radix ensures 大半。補全 matrix = 過度 |
|
|
42
|
+
| #20 CVE 全套 | 內部 DS 非 public npm,補 `npm audit` weekly cron 夠 |
|
|
43
|
+
|
|
44
|
+
## 真缺 + 已補(2026-04-24)
|
|
45
|
+
|
|
46
|
+
| 真缺項 | 補的形式 | Commit |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| #13 i18n 硬寫字串 | `.claude/hooks/check_hardcoded_strings.sh` PostToolUse,flag DS primitive tsx(非 stories)CJK ≥ 3 chars / 英文 sentence-case label;支援 `// i18n-allow: {rationale}` 白名單 | 本次 session |
|
|
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
|
+
| #23 edge case(null / empty / rapid / success) | `/ux-audit` Phase 5 從 3 態 → 5 態 + null-safety + rapid-interaction + edge case corollary | 本次 session |
|
|
51
|
+
|
|
52
|
+
## 未補 — 以後真需要再補
|
|
53
|
+
|
|
54
|
+
| 項目 | trigger 條件 |
|
|
55
|
+
|---|---|
|
|
56
|
+
| #22 cross-browser 抽測 | 第一個 Safari-specific bug 落地 → 建 weekly Playwright Safari smoke test |
|
|
57
|
+
| #20 `npm audit` cron | 第一次 dep CVE 被通知 → schedule `npm audit` weekly report |
|
|
58
|
+
| RTL 支援 | 第一個 RTL 產品需求 → 補 RTL audit dim + 測 logical properties |
|
|
59
|
+
| Next.js / Remix 整合 | DS 要發 npm 時 → 補 `use client` boundary + SSR 測試 |
|
|
60
|
+
|
|
61
|
+
## 為什麼不寫成 24 dim 平行 audit
|
|
62
|
+
|
|
63
|
+
**`/design-system-audit` 若膨脹成 24 dim** → 平行跑 24 個 sub-agent 每個吐 400-字 report → user cognitive load 爆 + 重複判斷(e.g. #4 Ref / #5 Composition 都是 shadcn 已驗的)。正確姿態:
|
|
64
|
+
|
|
65
|
+
1. **Framework audit(Dim 9)嚴格化** = 一條驗過 cascade 吸收 8 節
|
|
66
|
+
2. **新 dim 只為真無法從 framework 推導的 gap**(i18n / controlled-uncontrolled / edge case 三個)
|
|
67
|
+
3. **FAQ / 常被問到但已覆蓋的項**寫本 doc,下次 user 問「我們缺 X 嗎」先讀本 doc 再答
|
|
68
|
+
|
|
69
|
+
## Cross-link
|
|
70
|
+
|
|
71
|
+
- CLAUDE.md `# 稽核 canonical` 3-tier × 6-dim
|
|
72
|
+
- CLAUDE.md Meta-Pattern M1(SSOT)+ M8(benchmark)+ M10(exhaustive scan)
|
|
73
|
+
- `.claude/skills/design-system-audit/SKILL.md` Groups A-J
|
|
74
|
+
- `.claude/skills/ux-audit/SKILL.md` Phase 5
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# 建立 UI 前的 DS canonical 對照(從 CLAUDE.md 拆出的完整對照)
|
|
2
|
+
|
|
3
|
+
本檔是 `.claude/rules/ui-development.md`「建立 UI 前必讀」的**完整對照表**。Rule 主章只留「超級規則 + 自我檢查腳本」,遇到具體情境要查對照時讀本檔。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 既有 DS 元件 / primitive 優先消費(完整表)
|
|
8
|
+
|
|
9
|
+
**超級規則**:**`ls packages/design-system/src/components/` + `ls packages/design-system/src/patterns/` 看一次。任何視覺 / 行為命中既有元件 → 必消費,不 hand-craft raw HTML 繞過**。
|
|
10
|
+
|
|
11
|
+
### 常見手刻 vs canonical 對照
|
|
12
|
+
|
|
13
|
+
| 情境 | ❌ anti-pattern(手刻) | ✅ canonical(用 DS) |
|
|
14
|
+
|------|---------------------|---------------------|
|
|
15
|
+
| Select / 下拉選單 | `<Popover><PopoverContent><button className="flex items-center px-2">...</button></PopoverContent></Popover>` | `<Select options={...} />` or `<DropdownMenu><DropdownMenuItem>` |
|
|
16
|
+
| Input 欄位 | `<input className="h-field-sm w-20 pl-3 pr-7 border ..." />` | `<Input size="sm" />` or `<NumberInput />` |
|
|
17
|
+
| 列表項目 row(icon + text + action) | `<div className="flex items-center gap-2"><Icon/><span/><Button/></div>` | `<MenuItem>` + slot components(`<ItemIcon>` / `<ItemLabel>` / `<ItemSuffix>`) |
|
|
18
|
+
| 資料表格(含 header / sorting / sticky) | `<table><thead>...</thead><tbody>...</tbody></table>` | `<DataTable columns={...} data={...} />` |
|
|
19
|
+
| 檔案上傳列表 | `<div>filename</div><ProgressBar /><Paperclip />` | `<FileItem mode="compact" />` or `<FileUpload>` |
|
|
20
|
+
| 表單欄位(label + control + error) | `<label>...</label><input/><span className="text-error">...</span>` | `<Field><FieldLabel>...<Input />...<FieldError/>` |
|
|
21
|
+
| 全頁 / 區域 loading | `<div className="absolute inset-0 flex center"><Spinner /></div>` | `<Empty icon={<CircularProgress />} description="..." />` |
|
|
22
|
+
| 確認對話框 | raw `<div className="fixed inset-0 bg-black/50">...<button>OK</button>` | `<Dialog>` + `<DialogHeader>` etc |
|
|
23
|
+
| 分隔線 | `<hr className="..." />` or `<div className="h-px bg-..."/>` | `<Separator />`(必要時)or CSS border(見 separator.spec) |
|
|
24
|
+
| 標籤分類 / 狀態 chip | `<span className="inline-flex px-2 py-0.5 bg-... rounded">...</span>` | `<Tag variant="..." />` or `<Badge />` |
|
|
25
|
+
| 使用者頭像 | `<img className="w-8 h-8 rounded-full" />` | `<Avatar>` |
|
|
26
|
+
| 浮層(彈出資訊) | `<div className="absolute bg-white shadow p-3">...</div>` | `<Popover>` / `<HoverCard>` / `<Tooltip>`(視語義選) |
|
|
27
|
+
| 浮層 media + title + description + actions | 自組 `<div>` 結構 | `<Coachmark>` 或 `<Dialog>`(視是否阻斷) |
|
|
28
|
+
|
|
29
|
+
**Story 特別提醒**:**stories 也是 code**。如果 story 在 label / comment 說「DataTable cell 用法」「Table 配額」「Menu 選單」等,**要 render 真的該元件 demo,不可用 raw `<table>` / raw `<button>` 假裝**。否則 story 教壞 consumer、自己也在破壞 DS 訓練資料。
|
|
30
|
+
|
|
31
|
+
`check_story_anatomy.sh` hook 會在 Write/Edit 階段攔下這類手刻;allowlist `// @anatomy-exempt: <reason>`(檔首)/ `// @anatomy-exempt-next`(下一行)可豁免教學用 raw primitive。
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Layout primitive 特別子集(建立 pattern-level 新元件前 mechanical 掃)
|
|
36
|
+
|
|
37
|
+
以下是 **pattern-level** primitives(跨元件共用的視覺結構),建立新元件前必查。若新元件的視覺結構命中任一 row 的 pattern → **必消費該 primitive**,不自己重寫一套。漏掉 = 雙邊漂移 bug(改一邊另一邊失效)。
|
|
38
|
+
|
|
39
|
+
| 視覺 pattern | 既有 primitive | 典型觸發情境 |
|
|
40
|
+
|------|---------|---------|
|
|
41
|
+
| 單列 row:prefix(icon/avatar) + content + suffix(action) | `patterns/element-anatomy/item-anatomy.*` — `<MenuItem>` canonical + slot components | 任何「列表項目」元件(Menu/Tree/Sidebar/TableRow/StepItem/FileItem...) |
|
|
42
|
+
| 浮層容器的 Header + Body + Footer(border-b/t + padding token) | `patterns/overlay-surface/` — `SurfaceHeader/Body/Footer` | Dialog / Popover / Drawer / Sheet / 任何 elevation-200 浮層的結構化 sub-components |
|
|
43
|
+
| **垂直居中 icon + title + description(+ action)** | `components/Empty/` — `<Empty>` 元件 | **「告訴使用者狀態」的 surface**:空資料 / 拖放邀請(FileUpload)/ 錯誤 / 首次引導 / 無權限 / 載入佔位(非 Skeleton)|
|
|
44
|
+
| 橫向操作按鈕列(gap-2 分組)| `patterns/action-bar/` | Toolbar、page header actions、form footer buttons |
|
|
45
|
+
| 水平溢出處理(捲動/收合,**隱藏捲軸+ fade-mask** UX)| `patterns/horizontal-overflow/` | Tabs / ChipGroup / 未來 Steps 的溢出(刻意隱藏 scrollbar) |
|
|
46
|
+
| **跨 OS 一致 overlay 捲軸(顯示捲軸但不吃寬度)** | `components/ScrollArea/` | DataTable 水平捲動 / Sheet / Dialog body / Sidebar 長 nav 等需要使用者知道有捲軸又要跨 OS 視覺一致 |
|
|
47
|
+
| **固定長寬比容器(防 CLS 坍塌,多張圖統一 ratio)** | `components/AspectRatio/` | Coachmark media / Carousel item image / Card thumbnail / Chart container(override default 16:9) |
|
|
48
|
+
| Field wrapper(border + padding + startIcon + endAction 結構) | `components/Field/field-wrapper.tsx` + `field-controls.spec.md` | 所有單行可編輯欄位元件 |
|
|
49
|
+
|
|
50
|
+
### 自我檢查腳本(CLAUDE.md 保留這節的精簡版,完整對照在本檔上表)
|
|
51
|
+
|
|
52
|
+
- 新元件有 icon+text 垂直堆疊? → 用 `<Empty>`,不自己畫 icon + title + desc
|
|
53
|
+
- 新元件有橫向 row 結構(prefix/content/suffix)? → 用 `element-anatomy/item-anatomy` 的 `<MenuItem>` + slot components(`<ItemIcon>` / `<ItemAvatar>` / `<ItemLabel>` / `<ItemSuffix>` / `<ItemInlineAction>`)
|
|
54
|
+
- 新元件是浮層 + 有 header/body/footer? → 用 `overlay-surface`
|
|
55
|
+
- 新元件內容**可能溢出容器且需要使用者捲動**? → 用 `ScrollArea`(跨 OS 一致 overlay 捲軸);若是刻意隱藏捲軸 + fade-mask → 用 `horizontal-overflow` pattern
|
|
56
|
+
- 新元件有**圖像 / media 容器需要鎖定長寬比**(防 CLS、統一多張圖比例)? → 用 `AspectRatio` primitive,不硬寫 `aspect-video` / `aspect-square` class
|
|
57
|
+
- 以上都沒命中 → 才可自建,但 **建完要立刻回來加行**(防下一個人又重造輪子)
|
|
58
|
+
- **本規則同樣適用 story / consumer / exploration code**:不 hand-craft 已有 prop 能做的事(如 Input loading 走 `loading` prop 不自刻 `<div className="relative"><input/><div className="absolute">` / 全頁 loading 走 `<Empty icon={<CircularProgress/>}/>` 不自刻 `absolute inset-0`)。遇缺口**回元件 spec 擴 API**,不自刻繞過 — hand-craft 視覺對齊 bug 上游
|
|
59
|
+
|
|
60
|
+
具體 anti-pattern signals → `/design-system-audit` Dim 21;pixel-level 視覺 regression(API 用對但視覺仍跑掉)tech debt → memory `project_pending_tasks`。
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## overflow 使用三規則(避免跨 OS 跑版)
|
|
65
|
+
|
|
66
|
+
1. Design-system 元件 `.tsx` 內**禁止** raw `overflow-auto / overflow-scroll / overflow-{x,y}-{auto,scroll}`(hook `check_token_hygiene.sh` check #4 守衛)
|
|
67
|
+
2. 需捲軸且跨 OS 一致 → 用 `ScrollArea`
|
|
68
|
+
3. 刻意隱藏捲軸 + fade-mask → 用 `horizontal-overflow` pattern
|
|
69
|
+
4. 例外:`overlay-surface` spec 明文允許 Dialog body `flex-1 overflow-y-auto`(viewport-fill 特殊 context);若未來此場景需跨 OS 一致,遷移 ScrollArea 再更新 spec
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# cva 適用範圍 完整對照(從 CLAUDE.md 拆出)
|
|
2
|
+
|
|
3
|
+
`.claude/rules/ui-development.md`「shadcn 元件規範」 留判斷法 + 禁止一句話;完整對照表和 documented 例外在本檔。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 變體 × 實作模式對照
|
|
8
|
+
|
|
9
|
+
`cva()` 是系統管理 **className 變體**的標準工具,但**不是所有變體都該用 cva**。合法的**非 cva** 實作模式:
|
|
10
|
+
|
|
11
|
+
| 變體類型 | 實作方式 | 範例 |
|
|
12
|
+
|---------|---------|------|
|
|
13
|
+
| className 變體(bg / text / border / size / state) | **`cva()`** | Button / SegmentedControl / Chip / Tag / Field Controls 等絕大多數 |
|
|
14
|
+
| **Style prop 驅動的 variant**(需要 `style={{ backgroundColor: 'var(--...)' }}`)| **Object map / lookup table**(world-class:Material / Ant / Polaris 同樣做法) | **Avatar** 的 color variants 驅動 inline style;cva 無法產 style object |
|
|
15
|
+
| **結構性變體**(不同 mode 是不同 layout,不只 class swap) | **Conditional rendering / sub-components** | **FileItem** 的 `compact / rich` mode 有不同 flex 結構 |
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 當前系統 documented 例外
|
|
20
|
+
|
|
21
|
+
- **`Avatar`**:color variants 用 object map(原因:inline style prop;cva 無法產 style object)
|
|
22
|
+
- **`FileItem`**:mode variants 用 if-branches(原因:結構性差異,不是 class swap;compact vs rich 是不同 flex 樹)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 新增例外判斷法
|
|
27
|
+
|
|
28
|
+
要加例外(= 某元件變體不用 cva)前先問:
|
|
29
|
+
1. 變體差異 **真的需要 inline style** 嗎?(有些看似需要其實可用 CSS variable + data attribute 解)
|
|
30
|
+
2. **結構性差異**夠大嗎?(只差一個 slot 可以 cva + `data-mode` 選擇器;不同 root layout 才算結構)
|
|
31
|
+
3. 世界級 DS(Material / Ant / Polaris)怎麼處理同類變體?
|
|
32
|
+
|
|
33
|
+
若答案 3 題都指向「非 cva」,加 documented 例外 + 更新本檔。否則先嘗試 cva。
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 禁止
|
|
38
|
+
|
|
39
|
+
- ❌ 為了「一律用 cva」硬把 style prop 變體塞進 cva(無法優雅產出 style object)
|
|
40
|
+
- ❌ 為了「一律用 cva」把不同結構的 mode 強制壓到同一棵 JSX 配 className 切換(code 會長滿 `{mode === 'rich' && ...}` hacks)
|
|
41
|
+
- ❌ 「新例外」沒寫進本檔的 documented 例外清單(= 隱性 drift)
|