Initial commit: Clean DSS implementation

Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm

Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)

Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability

Migration completed: $(date)
🤖 Clean migration with full functionality preserved
This commit is contained in:
Digital Production Factory
2025-12-09 18:45:48 -03:00
commit 276ed71f31
884 changed files with 373737 additions and 0 deletions

View File

@@ -0,0 +1,253 @@
#!/usr/bin/env python3
"""
DSS Token Validator Hook
Detects hardcoded values that should use design tokens.
Written from scratch for DSS.
"""
import json
import re
import sys
from pathlib import Path
# Patterns for hardcoded values that should be tokens
HARDCODED_PATTERNS = [
{
"id": "color-hex",
"regex": r"(?<!var\()#[0-9a-fA-F]{3,8}\b",
"category": "color",
"message": "Hardcoded hex color detected. Consider using a design token.",
"suggestion": "Use: var(--color-*) or theme.colors.*",
"file_types": [".css", ".scss", ".less", ".js", ".jsx", ".ts", ".tsx"]
},
{
"id": "color-rgb",
"regex": r"rgba?\s*\(\s*\d+\s*,\s*\d+\s*,\s*\d+",
"category": "color",
"message": "Hardcoded RGB color detected. Consider using a design token.",
"suggestion": "Use: var(--color-*) or theme.colors.*",
"file_types": [".css", ".scss", ".less", ".js", ".jsx", ".ts", ".tsx"]
},
{
"id": "color-hsl",
"regex": r"hsla?\s*\(\s*\d+\s*,\s*\d+%?\s*,\s*\d+%?",
"category": "color",
"message": "Hardcoded HSL color detected. Consider using a design token.",
"suggestion": "Use: var(--color-*) or theme.colors.*",
"file_types": [".css", ".scss", ".less", ".js", ".jsx", ".ts", ".tsx"]
},
{
"id": "spacing-px",
"regex": r":\s*\d{2,}px",
"category": "spacing",
"message": "Hardcoded pixel spacing detected. Consider using a spacing token.",
"suggestion": "Use: var(--spacing-*) or theme.spacing.*",
"file_types": [".css", ".scss", ".less"]
},
{
"id": "font-size-px",
"regex": r"font-size:\s*\d+px",
"category": "typography",
"message": "Hardcoded font-size detected. Consider using a typography token.",
"suggestion": "Use: var(--font-size-*) or theme.fontSize.*",
"file_types": [".css", ".scss", ".less"]
},
{
"id": "font-family-direct",
"regex": r"font-family:\s*['\"]?(?:Arial|Helvetica|Times|Verdana|Georgia)",
"category": "typography",
"message": "Hardcoded font-family detected. Consider using a typography token.",
"suggestion": "Use: var(--font-family-*) or theme.fontFamily.*",
"file_types": [".css", ".scss", ".less"]
},
{
"id": "border-radius-px",
"regex": r"border-radius:\s*\d+px",
"category": "border",
"message": "Hardcoded border-radius detected. Consider using a radius token.",
"suggestion": "Use: var(--radius-*) or theme.borderRadius.*",
"file_types": [".css", ".scss", ".less"]
},
{
"id": "box-shadow-direct",
"regex": r"box-shadow:\s*\d+px\s+\d+px",
"category": "effects",
"message": "Hardcoded box-shadow detected. Consider using a shadow token.",
"suggestion": "Use: var(--shadow-*) or theme.boxShadow.*",
"file_types": [".css", ".scss", ".less"]
},
{
"id": "z-index-magic",
"regex": r"z-index:\s*(?:999|9999|99999|\d{4,})",
"category": "layout",
"message": "Magic number z-index detected. Consider using a z-index token.",
"suggestion": "Use: var(--z-index-*) with semantic names (modal, dropdown, tooltip)",
"file_types": [".css", ".scss", ".less"]
},
{
"id": "inline-style-color",
"regex": r"style=\{?\{[^}]*color:\s*['\"]#[0-9a-fA-F]+['\"]",
"category": "color",
"message": "Hardcoded color in inline style. Consider using theme tokens.",
"suggestion": "Use: style={{ color: theme.colors.* }}",
"file_types": [".jsx", ".tsx"]
},
{
"id": "tailwind-arbitrary",
"regex": r"(?:bg|text|border)-\[#[0-9a-fA-F]+\]",
"category": "color",
"message": "Arbitrary Tailwind color value. Consider using theme colors.",
"suggestion": "Use: bg-primary, text-secondary, etc.",
"file_types": [".jsx", ".tsx", ".html"]
}
]
# Allowlist patterns (common exceptions)
ALLOWLIST = [
r"#000000?", # Pure black
r"#fff(fff)?", # Pure white
r"transparent",
r"inherit",
r"currentColor",
r"var\(--", # Already using CSS variables
r"theme\.", # Already using theme
r"colors\.", # Already using colors object
]
def get_config():
"""Load hook configuration."""
config_path = Path.home() / ".dss" / "hooks-config.json"
default_config = {
"token_validator": {
"enabled": True,
"strict_mode": False,
"warn_only": True,
"categories": ["color", "spacing", "typography"]
}
}
if config_path.exists():
try:
with open(config_path) as f:
user_config = json.load(f)
return {**default_config, **user_config}
except:
pass
return default_config
def is_allowlisted(match: str) -> bool:
"""Check if match is in allowlist."""
for pattern in ALLOWLIST:
if re.search(pattern, match, re.IGNORECASE):
return True
return False
def check_content(content: str, file_path: str, config: dict) -> list:
"""Check content for hardcoded values."""
issues = []
file_ext = Path(file_path).suffix.lower()
enabled_categories = config.get("token_validator", {}).get("categories", [])
for pattern_def in HARDCODED_PATTERNS:
# Skip if file type doesn't match
if file_ext not in pattern_def.get("file_types", []):
continue
# Skip if category not enabled (unless empty = all)
if enabled_categories and pattern_def["category"] not in enabled_categories:
continue
matches = re.findall(pattern_def["regex"], content, re.IGNORECASE)
for match in matches:
if not is_allowlisted(match):
issues.append({
"id": pattern_def["id"],
"category": pattern_def["category"],
"message": pattern_def["message"],
"suggestion": pattern_def["suggestion"],
"value": match[:50] # Truncate long matches
})
# Deduplicate by id
seen = set()
unique_issues = []
for issue in issues:
if issue["id"] not in seen:
seen.add(issue["id"])
unique_issues.append(issue)
return unique_issues
def format_output(issues: list, file_path: str) -> str:
"""Format issues for display."""
if not issues:
return ""
category_icons = {
"color": "[COLOR]",
"spacing": "[SPACE]",
"typography": "[FONT]",
"border": "[BORDER]",
"effects": "[EFFECT]",
"layout": "[LAYOUT]"
}
lines = [f"\n=== DSS Token Validator: {file_path} ===\n"]
for issue in issues:
icon = category_icons.get(issue["category"], "[TOKEN]")
lines.append(f"{icon} {issue['message']}")
lines.append(f" Found: {issue['value']}")
lines.append(f" {issue['suggestion']}\n")
lines.append("=" * 50)
return "\n".join(lines)
def main():
"""Main hook entry point."""
config = get_config()
if not config.get("token_validator", {}).get("enabled", True):
sys.exit(0)
# Read hook input from stdin
try:
input_data = json.loads(sys.stdin.read())
except json.JSONDecodeError:
sys.exit(0)
tool_name = input_data.get("tool_name", "")
tool_input = input_data.get("tool_input", {})
if tool_name not in ["Edit", "Write"]:
sys.exit(0)
file_path = tool_input.get("file_path", "")
# Get content to check
if tool_name == "Write":
content = tool_input.get("content", "")
elif tool_name == "Edit":
content = tool_input.get("new_string", "")
else:
content = ""
if not content or not file_path:
sys.exit(0)
# Check for token issues
issues = check_content(content, file_path, config)
if issues:
output = format_output(issues, file_path)
print(output, file=sys.stderr)
# In strict mode, block on issues
if config.get("token_validator", {}).get("strict_mode", False):
sys.exit(2)
sys.exit(0)
if __name__ == "__main__":
main()