Skip to content

Commit 26a92e2

Browse files
lapc506claude
andcommitted
fix(rules): make ds-fixed-width rule fire on absolute paths + clarify hex warn
Greptile review on PR #14 caught three real issues: 1. ds-arbitrary-fixed-width-in-ds-component used a ^-anchored file_path pattern that never matched at runtime — Claude Code passes absolute paths like /home/user/repo/src/components/ui/foo.tsx, but ^src/ only anchors to start-of-string. All 56 tests passed because fixtures used relative paths; the rule was silently inert in production. Switch to (^|/)src/components/ui/ so both relative and absolute paths trigger it. Add a regression test covering an absolute fixture path. 2. ds-raw-hex-color-in-source description started with "Block" while action is warn — confused both maintainers reading the manifest and end-users seeing the runtime stderr. Description now says "Warn". 3. The design-system/ and design-tokens not_pattern exemptions had no test coverage. Added two fixtures so a future regex narrow-down that broke them would fail CI. Tests: 59/59 passing (was 56/56; added 3 regression cases). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 6ac32ee commit 26a92e2

2 files changed

Lines changed: 62 additions & 4 deletions

File tree

hooks/rules/rules.json

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,7 @@
701701
"match": [
702702
{
703703
"field": "file_path",
704-
"pattern": "^src/components/ui/"
704+
"pattern": "(^|/)src/components/ui/"
705705
},
706706
{
707707
"field": "content",
@@ -733,6 +733,16 @@
733733
},
734734
"expected_exit": 2
735735
},
736+
{
737+
"name": "blocks-w-pixel-in-ui-button-absolute-path",
738+
"input": {
739+
"tool_input": {
740+
"file_path": "/home/user/repo/src/components/ui/button.tsx",
741+
"content": "<button className=\"w-[120px]\">x</button>"
742+
}
743+
},
744+
"expected_exit": 2
745+
},
736746
{
737747
"name": "allows-w-pixel-outside-ds",
738748
"input": {
@@ -767,7 +777,7 @@
767777
},
768778
{
769779
"id": "ds-raw-hex-color-in-source",
770-
"description": "Block raw hex color literals in TSX/TS source — colors must come from Tailwind tokens (dojo-primary-*, etc.)",
780+
"description": "Warn on raw hex color literals in TSX/TS source — colors must come from Tailwind tokens (dojo-primary-*, etc.)",
771781
"applies_to": [
772782
"Edit",
773783
"Write",
@@ -841,6 +851,26 @@
841851
},
842852
"expected_exit": 0
843853
},
854+
{
855+
"name": "allows-design-system-folder",
856+
"input": {
857+
"tool_input": {
858+
"file_path": "src/design-system/tokens.ts",
859+
"content": "export const PRIMARY = \"#C980FC\""
860+
}
861+
},
862+
"expected_exit": 0
863+
},
864+
{
865+
"name": "allows-design-tokens-file",
866+
"input": {
867+
"tool_input": {
868+
"file_path": "src/lib/design-tokens.ts",
869+
"content": "export const LILAC = \"#C980FC\""
870+
}
871+
},
872+
"expected_exit": 0
873+
},
844874
{
845875
"name": "allows-bypass-marker",
846876
"input": {

hooks/rules/rules.yaml

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,8 +534,12 @@
534534
description: Block arbitrary fixed widths (w-[Xpx]) inside DS components — they must be flexible (w-full + max-w)
535535
applies_to: [Edit, Write, MultiEdit]
536536
match:
537+
# Anchor on start-of-string OR a leading "/" so the rule fires for both
538+
# relative paths ("src/components/ui/...") and absolute paths
539+
# ("/home/user/repo/src/components/ui/..."). Claude Code's Edit/Write
540+
# tools may pass either form at runtime.
537541
- field: file_path
538-
pattern: '^src/components/ui/'
542+
pattern: '(^|/)src/components/ui/'
539543
- field: content
540544
# Require the `w` to NOT be preceded by a letter/dash so we don't
541545
# mis-flag legitimate composite utilities like max-w-[200px] or
@@ -567,6 +571,15 @@
567571
file_path: 'src/components/ui/card.tsx'
568572
content: '<div className="w-[300px] p-4">y</div>'
569573
expected_exit: 2
574+
# Regression: Claude Code passes absolute paths to Edit/Write at runtime.
575+
# Without the (^|/) anchor the rule would silently allow these (the bug
576+
# Greptile flagged in PR #14).
577+
- name: blocks-w-pixel-in-ui-button-absolute-path
578+
input:
579+
tool_input:
580+
file_path: '/home/user/repo/src/components/ui/button.tsx'
581+
content: '<button className="w-[120px]">x</button>'
582+
expected_exit: 2
570583
- name: allows-w-pixel-outside-ds
571584
input:
572585
tool_input:
@@ -587,7 +600,7 @@
587600
expected_exit: 0
588601

589602
- id: ds-raw-hex-color-in-source
590-
description: Block raw hex color literals in TSX/TS source — colors must come from Tailwind tokens (dojo-primary-*, etc.)
603+
description: Warn on raw hex color literals in TSX/TS source — colors must come from Tailwind tokens (dojo-primary-*, etc.)
591604
applies_to: [Edit, Write, MultiEdit]
592605
match:
593606
- field: file_path
@@ -641,6 +654,21 @@
641654
file_path: 'src/components/foo.test.tsx'
642655
content: 'expect(color).toBe("#FF7151")'
643656
expected_exit: 0
657+
# Lock in the design-system/ exemption so a future regex tweak that
658+
# accidentally narrows not_pattern fails this test.
659+
- name: allows-design-system-folder
660+
input:
661+
tool_input:
662+
file_path: 'src/design-system/tokens.ts'
663+
content: 'export const PRIMARY = "#C980FC"'
664+
expected_exit: 0
665+
# Lock in the design-tokens exemption (matches both folder and filename).
666+
- name: allows-design-tokens-file
667+
input:
668+
tool_input:
669+
file_path: 'src/lib/design-tokens.ts'
670+
content: 'export const LILAC = "#C980FC"'
671+
expected_exit: 0
644672
- name: allows-bypass-marker
645673
input:
646674
tool_input:

0 commit comments

Comments
 (0)