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:
330
demo/tools/discovery/discover.sh
Executable file
330
demo/tools/discovery/discover.sh
Executable file
@@ -0,0 +1,330 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Design System Server (DSS) - Project Discovery Script
|
||||
#
|
||||
# Non-intrusive analysis of project structure, dependencies, and health.
|
||||
# Outputs JSON for UI consumption.
|
||||
#
|
||||
# Usage: ./discover.sh [project_path] [--full]
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
PROJECT_PATH="${1:-.}"
|
||||
FULL_SCAN="${2:-}"
|
||||
OUTPUT_DIR="${PROJECT_PATH}/.dss"
|
||||
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
|
||||
# Create output directory
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
# Colors for terminal output (only if interactive)
|
||||
if [ -t 1 ]; then
|
||||
GREEN='\033[0;32m'
|
||||
BLUE='\033[0;34m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
else
|
||||
GREEN=''
|
||||
BLUE=''
|
||||
YELLOW=''
|
||||
NC=''
|
||||
fi
|
||||
|
||||
log() {
|
||||
echo -e "${BLUE}[DSS]${NC} $1" >&2
|
||||
}
|
||||
|
||||
# === Project Type Detection ===
|
||||
|
||||
detect_project_type() {
|
||||
local types=()
|
||||
|
||||
[ -f "$PROJECT_PATH/package.json" ] && types+=("nodejs")
|
||||
[ -f "$PROJECT_PATH/requirements.txt" ] || [ -f "$PROJECT_PATH/pyproject.toml" ] && types+=("python")
|
||||
[ -f "$PROJECT_PATH/Cargo.toml" ] && types+=("rust")
|
||||
[ -f "$PROJECT_PATH/go.mod" ] && types+=("go")
|
||||
[ -f "$PROJECT_PATH/pom.xml" ] || [ -f "$PROJECT_PATH/build.gradle" ] && types+=("java")
|
||||
[ -f "$PROJECT_PATH/Gemfile" ] && types+=("ruby")
|
||||
[ -f "$PROJECT_PATH/composer.json" ] && types+=("php")
|
||||
|
||||
echo "${types[@]:-unknown}"
|
||||
}
|
||||
|
||||
# === Framework Detection ===
|
||||
|
||||
detect_frameworks() {
|
||||
local frameworks=()
|
||||
|
||||
if [ -f "$PROJECT_PATH/package.json" ]; then
|
||||
local pkg=$(cat "$PROJECT_PATH/package.json")
|
||||
|
||||
echo "$pkg" | grep -q '"react"' && frameworks+=("react")
|
||||
echo "$pkg" | grep -q '"vue"' && frameworks+=("vue")
|
||||
echo "$pkg" | grep -q '"@angular/core"' && frameworks+=("angular")
|
||||
echo "$pkg" | grep -q '"svelte"' && frameworks+=("svelte")
|
||||
echo "$pkg" | grep -q '"next"' && frameworks+=("nextjs")
|
||||
echo "$pkg" | grep -q '"nuxt"' && frameworks+=("nuxt")
|
||||
echo "$pkg" | grep -q '"express"' && frameworks+=("express")
|
||||
echo "$pkg" | grep -q '"fastify"' && frameworks+=("fastify")
|
||||
echo "$pkg" | grep -q '"tailwindcss"' && frameworks+=("tailwind")
|
||||
echo "$pkg" | grep -q '"@emotion"' && frameworks+=("emotion")
|
||||
echo "$pkg" | grep -q '"styled-components"' && frameworks+=("styled-components")
|
||||
fi
|
||||
|
||||
if [ -f "$PROJECT_PATH/requirements.txt" ]; then
|
||||
grep -q "fastapi" "$PROJECT_PATH/requirements.txt" && frameworks+=("fastapi")
|
||||
grep -q "django" "$PROJECT_PATH/requirements.txt" && frameworks+=("django")
|
||||
grep -q "flask" "$PROJECT_PATH/requirements.txt" && frameworks+=("flask")
|
||||
fi
|
||||
|
||||
echo "${frameworks[@]:-none}"
|
||||
}
|
||||
|
||||
# === Design System Detection ===
|
||||
|
||||
detect_design_system() {
|
||||
local ds_info='{"detected":false}'
|
||||
|
||||
# Check for common design system indicators
|
||||
if [ -f "$PROJECT_PATH/package.json" ]; then
|
||||
local pkg=$(cat "$PROJECT_PATH/package.json")
|
||||
|
||||
if echo "$pkg" | grep -qE '"(@chakra-ui|@mui|antd|@radix-ui|@headlessui)"'; then
|
||||
ds_info='{"detected":true,"type":"library"}'
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for custom design tokens
|
||||
if find "$PROJECT_PATH" -maxdepth 3 -name "tokens.css" -o -name "tokens.json" -o -name "design-tokens.*" 2>/dev/null | grep -q .; then
|
||||
ds_info='{"detected":true,"type":"custom","has_tokens":true}'
|
||||
fi
|
||||
|
||||
# Check for Figma integration
|
||||
if find "$PROJECT_PATH" -maxdepth 3 -name ".figmarc" -o -name "figma.config.*" 2>/dev/null | grep -q .; then
|
||||
ds_info=$(echo "$ds_info" | sed 's/}$/,"figma_connected":true}/')
|
||||
fi
|
||||
|
||||
echo "$ds_info"
|
||||
}
|
||||
|
||||
# === File Statistics ===
|
||||
|
||||
get_file_stats() {
|
||||
local total_files=$(find "$PROJECT_PATH" -type f ! -path "*/node_modules/*" ! -path "*/.git/*" ! -path "*/dist/*" ! -path "*/__pycache__/*" 2>/dev/null | wc -l)
|
||||
local js_files=$(find "$PROJECT_PATH" -type f \( -name "*.js" -o -name "*.jsx" -o -name "*.ts" -o -name "*.tsx" \) ! -path "*/node_modules/*" 2>/dev/null | wc -l)
|
||||
local css_files=$(find "$PROJECT_PATH" -type f \( -name "*.css" -o -name "*.scss" -o -name "*.less" \) ! -path "*/node_modules/*" 2>/dev/null | wc -l)
|
||||
local py_files=$(find "$PROJECT_PATH" -type f -name "*.py" ! -path "*/__pycache__/*" 2>/dev/null | wc -l)
|
||||
local component_files=$(find "$PROJECT_PATH" -type f \( -name "*.jsx" -o -name "*.tsx" -o -name "*.vue" -o -name "*.svelte" \) ! -path "*/node_modules/*" 2>/dev/null | wc -l)
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"total": $total_files,
|
||||
"javascript": $js_files,
|
||||
"css": $css_files,
|
||||
"python": $py_files,
|
||||
"components": $component_files
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# === Dependency Analysis ===
|
||||
|
||||
analyze_dependencies() {
|
||||
local deps='{"production":[],"development":[],"total":0}'
|
||||
|
||||
if [ -f "$PROJECT_PATH/package.json" ]; then
|
||||
local prod_count=$(jq '.dependencies | length // 0' "$PROJECT_PATH/package.json" 2>/dev/null || echo 0)
|
||||
local dev_count=$(jq '.devDependencies | length // 0' "$PROJECT_PATH/package.json" 2>/dev/null || echo 0)
|
||||
local total=$((prod_count + dev_count))
|
||||
|
||||
deps="{\"production\":$prod_count,\"development\":$dev_count,\"total\":$total}"
|
||||
fi
|
||||
|
||||
if [ -f "$PROJECT_PATH/requirements.txt" ]; then
|
||||
local py_deps=$(grep -v "^#" "$PROJECT_PATH/requirements.txt" | grep -v "^$" | wc -l)
|
||||
deps="{\"python\":$py_deps,\"total\":$py_deps}"
|
||||
fi
|
||||
|
||||
echo "$deps"
|
||||
}
|
||||
|
||||
# === Git Analysis ===
|
||||
|
||||
analyze_git() {
|
||||
if [ ! -d "$PROJECT_PATH/.git" ]; then
|
||||
echo '{"is_repo":false}'
|
||||
return
|
||||
fi
|
||||
|
||||
cd "$PROJECT_PATH"
|
||||
|
||||
local branch=$(git branch --show-current 2>/dev/null || echo "unknown")
|
||||
local commits=$(git rev-list --count HEAD 2>/dev/null || echo 0)
|
||||
local contributors=$(git log --format='%ae' | sort -u | wc -l 2>/dev/null || echo 0)
|
||||
local last_commit=$(git log -1 --format='%ci' 2>/dev/null || echo "unknown")
|
||||
local uncommitted=$(git status --porcelain 2>/dev/null | wc -l || echo 0)
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"is_repo": true,
|
||||
"branch": "$branch",
|
||||
"commits": $commits,
|
||||
"contributors": $contributors,
|
||||
"last_commit": "$last_commit",
|
||||
"uncommitted_changes": $uncommitted
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# === Component Discovery ===
|
||||
|
||||
discover_components() {
|
||||
local components=()
|
||||
|
||||
# Find component files
|
||||
while IFS= read -r file; do
|
||||
if [ -n "$file" ]; then
|
||||
local name=$(basename "$file" | sed 's/\.[^.]*$//')
|
||||
local dir=$(dirname "$file" | sed "s|^$PROJECT_PATH/||")
|
||||
components+=("{\"name\":\"$name\",\"path\":\"$dir\",\"file\":\"$(basename "$file")\"}")
|
||||
fi
|
||||
done < <(find "$PROJECT_PATH" -type f \( -name "*.jsx" -o -name "*.tsx" -o -name "*.vue" \) ! -path "*/node_modules/*" ! -path "*/.next/*" ! -path "*/dist/*" 2>/dev/null | head -50)
|
||||
|
||||
# Join array
|
||||
local joined=$(IFS=,; echo "${components[*]}")
|
||||
echo "[$joined]"
|
||||
}
|
||||
|
||||
# === Health Score ===
|
||||
|
||||
calculate_health_score() {
|
||||
local score=100
|
||||
local issues=()
|
||||
|
||||
# Check for package-lock or yarn.lock
|
||||
if [ -f "$PROJECT_PATH/package.json" ]; then
|
||||
if [ ! -f "$PROJECT_PATH/package-lock.json" ] && [ ! -f "$PROJECT_PATH/yarn.lock" ] && [ ! -f "$PROJECT_PATH/pnpm-lock.yaml" ]; then
|
||||
score=$((score - 10))
|
||||
issues+=("\"No lock file found\"")
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for .gitignore
|
||||
if [ -d "$PROJECT_PATH/.git" ] && [ ! -f "$PROJECT_PATH/.gitignore" ]; then
|
||||
score=$((score - 5))
|
||||
issues+=("\"Missing .gitignore\"")
|
||||
fi
|
||||
|
||||
# Check for README
|
||||
if [ ! -f "$PROJECT_PATH/README.md" ] && [ ! -f "$PROJECT_PATH/README" ]; then
|
||||
score=$((score - 5))
|
||||
issues+=("\"Missing README\"")
|
||||
fi
|
||||
|
||||
# Check for tests
|
||||
if ! find "$PROJECT_PATH" -maxdepth 3 -type d \( -name "test" -o -name "tests" -o -name "__tests__" -o -name "spec" \) 2>/dev/null | grep -q .; then
|
||||
score=$((score - 10))
|
||||
issues+=("\"No test directory found\"")
|
||||
fi
|
||||
|
||||
# Check for TypeScript
|
||||
if [ -f "$PROJECT_PATH/package.json" ] && ! [ -f "$PROJECT_PATH/tsconfig.json" ]; then
|
||||
if grep -q "typescript" "$PROJECT_PATH/package.json" 2>/dev/null; then
|
||||
score=$((score - 5))
|
||||
issues+=("\"TypeScript installed but no tsconfig.json\"")
|
||||
fi
|
||||
fi
|
||||
|
||||
local joined_issues=$(IFS=,; echo "${issues[*]}")
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"score": $score,
|
||||
"grade": "$([ $score -ge 90 ] && echo 'A' || ([ $score -ge 80 ] && echo 'B' || ([ $score -ge 70 ] && echo 'C' || ([ $score -ge 60 ] && echo 'D' || echo 'F'))))",
|
||||
"issues": [$joined_issues]
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# === CSS Analysis ===
|
||||
|
||||
analyze_css() {
|
||||
local css_files=$(find "$PROJECT_PATH" -type f \( -name "*.css" -o -name "*.scss" \) ! -path "*/node_modules/*" 2>/dev/null)
|
||||
local total_files=$(echo "$css_files" | grep -c . || echo 0)
|
||||
|
||||
local has_variables=false
|
||||
local has_custom_properties=false
|
||||
local preprocessor="none"
|
||||
|
||||
if echo "$css_files" | grep -q ".scss"; then
|
||||
preprocessor="sass"
|
||||
fi
|
||||
|
||||
if [ -n "$css_files" ]; then
|
||||
for file in $css_files; do
|
||||
if grep -q -- "--" "$file" 2>/dev/null; then
|
||||
has_custom_properties=true
|
||||
fi
|
||||
if grep -q "\\\$" "$file" 2>/dev/null; then
|
||||
has_variables=true
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
{
|
||||
"files": $total_files,
|
||||
"preprocessor": "$preprocessor",
|
||||
"has_css_variables": $has_custom_properties,
|
||||
"has_preprocessor_variables": $has_variables
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
# === Main Discovery ===
|
||||
|
||||
log "Starting project discovery..."
|
||||
|
||||
PROJECT_TYPES=$(detect_project_type)
|
||||
FRAMEWORKS=$(detect_frameworks)
|
||||
DESIGN_SYSTEM=$(detect_design_system)
|
||||
FILE_STATS=$(get_file_stats)
|
||||
DEPENDENCIES=$(analyze_dependencies)
|
||||
GIT_INFO=$(analyze_git)
|
||||
HEALTH=$(calculate_health_score)
|
||||
CSS_INFO=$(analyze_css)
|
||||
|
||||
if [ "$FULL_SCAN" = "--full" ]; then
|
||||
COMPONENTS=$(discover_components)
|
||||
else
|
||||
COMPONENTS="[]"
|
||||
fi
|
||||
|
||||
# Build final JSON
|
||||
cat > "$OUTPUT_DIR/discovery.json" <<EOF
|
||||
{
|
||||
"meta": {
|
||||
"version": "1.0.0",
|
||||
"timestamp": "$TIMESTAMP",
|
||||
"project_path": "$PROJECT_PATH",
|
||||
"full_scan": $([ "$FULL_SCAN" = "--full" ] && echo true || echo false)
|
||||
},
|
||||
"project": {
|
||||
"types": $(echo "$PROJECT_TYPES" | jq -R 'split(" ")' 2>/dev/null || echo '["unknown"]'),
|
||||
"frameworks": $(echo "$FRAMEWORKS" | jq -R 'split(" ")' 2>/dev/null || echo '[]')
|
||||
},
|
||||
"design_system": $DESIGN_SYSTEM,
|
||||
"files": $FILE_STATS,
|
||||
"dependencies": $DEPENDENCIES,
|
||||
"git": $GIT_INFO,
|
||||
"health": $HEALTH,
|
||||
"css": $CSS_INFO,
|
||||
"components": $COMPONENTS
|
||||
}
|
||||
EOF
|
||||
|
||||
log "Discovery complete: $OUTPUT_DIR/discovery.json"
|
||||
|
||||
# Output the JSON
|
||||
cat "$OUTPUT_DIR/discovery.json"
|
||||
Reference in New Issue
Block a user