@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,143 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for block_prototype_imports.py
|
|
3
|
+
#
|
|
4
|
+
# This hook is PostToolUse — reads files from disk via os.path.exists, so we
|
|
5
|
+
# create real temp files inside src/ tree to drive each scenario.
|
|
6
|
+
#
|
|
7
|
+
# Usage: bash test_block_prototype_imports.sh
|
|
8
|
+
|
|
9
|
+
set -u
|
|
10
|
+
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
12
|
+
HOOK="$SCRIPT_DIR/../block_prototype_imports.py"
|
|
13
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
|
14
|
+
|
|
15
|
+
if [ ! -f "$HOOK" ]; then
|
|
16
|
+
echo "FATAL: hook not found: $HOOK"
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
PASS=0
|
|
21
|
+
FAIL=0
|
|
22
|
+
FAILED_TESTS=""
|
|
23
|
+
|
|
24
|
+
# Sandbox dir for temp files inside src/ (so should_check passes prefix gate)
|
|
25
|
+
SANDBOX="$PROJECT_ROOT/src/.test-block-prototype-imports-$$"
|
|
26
|
+
mkdir -p "$SANDBOX"
|
|
27
|
+
trap 'rm -rf "$SANDBOX"' EXIT
|
|
28
|
+
|
|
29
|
+
run_hook() {
|
|
30
|
+
local file_path="$1"
|
|
31
|
+
local payload
|
|
32
|
+
payload=$(jq -n --arg fp "$file_path" \
|
|
33
|
+
'{tool_name: "Write", tool_input: {file_path: $fp}}')
|
|
34
|
+
|
|
35
|
+
STDOUT=$(mktemp)
|
|
36
|
+
STDERR=$(mktemp)
|
|
37
|
+
set +e
|
|
38
|
+
printf '%s' "$payload" | python3 "$HOOK" >"$STDOUT" 2>"$STDERR"
|
|
39
|
+
EXIT=$?
|
|
40
|
+
set -e
|
|
41
|
+
STDOUT_TEXT=$(cat "$STDOUT")
|
|
42
|
+
STDERR_TEXT=$(cat "$STDERR")
|
|
43
|
+
rm -f "$STDOUT" "$STDERR"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
expect_pass() {
|
|
47
|
+
local name="$1"
|
|
48
|
+
if [ "$EXIT" = "0" ]; then
|
|
49
|
+
echo " PASS $name"
|
|
50
|
+
PASS=$((PASS+1))
|
|
51
|
+
else
|
|
52
|
+
echo " FAIL $name (expected exit 0, got $EXIT)"
|
|
53
|
+
echo "$STDOUT_TEXT" | sed 's/^/ /'
|
|
54
|
+
FAIL=$((FAIL+1))
|
|
55
|
+
FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
56
|
+
fi
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
expect_block() {
|
|
60
|
+
local name="$1"
|
|
61
|
+
local needle="$2"
|
|
62
|
+
if [ "$EXIT" = "2" ]; then
|
|
63
|
+
if echo "$STDOUT_TEXT" | grep -qF "$needle"; then
|
|
64
|
+
echo " PASS $name"
|
|
65
|
+
PASS=$((PASS+1))
|
|
66
|
+
else
|
|
67
|
+
echo " FAIL $name (exit 2 OK but stdout missing '$needle')"
|
|
68
|
+
echo "$STDOUT_TEXT" | sed 's/^/ /'
|
|
69
|
+
FAIL=$((FAIL+1))
|
|
70
|
+
FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
71
|
+
fi
|
|
72
|
+
else
|
|
73
|
+
echo " FAIL $name (expected exit 2, got $EXIT)"
|
|
74
|
+
echo "$STDOUT_TEXT" | sed 's/^/ /'
|
|
75
|
+
FAIL=$((FAIL+1))
|
|
76
|
+
FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
77
|
+
fi
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
cd "$PROJECT_ROOT"
|
|
81
|
+
|
|
82
|
+
# ── Test 1: clean import → pass ──────────────────────────────────────────────
|
|
83
|
+
echo "Test 1: clean tsx with non-explorations import → pass"
|
|
84
|
+
F1="$SANDBOX/clean.tsx"
|
|
85
|
+
cat >"$F1" <<'EOF'
|
|
86
|
+
import { Button } from '@/design-system/components/Button/button'
|
|
87
|
+
export const X = () => <Button>OK</Button>
|
|
88
|
+
EOF
|
|
89
|
+
run_hook "${F1#$PROJECT_ROOT/}"
|
|
90
|
+
expect_pass "Test 1 clean import"
|
|
91
|
+
|
|
92
|
+
# ── Test 2: import from src/explorations → block ─────────────────────────────
|
|
93
|
+
echo ""
|
|
94
|
+
echo "Test 2: tsx imports from src/explorations/ → block"
|
|
95
|
+
F2="$SANDBOX/violation.tsx"
|
|
96
|
+
cat >"$F2" <<'EOF'
|
|
97
|
+
import { ProtoX } from '@/explorations/foo/bar'
|
|
98
|
+
import { Button } from '@/design-system/components/Button/button'
|
|
99
|
+
export const X = () => <ProtoX />
|
|
100
|
+
EOF
|
|
101
|
+
run_hook "${F2#$PROJECT_ROOT/}"
|
|
102
|
+
expect_block "Test 2 explorations import blocked" "Blocked"
|
|
103
|
+
|
|
104
|
+
# ── Test 3: file inside src/explorations/ itself → exempt (pass) ──────────────
|
|
105
|
+
echo ""
|
|
106
|
+
echo "Test 3: file IN src/explorations/ importing from explorations → pass (allowed)"
|
|
107
|
+
EXPL_DIR="$PROJECT_ROOT/src/explorations/.test-block-prototype-imports-$$"
|
|
108
|
+
mkdir -p "$EXPL_DIR"
|
|
109
|
+
F3="$EXPL_DIR/proto.tsx"
|
|
110
|
+
cat >"$F3" <<'EOF'
|
|
111
|
+
import { Other } from '@/explorations/other'
|
|
112
|
+
export const Y = () => <Other />
|
|
113
|
+
EOF
|
|
114
|
+
run_hook "${F3#$PROJECT_ROOT/}"
|
|
115
|
+
EXIT_CAPTURED=$EXIT
|
|
116
|
+
rm -rf "$EXPL_DIR"
|
|
117
|
+
EXIT=$EXIT_CAPTURED
|
|
118
|
+
expect_pass "Test 3 explorations file is exempt"
|
|
119
|
+
|
|
120
|
+
# ── Test 4: non-tsx file (md) → pass ─────────────────────────────────────────
|
|
121
|
+
echo ""
|
|
122
|
+
echo "Test 4: .md file (out of scope) → pass"
|
|
123
|
+
F4="$SANDBOX/note.md"
|
|
124
|
+
echo "import from src/explorations/foo (just text)" >"$F4"
|
|
125
|
+
run_hook "${F4#$PROJECT_ROOT/}"
|
|
126
|
+
expect_pass "Test 4 non-tsx out of scope"
|
|
127
|
+
|
|
128
|
+
# ── Test 5: nonexistent path → pass (silently skip) ──────────────────────────
|
|
129
|
+
echo ""
|
|
130
|
+
echo "Test 5: nonexistent path → pass (silently skip)"
|
|
131
|
+
run_hook "src/does-not-exist-$$.tsx"
|
|
132
|
+
expect_pass "Test 5 nonexistent path"
|
|
133
|
+
|
|
134
|
+
# ── Summary ──────────────────────────────────────────────────────────────────
|
|
135
|
+
echo ""
|
|
136
|
+
echo "════════════════════════════════════════"
|
|
137
|
+
echo " Results: $PASS PASS, $FAIL FAIL"
|
|
138
|
+
echo "════════════════════════════════════════"
|
|
139
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
140
|
+
printf "Failed tests:%b\n" "$FAILED_TESTS"
|
|
141
|
+
exit 1
|
|
142
|
+
fi
|
|
143
|
+
exit 0
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for check_app_shell_primary_header_consistency.sh
|
|
3
|
+
#
|
|
4
|
+
# Hook(PreToolUse Edit/Write):偵測 AppShell consumer 2 violations:
|
|
5
|
+
# V1 layout="primary-header" 缺 globalHeader prop
|
|
6
|
+
# V2 layout="primary-header" + 同 file 含 <SidebarHeader>
|
|
7
|
+
#
|
|
8
|
+
# Hook 透過 CLAUDE_TOOL_INPUT env var 讀 tool_input(JSON {tool_name, tool_input})
|
|
9
|
+
# 且需 TARGET file 真實存在於 disk(`[[ ! -f "$TARGET" ]] && exit 0`)。
|
|
10
|
+
# 排除:.spec.md / *test* / app-shell.tsx 自身 / `@app-shell-primary-header-allow:` escape。
|
|
11
|
+
# Violation 時 stderr「🚨 AppShell primary-header consistency violation」+ exit 2。
|
|
12
|
+
|
|
13
|
+
set -u
|
|
14
|
+
|
|
15
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
16
|
+
HOOK="$SCRIPT_DIR/../check_app_shell_primary_header_consistency.sh"
|
|
17
|
+
TMPDIR_TEST=$(mktemp -d)
|
|
18
|
+
trap 'rm -rf "$TMPDIR_TEST"' EXIT
|
|
19
|
+
|
|
20
|
+
if [ ! -x "$HOOK" ]; then chmod +x "$HOOK" 2>/dev/null || true; fi
|
|
21
|
+
if [ ! -f "$HOOK" ]; then echo "FATAL: hook not found: $HOOK"; exit 1; fi
|
|
22
|
+
|
|
23
|
+
PASS=0
|
|
24
|
+
FAIL=0
|
|
25
|
+
FAILED_TESTS=""
|
|
26
|
+
|
|
27
|
+
# Helper: write file to test temp dir, run hook with that path
|
|
28
|
+
run_hook_on_file() {
|
|
29
|
+
local rel="$1"; local content="$2"
|
|
30
|
+
local fp="$TMPDIR_TEST/$rel"
|
|
31
|
+
mkdir -p "$(dirname "$fp")"
|
|
32
|
+
printf '%s' "$content" > "$fp"
|
|
33
|
+
local payload
|
|
34
|
+
payload=$(jq -n --arg fp "$fp" --arg tn "Edit" \
|
|
35
|
+
'{tool_name: $tn, tool_input: {file_path: $fp, new_string: ""}}')
|
|
36
|
+
STDOUT=$(mktemp); STDERR=$(mktemp)
|
|
37
|
+
set +e
|
|
38
|
+
CLAUDE_TOOL_INPUT="$payload" bash "$HOOK" >"$STDOUT" 2>"$STDERR" </dev/null
|
|
39
|
+
EXIT=$?
|
|
40
|
+
set -e
|
|
41
|
+
STDERR_TEXT=$(cat "$STDERR")
|
|
42
|
+
rm -f "$STDOUT" "$STDERR"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# Helper: run with arbitrary path (non-existent) for skip tests
|
|
46
|
+
run_hook_no_file() {
|
|
47
|
+
local fp="$1"; local tool="${2:-Edit}"
|
|
48
|
+
local payload
|
|
49
|
+
payload=$(jq -n --arg fp "$fp" --arg tn "$tool" \
|
|
50
|
+
'{tool_name: $tn, tool_input: {file_path: $fp, new_string: ""}}')
|
|
51
|
+
STDOUT=$(mktemp); STDERR=$(mktemp)
|
|
52
|
+
set +e
|
|
53
|
+
CLAUDE_TOOL_INPUT="$payload" bash "$HOOK" >"$STDOUT" 2>"$STDERR" </dev/null
|
|
54
|
+
EXIT=$?
|
|
55
|
+
set -e
|
|
56
|
+
STDERR_TEXT=$(cat "$STDERR")
|
|
57
|
+
rm -f "$STDOUT" "$STDERR"
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
expect_pass_silent() {
|
|
61
|
+
local name="$1"
|
|
62
|
+
if [ "$EXIT" = "0" ] && [ -z "$STDERR_TEXT" ]; then
|
|
63
|
+
echo " PASS $name"; PASS=$((PASS+1))
|
|
64
|
+
else
|
|
65
|
+
echo " FAIL $name (expected silent, exit=$EXIT, stderr non-empty=$([ -n "$STDERR_TEXT" ] && echo yes))"
|
|
66
|
+
echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
|
|
67
|
+
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
68
|
+
fi
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
expect_block() {
|
|
72
|
+
local name="$1"; local needle="$2"
|
|
73
|
+
if [ "$EXIT" = "2" ] && echo "$STDERR_TEXT" | grep -qF "$needle"; then
|
|
74
|
+
echo " PASS $name"; PASS=$((PASS+1))
|
|
75
|
+
else
|
|
76
|
+
echo " FAIL $name (expected exit=2 + needle '$needle', got exit $EXIT)"
|
|
77
|
+
echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
|
|
78
|
+
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
79
|
+
fi
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
echo "=== check_app_shell_primary_header_consistency tests ==="
|
|
83
|
+
|
|
84
|
+
# 1. Non-tsx file → skip
|
|
85
|
+
run_hook_no_file "$TMPDIR_TEST/foo.md" "Edit"
|
|
86
|
+
expect_pass_silent "1. non-tsx file → skip"
|
|
87
|
+
|
|
88
|
+
# 2. Non-Edit/Write tool → skip
|
|
89
|
+
run_hook_no_file "$TMPDIR_TEST/foo.tsx" "Read"
|
|
90
|
+
expect_pass_silent "2. Read tool → skip"
|
|
91
|
+
|
|
92
|
+
# 3. layout="primary-header" with globalHeader + no SidebarHeader → silent (compliant)
|
|
93
|
+
run_hook_on_file "src/app.tsx" '
|
|
94
|
+
<AppShell layout="primary-header" globalHeader={<GlobalHeader />}>
|
|
95
|
+
<Sidebar />
|
|
96
|
+
</AppShell>
|
|
97
|
+
'
|
|
98
|
+
expect_pass_silent "3. primary-header + globalHeader + no SidebarHeader → silent"
|
|
99
|
+
|
|
100
|
+
# 4. layout="primary-header" missing globalHeader → block (V1)
|
|
101
|
+
run_hook_on_file "src/missing-gh.tsx" '
|
|
102
|
+
<AppShell layout="primary-header">
|
|
103
|
+
<Sidebar />
|
|
104
|
+
</AppShell>
|
|
105
|
+
'
|
|
106
|
+
expect_block "4. V1 missing globalHeader → block" "V1 缺 globalHeader prop"
|
|
107
|
+
|
|
108
|
+
# 5. layout="primary-header" + <SidebarHeader> with globalHeader → V2 only block
|
|
109
|
+
run_hook_on_file "src/dup-header.tsx" '
|
|
110
|
+
<AppShell layout="primary-header" globalHeader={<GH />}>
|
|
111
|
+
<Sidebar>
|
|
112
|
+
<SidebarHeader>brand</SidebarHeader>
|
|
113
|
+
</Sidebar>
|
|
114
|
+
</AppShell>
|
|
115
|
+
'
|
|
116
|
+
expect_block "5. V2 SidebarHeader duplicate → block" "V2 Sidebar 內含 SidebarHeader"
|
|
117
|
+
|
|
118
|
+
# 6. Escape allowlist → silent
|
|
119
|
+
run_hook_on_file "src/escape.tsx" '// @app-shell-primary-header-allow: legacy migration in progress
|
|
120
|
+
<AppShell layout="primary-header">
|
|
121
|
+
<SidebarHeader>brand</SidebarHeader>
|
|
122
|
+
</AppShell>
|
|
123
|
+
'
|
|
124
|
+
expect_pass_silent "6. escape allowlist → silent"
|
|
125
|
+
|
|
126
|
+
# 7. No primary-header layout at all → skip
|
|
127
|
+
run_hook_on_file "src/other.tsx" '
|
|
128
|
+
<AppShell layout="primary-sidebar">
|
|
129
|
+
<Sidebar />
|
|
130
|
+
</AppShell>
|
|
131
|
+
'
|
|
132
|
+
expect_pass_silent "7. layout != primary-header → skip"
|
|
133
|
+
|
|
134
|
+
echo ""
|
|
135
|
+
echo "=== Summary ==="
|
|
136
|
+
echo "Passed: $PASS / $((PASS + FAIL))"
|
|
137
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
138
|
+
echo "Failed:$FAILED_TESTS"
|
|
139
|
+
exit 1
|
|
140
|
+
fi
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for check_audit_post_report_validator.sh
|
|
3
|
+
#
|
|
4
|
+
# Hook(PostToolUse Write/Edit/MultiEdit):驗 audit report quality:
|
|
5
|
+
# A) NO-SAMPLE keyword 偵測
|
|
6
|
+
# B) Dim ≥ 46 coverage
|
|
7
|
+
# C) audit-prompts.md prompt count
|
|
8
|
+
# D) @benchmark-unverified-blanket count drift
|
|
9
|
+
# E) prune-chain-trigger → emit additionalContext JSON
|
|
10
|
+
#
|
|
11
|
+
# 只 fire 在 file_path matches `*/audit-report-*.json` 或 `*/project_audit_progress.md`,
|
|
12
|
+
# 且 file 必須真實存在於 disk(`[ -f "$FILE_PATH" ] || exit 0`)。
|
|
13
|
+
# 輸出至 stdout(JSON additionalContext)時是 trigger_prune=1 路徑;非 prune trigger 走 silent。
|
|
14
|
+
# 注意:hook 內 WARNINGS 累積但 stderr 不直接 print(只 stdout JSON);此測試 verify stdout JSON。
|
|
15
|
+
|
|
16
|
+
set -u
|
|
17
|
+
|
|
18
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
19
|
+
HOOK="$SCRIPT_DIR/../check_audit_post_report_validator.sh"
|
|
20
|
+
TMPDIR_TEST=$(mktemp -d)
|
|
21
|
+
trap 'rm -rf "$TMPDIR_TEST"' EXIT
|
|
22
|
+
|
|
23
|
+
if [ ! -f "$HOOK" ]; then echo "FATAL: hook not found: $HOOK"; exit 1; fi
|
|
24
|
+
|
|
25
|
+
PASS=0
|
|
26
|
+
FAIL=0
|
|
27
|
+
FAILED_TESTS=""
|
|
28
|
+
|
|
29
|
+
run_hook() {
|
|
30
|
+
local file_path="$1"; local tool="$2"
|
|
31
|
+
local payload
|
|
32
|
+
payload=$(jq -n --arg fp "$file_path" --arg tn "$tool" \
|
|
33
|
+
'{tool_name: $tn, tool_input: {file_path: $fp}}')
|
|
34
|
+
STDOUT=$(mktemp); STDERR=$(mktemp)
|
|
35
|
+
set +e
|
|
36
|
+
export CLAUDE_PROJECT_DIR="$TMPDIR_TEST"
|
|
37
|
+
printf '%s' "$payload" | bash "$HOOK" >"$STDOUT" 2>"$STDERR"
|
|
38
|
+
EXIT=$?
|
|
39
|
+
set -e
|
|
40
|
+
STDOUT_TEXT=$(cat "$STDOUT")
|
|
41
|
+
STDERR_TEXT=$(cat "$STDERR")
|
|
42
|
+
rm -f "$STDOUT" "$STDERR"
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
expect_silent() {
|
|
46
|
+
local name="$1"
|
|
47
|
+
if [ "$EXIT" = "0" ] && [ -z "$STDOUT_TEXT" ] && [ -z "$STDERR_TEXT" ]; then
|
|
48
|
+
echo " PASS $name"; PASS=$((PASS+1))
|
|
49
|
+
else
|
|
50
|
+
echo " FAIL $name (exit=$EXIT, stdout=[$STDOUT_TEXT], stderr non-empty=$([ -n "$STDERR_TEXT" ] && echo yes))"
|
|
51
|
+
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
52
|
+
fi
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
expect_stdout_contains() {
|
|
56
|
+
local name="$1"; local needle="$2"
|
|
57
|
+
if [ "$EXIT" = "0" ] && echo "$STDOUT_TEXT" | grep -qF "$needle"; then
|
|
58
|
+
echo " PASS $name"; PASS=$((PASS+1))
|
|
59
|
+
else
|
|
60
|
+
echo " FAIL $name (expected stdout contains '$needle', got exit $EXIT)"
|
|
61
|
+
echo " --- stdout ---"; echo "$STDOUT_TEXT" | sed 's/^/ /'; echo " --- end ---"
|
|
62
|
+
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
63
|
+
fi
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
echo "=== check_audit_post_report_validator tests ==="
|
|
67
|
+
|
|
68
|
+
# 1. Non-audit file path → skip silently
|
|
69
|
+
run_hook "/tmp/random.txt" "Write"
|
|
70
|
+
expect_silent "1. non-audit path → skip"
|
|
71
|
+
|
|
72
|
+
# 2. Non-Write/Edit tool → skip silently
|
|
73
|
+
run_hook "$TMPDIR_TEST/.claude/logs/audit-report-foo.json" "Read"
|
|
74
|
+
expect_silent "2. Read tool → skip"
|
|
75
|
+
|
|
76
|
+
# 3. Audit-report path but file not on disk → skip
|
|
77
|
+
run_hook "$TMPDIR_TEST/.claude/logs/audit-report-missing.json" "Write"
|
|
78
|
+
expect_silent "3. missing file → skip"
|
|
79
|
+
|
|
80
|
+
# 4. project_audit_progress.md with NO-SAMPLE keyword but no audit-prompts.md → no prune trigger, silent stdout
|
|
81
|
+
mkdir -p "$TMPDIR_TEST/.claude/memory"
|
|
82
|
+
cat > "$TMPDIR_TEST/.claude/memory/project_audit_progress.md" <<'EOF'
|
|
83
|
+
# Audit progress
|
|
84
|
+
Dim 1: pass
|
|
85
|
+
Dim 2: pass
|
|
86
|
+
Dim 3: pass
|
|
87
|
+
EOF
|
|
88
|
+
run_hook "$TMPDIR_TEST/.claude/memory/project_audit_progress.md" "Write"
|
|
89
|
+
# B fires (DIM_COUNT < 46) but no TRIGGER_PRUNE since audit-prompts.md absent + no bench debt
|
|
90
|
+
# stdout should be silent (TRIGGER_PRUNE=0)
|
|
91
|
+
expect_silent "4. valid file no prune trigger → silent stdout"
|
|
92
|
+
|
|
93
|
+
# 5. audit-prompts.md present but only 2 prompts → TRIGGER_PRUNE=1, stdout JSON
|
|
94
|
+
mkdir -p "$TMPDIR_TEST/.claude/skills/design-system-audit/references"
|
|
95
|
+
cat > "$TMPDIR_TEST/.claude/skills/design-system-audit/references/audit-prompts.md" <<'EOF'
|
|
96
|
+
### Dim 1: foo
|
|
97
|
+
prompt
|
|
98
|
+
|
|
99
|
+
### Dim 2: bar
|
|
100
|
+
prompt
|
|
101
|
+
EOF
|
|
102
|
+
cat > "$TMPDIR_TEST/.claude/memory/project_audit_progress.md" <<'EOF'
|
|
103
|
+
# Audit progress
|
|
104
|
+
Dim 1: pass
|
|
105
|
+
EOF
|
|
106
|
+
run_hook "$TMPDIR_TEST/.claude/memory/project_audit_progress.md" "Edit"
|
|
107
|
+
expect_stdout_contains "5. audit-prompts coverage low → prune trigger JSON" "prune-chain-trigger"
|
|
108
|
+
|
|
109
|
+
echo ""
|
|
110
|
+
echo "=== Summary ==="
|
|
111
|
+
echo "Passed: $PASS / $((PASS + FAIL))"
|
|
112
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
113
|
+
echo "Failed:$FAILED_TESTS"
|
|
114
|
+
exit 1
|
|
115
|
+
fi
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for check_audit_sample_escape.sh
|
|
3
|
+
#
|
|
4
|
+
# Hook(PreToolUse Agent):dispatch prompt 含 sample escape clause → BLOCK(exit 2)。
|
|
5
|
+
# Only enforce on prompt containing audit-related keyword(audit / Dim N / DS-wide / sub-agent / sweep)。
|
|
6
|
+
# Escape:prompt 含 `@audit-sample-allow:` 整 prompt 豁免。
|
|
7
|
+
# 違規 stderr「🚨 AUDIT NO-SAMPLE ESCAPE CLAUSE BLOCKER」+ exit 2。
|
|
8
|
+
|
|
9
|
+
set -u
|
|
10
|
+
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
12
|
+
HOOK="$SCRIPT_DIR/../check_audit_sample_escape.sh"
|
|
13
|
+
|
|
14
|
+
if [ ! -f "$HOOK" ]; then echo "FATAL: hook not found: $HOOK"; exit 1; fi
|
|
15
|
+
|
|
16
|
+
PASS=0
|
|
17
|
+
FAIL=0
|
|
18
|
+
FAILED_TESTS=""
|
|
19
|
+
|
|
20
|
+
run_hook() {
|
|
21
|
+
local tool="$1"; local prompt="$2"
|
|
22
|
+
local payload
|
|
23
|
+
payload=$(jq -n --arg tn "$tool" --arg p "$prompt" \
|
|
24
|
+
'{tool_name: $tn, tool_input: {prompt: $p}}')
|
|
25
|
+
STDOUT=$(mktemp); STDERR=$(mktemp)
|
|
26
|
+
set +e
|
|
27
|
+
printf '%s' "$payload" | bash "$HOOK" >"$STDOUT" 2>"$STDERR"
|
|
28
|
+
EXIT=$?
|
|
29
|
+
set -e
|
|
30
|
+
STDERR_TEXT=$(cat "$STDERR")
|
|
31
|
+
rm -f "$STDOUT" "$STDERR"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
expect_pass_silent() {
|
|
35
|
+
local name="$1"
|
|
36
|
+
if [ "$EXIT" = "0" ] && [ -z "$STDERR_TEXT" ]; then
|
|
37
|
+
echo " PASS $name"; PASS=$((PASS+1))
|
|
38
|
+
else
|
|
39
|
+
echo " FAIL $name (expected silent, exit=$EXIT)"
|
|
40
|
+
echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
|
|
41
|
+
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
42
|
+
fi
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
expect_block() {
|
|
46
|
+
local name="$1"; local needle="$2"
|
|
47
|
+
if [ "$EXIT" = "2" ] && echo "$STDERR_TEXT" | grep -qF "$needle"; then
|
|
48
|
+
echo " PASS $name"; PASS=$((PASS+1))
|
|
49
|
+
else
|
|
50
|
+
echo " FAIL $name (expected exit=2 + needle '$needle', got exit $EXIT)"
|
|
51
|
+
echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
|
|
52
|
+
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
53
|
+
fi
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
echo "=== check_audit_sample_escape tests ==="
|
|
57
|
+
|
|
58
|
+
# 1. Non-Agent tool → skip
|
|
59
|
+
run_hook "Bash" "audit DS-wide sample top 5"
|
|
60
|
+
expect_pass_silent "1. non-Agent tool → skip"
|
|
61
|
+
|
|
62
|
+
# 2. Agent dispatch without audit keyword → skip
|
|
63
|
+
run_hook "Agent" "refactor this function please"
|
|
64
|
+
expect_pass_silent "2. non-audit prompt → skip"
|
|
65
|
+
|
|
66
|
+
# 3. Agent + audit keyword + NO sample keyword → silent
|
|
67
|
+
run_hook "Agent" "audit Dim 12 DS-wide full sweep all components"
|
|
68
|
+
expect_pass_silent "3. audit prompt without sample escape → silent"
|
|
69
|
+
|
|
70
|
+
# 4. Agent + audit + 'sample top 10' → BLOCK
|
|
71
|
+
run_hook "Agent" "audit Dim 24 DS-wide sample top 10 components"
|
|
72
|
+
expect_block "4. sample top N → block" "AUDIT NO-SAMPLE ESCAPE CLAUSE BLOCKER"
|
|
73
|
+
|
|
74
|
+
# 5. Agent + audit + 'sampled components' → BLOCK
|
|
75
|
+
run_hook "Agent" "Dim 40 DS-wide sub-agent dispatch, sampled components only"
|
|
76
|
+
expect_block "5. sampled components → block" "AUDIT NO-SAMPLE ESCAPE CLAUSE BLOCKER"
|
|
77
|
+
|
|
78
|
+
# 6. Agent + audit + 'heavy agent needed' → BLOCK
|
|
79
|
+
run_hook "Agent" "audit sweep all 53 dim, heavy agent needed for Dim 25"
|
|
80
|
+
expect_block "6. heavy agent needed → block" "AUDIT NO-SAMPLE ESCAPE CLAUSE BLOCKER"
|
|
81
|
+
|
|
82
|
+
# 7. Escape allowlist → silent
|
|
83
|
+
run_hook "Agent" "// @audit-sample-allow: rare integration test scope
|
|
84
|
+
audit Dim 99 sample top 3"
|
|
85
|
+
expect_pass_silent "7. @audit-sample-allow escape → silent"
|
|
86
|
+
|
|
87
|
+
echo ""
|
|
88
|
+
echo "=== Summary ==="
|
|
89
|
+
echo "Passed: $PASS / $((PASS + FAIL))"
|
|
90
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
91
|
+
echo "Failed:$FAILED_TESTS"
|
|
92
|
+
exit 1
|
|
93
|
+
fi
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for check_benchmark_citation.sh
|
|
3
|
+
#
|
|
4
|
+
# Hook(PreToolUse Edit/Write/MultiEdit):spec.md / .tsx in packages/design-system/src/
|
|
5
|
+
# 含 world-class benchmark claim(Ant / Material / Polaris ...)必附 inline citation
|
|
6
|
+
# (URL / GitHub #L / snapshots/ / @benchmark-unverified)。違 P1 soft warn(exit 1)。
|
|
7
|
+
# 整檔 escape:前 5 行含 @benchmark-citation-allow: 或 @benchmark-unverified-blanket:。
|
|
8
|
+
|
|
9
|
+
set -u
|
|
10
|
+
|
|
11
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
12
|
+
HOOK="$SCRIPT_DIR/../check_benchmark_citation.sh"
|
|
13
|
+
|
|
14
|
+
if [ ! -f "$HOOK" ]; then echo "FATAL: hook not found: $HOOK"; exit 1; fi
|
|
15
|
+
|
|
16
|
+
PASS=0
|
|
17
|
+
FAIL=0
|
|
18
|
+
FAILED_TESTS=""
|
|
19
|
+
|
|
20
|
+
# tool_input.content 用於 Write;tool_input.new_string 用於 Edit
|
|
21
|
+
run_hook_write() {
|
|
22
|
+
local file_path="$1"; local content="$2"
|
|
23
|
+
local payload
|
|
24
|
+
payload=$(jq -n --arg fp "$file_path" --arg c "$content" \
|
|
25
|
+
'{tool_name: "Write", tool_input: {file_path: $fp, content: $c}}')
|
|
26
|
+
STDOUT=$(mktemp); STDERR=$(mktemp)
|
|
27
|
+
set +e
|
|
28
|
+
printf '%s' "$payload" | bash "$HOOK" >"$STDOUT" 2>"$STDERR"
|
|
29
|
+
EXIT=$?
|
|
30
|
+
set -e
|
|
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 "$STDERR_TEXT" ]; then
|
|
38
|
+
echo " PASS $name"; PASS=$((PASS+1))
|
|
39
|
+
else
|
|
40
|
+
echo " FAIL $name (expected silent, exit=$EXIT)"
|
|
41
|
+
echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
|
|
42
|
+
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
43
|
+
fi
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
expect_warn() {
|
|
47
|
+
local name="$1"; local needle="$2"
|
|
48
|
+
if [ "$EXIT" = "1" ] && echo "$STDERR_TEXT" | grep -qF "$needle"; then
|
|
49
|
+
echo " PASS $name"; PASS=$((PASS+1))
|
|
50
|
+
else
|
|
51
|
+
echo " FAIL $name (expected exit=1 + needle '$needle', got exit $EXIT)"
|
|
52
|
+
echo " --- stderr ---"; echo "$STDERR_TEXT" | sed 's/^/ /'; echo " --- end ---"
|
|
53
|
+
FAIL=$((FAIL+1)); FAILED_TESTS="${FAILED_TESTS}\n - $name"
|
|
54
|
+
fi
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
echo "=== check_benchmark_citation tests ==="
|
|
58
|
+
|
|
59
|
+
# 1. Non-DS path → skip
|
|
60
|
+
run_hook_write "/tmp/random.tsx" '對齊 Ant Design'
|
|
61
|
+
expect_pass_silent "1. non-DS path → skip"
|
|
62
|
+
|
|
63
|
+
# 2. DS path no benchmark claim → silent
|
|
64
|
+
run_hook_write "/repo/packages/design-system/src/components/Foo/foo.spec.md" '
|
|
65
|
+
# Foo spec
|
|
66
|
+
普通文字無 world-class claim
|
|
67
|
+
'
|
|
68
|
+
expect_pass_silent "2. no benchmark claim → silent"
|
|
69
|
+
|
|
70
|
+
# 3. DS path Ant Design claim WITH inline URL → silent
|
|
71
|
+
run_hook_write "/repo/packages/design-system/src/components/Foo/foo.spec.md" '
|
|
72
|
+
對齊 Ant Design 設計
|
|
73
|
+
參考 https://ant-design.com/components/foo
|
|
74
|
+
'
|
|
75
|
+
expect_pass_silent "3. claim + ant-design URL → silent"
|
|
76
|
+
|
|
77
|
+
# 4. DS path Material claim with GitHub #L cite → silent
|
|
78
|
+
run_hook_write "/repo/packages/design-system/src/components/Foo/foo.tsx" '
|
|
79
|
+
// 對齊 Material UI button(https://github.com/mui/material-ui/blob/master/Button.tsx#L42)
|
|
80
|
+
const x = 1
|
|
81
|
+
'
|
|
82
|
+
expect_pass_silent "4. claim + github #L cite → silent"
|
|
83
|
+
|
|
84
|
+
# 5. DS path Polaris claim WITHOUT citation → warn
|
|
85
|
+
run_hook_write "/repo/packages/design-system/src/components/Foo/foo.spec.md" '
|
|
86
|
+
# Foo spec
|
|
87
|
+
|
|
88
|
+
對齊 Polaris 設計派,確保視覺一致。
|
|
89
|
+
'
|
|
90
|
+
expect_warn "5. Polaris claim missing cite → warn" "check_benchmark_citation"
|
|
91
|
+
|
|
92
|
+
# 6. DS path Atlassian claim with @benchmark-unverified → silent (撤回 marker)
|
|
93
|
+
run_hook_write "/repo/packages/design-system/src/components/Foo/foo.spec.md" '
|
|
94
|
+
# Foo spec
|
|
95
|
+
|
|
96
|
+
對齊 Atlassian Design @benchmark-unverified 待補 source
|
|
97
|
+
'
|
|
98
|
+
expect_pass_silent "6. claim with @benchmark-unverified → silent"
|
|
99
|
+
|
|
100
|
+
# 7. File-level @benchmark-citation-allow escape → silent
|
|
101
|
+
run_hook_write "/repo/packages/design-system/src/components/Foo/foo.spec.md" '// @benchmark-citation-allow: legacy migration backlog
|
|
102
|
+
# Foo
|
|
103
|
+
|
|
104
|
+
對齊 Carbon Design 內部共識。
|
|
105
|
+
對齊 Polaris 派系。
|
|
106
|
+
'
|
|
107
|
+
expect_pass_silent "7. file-level @benchmark-citation-allow → silent"
|
|
108
|
+
|
|
109
|
+
echo ""
|
|
110
|
+
echo "=== Summary ==="
|
|
111
|
+
echo "Passed: $PASS / $((PASS + FAIL))"
|
|
112
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
113
|
+
echo "Failed:$FAILED_TESTS"
|
|
114
|
+
exit 1
|
|
115
|
+
fi
|