#!/bin/bash # DSS Initialization Script - Full Workflow # Sets up complete DSS structure and manages the entire pipeline # # Usage: scripts/dss-init.sh [--reset] [--skip-analysis] # # Full Workflow: # 1. Reset to clean state (optional, with --reset) # 2. Create directory structure and database # 3. Analyze target projects (admin-ui, storybook) # 4. Figma sync (requires FIGMA_TOKEN, uses MCP) # 5. Build CSS with style-dictionary # 6. admin-ui imports from .dss/data/_system/themes/ set -e DSS_ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$DSS_ROOT" # Parse arguments RESET=false SKIP_ANALYSIS=false for arg in "$@"; do case $arg in --reset) RESET=true ;; --skip-analysis) SKIP_ANALYSIS=true ;; esac done # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' log_step() { echo -e "${BLUE}[STEP]${NC} $1"; } log_ok() { echo -e "${GREEN}[OK]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } log_info() { echo -e "${CYAN}[INFO]${NC} $1"; } echo "╔══════════════════════════════════════════════════════════════╗" echo "║ DSS INITIALIZATION ║" echo "║ Full Workflow Pipeline ║" echo "╚══════════════════════════════════════════════════════════════╝" echo "" # ============================================================================ # STEP 1: Reset (if requested) # ============================================================================ if [ "$RESET" = true ]; then log_step "1. Resetting DSS to clean state..." # Clear data directories rm -rf .dss/data/projects/* .dss/data/teams/* .dss/data/_system/cache/* .dss/data/_system/activity/* 2>/dev/null || true rm -rf .dss/data/_system/tokens/* .dss/data/_system/themes/* .dss/data/_system/components/* 2>/dev/null || true # Reset database rm -f .dss/dss.db .dss/dss.db.old # Clear admin-ui generated files rm -f admin-ui/css/dss-*.css 2>/dev/null || true rm -f admin-ui/src/components/*.stories.js admin-ui/src/components/ds-*.js 2>/dev/null || true # Reset core_tokens mkdir -p dss/core_tokens cat > dss/core_tokens/tokens.json << 'EOF' { "_meta": { "version": "1.0.0", "generated": null, "source": "awaiting Figma sync", "status": "empty" }, "tokens": {} } EOF # Reset skins for skin in base classic workbench; do if [ "$skin" = "base" ]; then cat > "dss-claude-plugin/core/skins/${skin}.json" << EOF { "meta": { "id": "${skin}", "version": "1.0.0", "description": "${skin^} skin - awaiting Figma sync" }, "tokens": {} } EOF else cat > "dss-claude-plugin/core/skins/${skin}.json" << EOF { "meta": { "id": "${skin}", "version": "1.0.0", "description": "${skin^} skin - awaiting Figma sync", "extends": "base" }, "tokens": {} } EOF fi done # Clear logs rm -f .dss/logs/*.jsonl 2>/dev/null || true rm -rf .dss/logs/browser-logs/* 2>/dev/null || true log_ok "Reset complete" echo "" else log_step "1. Skipping reset (use --reset to clear first)" echo "" fi # ============================================================================ # STEP 2: Validate Environment # ============================================================================ log_step "2. Validating DSS environment..." STYLE_DICT_AVAILABLE=false FIGMA_AVAILABLE=false # Check Python if ! command -v python3 &> /dev/null; then log_error "Python3 not found" exit 1 fi log_ok "Python3: $(python3 --version | cut -d' ' -f2)" # Check Node.js if command -v node &> /dev/null; then log_ok "Node.js: $(node --version)" else log_warn "Node.js not found - Storybook features limited" fi # Check style-dictionary (project, home, or global) if command -v style-dictionary &> /dev/null; then STYLE_DICT_AVAILABLE=true log_ok "style-dictionary: available" elif [ -f "node_modules/.bin/style-dictionary" ]; then STYLE_DICT_AVAILABLE=true log_ok "style-dictionary: local install" elif [ -f "$HOME/node_modules/.bin/style-dictionary" ]; then STYLE_DICT_AVAILABLE=true log_ok "style-dictionary: installed (~)" else log_warn "style-dictionary not installed (npm install -g style-dictionary)" fi # Check Figma token - load from config if not in environment FIGMA_CONFIG=".dss/config/figma.json" if [ -z "$FIGMA_TOKEN" ] && [ -f "$FIGMA_CONFIG" ]; then FIGMA_TOKEN=$(python3 -c "import json; print(json.load(open('$FIGMA_CONFIG')).get('token',''))" 2>/dev/null) export FIGMA_TOKEN fi if [ -n "$FIGMA_TOKEN" ]; then FIGMA_AVAILABLE=true log_ok "FIGMA_TOKEN: configured (from .dss/config/figma.json)" # Also show UIKit reference if available if [ -f "$FIGMA_CONFIG" ]; then UIKIT_NAME=$(python3 -c "import json; d=json.load(open('$FIGMA_CONFIG')); print(d.get('uikit_reference',{}).get('name',''))" 2>/dev/null) [ -n "$UIKIT_NAME" ] && log_ok "UIKit reference: $UIKIT_NAME" fi else log_warn "FIGMA_TOKEN not set - add to .dss/config/figma.json" fi echo "" # ============================================================================ # STEP 3: Create Directory Structure # ============================================================================ log_step "3. Creating DSS directory structure..." mkdir -p .dss/data/{_system/{tokens,themes,components,cache,activity},projects,teams} mkdir -p .dss/schema mkdir -p .dss/logs/browser-logs touch .dss/logs/dss-operations.jsonl touch .dss/logs/git-hooks.jsonl # Create _system ds.config.json if [ ! -f ".dss/data/_system/ds.config.json" ]; then cat > .dss/data/_system/ds.config.json << 'EOF' { "name": "dss-system", "version": "1.0.0", "description": "DSS internal design system (dogfooding)", "skin": "base", "base_theme": "light", "targets": [ { "name": "admin-ui", "path": "./admin-ui", "type": "web-app", "framework": "vanilla" }, { "name": "storybook", "path": "./storybook", "type": "documentation", "framework": "storybook" } ], "output": { "tokens_dir": "./.dss/data/_system/tokens", "themes_dir": "./.dss/data/_system/themes", "components_dir": "./.dss/data/_system/components", "formats": ["css", "scss", "json"] } } EOF fi log_ok "Directory structure ready" echo "" # ============================================================================ # STEP 4: Initialize Database # ============================================================================ log_step "4. Initializing database..." if [ ! -f ".dss/dss.db" ]; then python3 << 'PYEOF' import sqlite3 conn = sqlite3.connect(".dss/dss.db") c = conn.cursor() c.execute('''CREATE TABLE IF NOT EXISTS projects ( id TEXT PRIMARY KEY, name TEXT NOT NULL, path TEXT, config TEXT, created_at TEXT, updated_at TEXT)''') c.execute('''CREATE TABLE IF NOT EXISTS tokens ( id TEXT PRIMARY KEY, project_id TEXT, category TEXT, name TEXT, value TEXT, source TEXT, created_at TEXT, FOREIGN KEY (project_id) REFERENCES projects(id))''') c.execute('''CREATE TABLE IF NOT EXISTS components ( id TEXT PRIMARY KEY, project_id TEXT, name TEXT, path TEXT, analysis TEXT, created_at TEXT, FOREIGN KEY (project_id) REFERENCES projects(id))''') c.execute('''CREATE TABLE IF NOT EXISTS figma_syncs ( id TEXT PRIMARY KEY, file_key TEXT, file_name TEXT, tokens_count INTEGER, status TEXT, synced_at TEXT)''') conn.commit() conn.close() PYEOF log_ok "Database initialized" else log_ok "Database exists" fi echo "" # ============================================================================ # STEP 5: Analyze Target Projects # ============================================================================ if [ "$SKIP_ANALYSIS" = false ]; then log_step "5. Analyzing target projects..." # Analyze admin-ui if [ -d "admin-ui" ]; then JS_COUNT=$(find admin-ui -name "*.js" -not -path "*/node_modules/*" 2>/dev/null | wc -l) CSS_COUNT=$(find admin-ui -name "*.css" -not -path "*/node_modules/*" 2>/dev/null | wc -l) HTML_COUNT=$(find admin-ui -name "*.html" -not -path "*/node_modules/*" 2>/dev/null | wc -l) cat > .dss/data/_system/analysis-admin-ui.json << EOF {"target":"admin-ui","analyzed_at":"$(date -Iseconds)","stats":{"js":$JS_COUNT,"css":$CSS_COUNT,"html":$HTML_COUNT},"status":"analyzed"} EOF log_ok "admin-ui: $JS_COUNT js, $CSS_COUNT css, $HTML_COUNT html" else log_warn "admin-ui directory not found" fi # Analyze storybook STORIES_COUNT=$(find . -name "*.stories.js" -o -name "*.stories.ts" 2>/dev/null | grep -v node_modules | wc -l) MDX_COUNT=$(find . -name "*.mdx" 2>/dev/null | grep -v node_modules | wc -l) cat > .dss/data/_system/analysis-storybook.json << EOF {"target":"storybook","analyzed_at":"$(date -Iseconds)","stats":{"stories":$STORIES_COUNT,"mdx":$MDX_COUNT},"status":"analyzed"} EOF log_ok "storybook: $STORIES_COUNT stories, $MDX_COUNT mdx" echo "" else log_step "5. Skipping analysis (--skip-analysis)" echo "" fi # ============================================================================ # STEP 6: Initialize Token Structure # ============================================================================ log_step "6. Checking token structure..." mkdir -p .dss/data/_system/tokens if [ ! -f ".dss/data/_system/tokens/base.json" ]; then cat > .dss/data/_system/tokens/base.json << 'EOF' { "_meta": { "version": "1.0.0", "generated": null, "source": "awaiting Figma sync", "status": "empty" }, "tokens": {} } EOF log_ok "Empty token structure created" else # Check if tokens have content TOKEN_STATUS=$(python3 -c "import json; d=json.load(open('.dss/data/_system/tokens/base.json')); print(d.get('_meta',{}).get('status','unknown'))" 2>/dev/null || echo "unknown") if [ "$TOKEN_STATUS" = "empty" ]; then log_warn "Tokens empty - run Figma sync to populate" else log_ok "Tokens present (status: $TOKEN_STATUS)" fi fi # Create style-dictionary config (paths relative to .dss/data/_system/ where it runs) cat > .dss/data/_system/style-dictionary.config.json << 'EOF' { "source": ["tokens/tokens.json"], "platforms": { "css": { "transformGroup": "css", "buildPath": "themes/", "files": [{"destination": "tokens.css", "format": "css/variables"}] }, "scss": { "transformGroup": "scss", "buildPath": "themes/", "files": [{"destination": "_tokens.scss", "format": "scss/variables"}] }, "json": { "transformGroup": "js", "buildPath": "themes/", "files": [{"destination": "tokens.json", "format": "json/flat"}] } } } EOF echo "" # ============================================================================ # STEP 7: Validate 3-Layer Architecture # ============================================================================ log_step "7. Validating 3-layer architecture..." # Check core primitives if [ -f ".dss/core/primitives.json" ]; then PRIM_COUNT=$(python3 -c "import json; d=json.load(open('.dss/core/primitives.json')); print(sum(len(v) if isinstance(v,dict) else 0 for k,v in d.items() if not k.startswith('_')))" 2>/dev/null || echo "0") log_ok "Core primitives: $PRIM_COUNT tokens" else log_warn "Core primitives not found (.dss/core/primitives.json)" fi # Check skin contract if [ -f ".dss/schema/skin-contract.json" ]; then log_ok "Skin contract defined" else log_warn "Skin contract not found (.dss/schema/skin-contract.json)" fi # Check skins SKIN_COUNT=$(find .dss/skins -name "tokens.json" 2>/dev/null | wc -l) if [ "$SKIN_COUNT" -gt 0 ]; then log_ok "Skins available: $SKIN_COUNT" for skin in $(find .dss/skins -type d -mindepth 1 -maxdepth 1 2>/dev/null); do SKIN_NAME=$(basename "$skin") log_info " - $SKIN_NAME" done else log_warn "No skins found (.dss/skins/)" fi # Check themes THEME_COUNT=$(find .dss/themes -name "*.json" 2>/dev/null | grep -v "_" | wc -l) if [ "$THEME_COUNT" -gt 0 ]; then log_ok "Themes available: $THEME_COUNT" for theme in $(find .dss/themes -name "*.json" 2>/dev/null | grep -v "_"); do THEME_NAME=$(basename "$theme" .json) log_info " - $THEME_NAME" done else log_warn "No themes found (.dss/themes/)" fi # Run validation if available if [ -f "scripts/validate-theme.py" ] && [ -f ".dss/schema/skin-contract.json" ]; then log_info "Running theme/skin validation..." if python3 scripts/validate-theme.py --validate-skin --quiet 2>&1 | while read line; do echo " $line" done; then log_ok "All validations passed" else log_warn "Validation had issues - check output above" fi fi echo "" # ============================================================================ # STEP 8: Figma Sync # ============================================================================ log_step "8. Figma sync..." # Check if tokens are empty and Figma is available TOKEN_STATUS=$(python3 -c "import json; d=json.load(open('.dss/data/_system/tokens/base.json')); print(d.get('_meta',{}).get('status','empty'))" 2>/dev/null || echo "empty") if [ "$FIGMA_AVAILABLE" = true ] && [ "$TOKEN_STATUS" = "empty" ]; then log_info "Tokens empty - syncing from Figma..." # Get file key from config FIGMA_FILE_KEY=$(python3 -c "import json; print(json.load(open('$FIGMA_CONFIG')).get('uikit_reference',{}).get('file_key',''))" 2>/dev/null) if [ -n "$FIGMA_FILE_KEY" ]; then log_info "File: $FIGMA_FILE_KEY" # Run Figma sync script if python3 "$DSS_ROOT/scripts/figma-sync.py" --file-key "$FIGMA_FILE_KEY" 2>&1 | while read line; do echo " $line" done; then log_ok "Figma sync complete" else log_warn "Figma sync had issues - check output above" fi else log_warn "No UIKit file_key in config - add to .dss/config/figma.json" fi elif [ "$TOKEN_STATUS" != "empty" ]; then log_ok "Tokens already synced (status: $TOKEN_STATUS)" else log_warn "FIGMA_TOKEN not set - add to .dss/config/figma.json" fi echo "" # ============================================================================ # STEP 9: Resolve 3-Layer Token Cascade # ============================================================================ log_step "9. Resolving 3-layer token cascade..." # Check if we have the 3-layer structure HAS_PRIMITIVES=$([ -f ".dss/core/primitives.json" ] && echo "yes" || echo "no") HAS_SKINS=$([ -d ".dss/skins/shadcn" ] && echo "yes" || echo "no") if [ "$HAS_PRIMITIVES" = "yes" ] && [ "$HAS_SKINS" = "yes" ]; then log_info "Resolving: Core → Skin → Theme" if python3 scripts/resolve-tokens.py 2>&1 | while read line; do echo " $line" done; then log_ok "Token cascade resolved" else log_warn "Token resolution had issues" fi else log_warn "3-layer structure incomplete - using legacy tokens" fi echo "" # ============================================================================ # STEP 10: Build CSS with style-dictionary # ============================================================================ log_step "10. Building CSS from tokens..." # Re-check if tokens have content (may have been resolved in step 9) # Check tokens.json which is the style-dictionary input file HAS_TOKENS=$(python3 -c " import json try: d = json.load(open('.dss/data/_system/tokens/tokens.json')) has_content = bool(d) # tokens.json has direct categories like typography, effect print('yes' if has_content else 'no') except: print('no') " 2>/dev/null || echo "no") # Find style-dictionary (local, parent, home, or global) STYLE_DICT_CMD="" if [ -f "$DSS_ROOT/node_modules/.bin/style-dictionary" ]; then STYLE_DICT_CMD="$DSS_ROOT/node_modules/.bin/style-dictionary" elif [ -f "$HOME/node_modules/.bin/style-dictionary" ]; then STYLE_DICT_CMD="$HOME/node_modules/.bin/style-dictionary" elif [ -f "$(dirname "$DSS_ROOT")/node_modules/.bin/style-dictionary" ]; then STYLE_DICT_CMD="$(dirname "$DSS_ROOT")/node_modules/.bin/style-dictionary" elif command -v style-dictionary &> /dev/null; then STYLE_DICT_CMD="style-dictionary" fi if [ "$HAS_TOKENS" = "yes" ] && [ -n "$STYLE_DICT_CMD" ]; then log_info "Running style-dictionary build..." cd .dss/data/_system if $STYLE_DICT_CMD build --config style-dictionary.config.json 2>&1 | grep -v "^$"; then log_ok "CSS/SCSS/JSON generated in .dss/data/_system/themes/" else log_warn "style-dictionary build had issues" fi cd "$DSS_ROOT" # Show what was generated if [ -f ".dss/data/_system/themes/tokens.css" ]; then CSS_VARS=$(grep -c "^ --" .dss/data/_system/themes/tokens.css 2>/dev/null || echo "0") log_ok "Generated $CSS_VARS CSS variables" fi elif [ "$HAS_TOKENS" = "no" ]; then log_warn "No tokens - run Figma sync first" elif [ -z "$STYLE_DICT_CMD" ]; then log_warn "style-dictionary not found" log_info "Install: npm install style-dictionary (in project root)" fi echo "" # ============================================================================ # STEP 11: Generate Storybook Stories # ============================================================================ log_step "11. Generating Storybook stories..." if [ "$HAS_TOKENS" = "yes" ] && [ -f "scripts/generate-storybook.py" ]; then log_info "Building stories from tokens..." if python3 scripts/generate-storybook.py 2>&1 | while read line; do echo " $line" done; then STORY_COUNT=$(find admin-ui/src/stories -name "*.stories.js" 2>/dev/null | wc -l) log_ok "Generated $STORY_COUNT Storybook stories" else log_warn "Storybook generation had issues" fi else if [ "$HAS_TOKENS" = "no" ]; then log_warn "No tokens - skipping Storybook generation" else log_warn "Storybook generator not found (scripts/generate-storybook.py)" fi fi echo "" # ============================================================================ # STEP 12: Regenerate Hash Manifest # ============================================================================ log_step "12. Updating hash manifest..." if [ -f "scripts/regenerate-core-hashes.sh" ]; then ./scripts/regenerate-core-hashes.sh 2>/dev/null log_ok "Hash manifest updated" else log_warn "Hash script not found" fi echo "" # ============================================================================ # SUMMARY # ============================================================================ # Re-check token status after Figma sync FINAL_TOKEN_STATUS=$(python3 -c "import json; d=json.load(open('.dss/data/_system/tokens/base.json')); print(d.get('_meta',{}).get('status','empty'))" 2>/dev/null || echo "empty") FINAL_TOKEN_COUNT=$(python3 -c "import json; d=json.load(open('.dss/data/_system/tokens/base.json')); print(sum(len(v) for v in d.get('tokens',{}).values()))" 2>/dev/null || echo "0") # Determine overall status if [ -f ".dss/data/_system/themes/tokens.css" ]; then STATUS="READY" STATUS_MSG="admin-ui can import from .dss/data/_system/themes/" elif [ "$FINAL_TOKEN_STATUS" = "synced" ]; then STATUS="TOKENS SYNCED ($FINAL_TOKEN_COUNT tokens)" STATUS_MSG="Install style-dictionary to build CSS: npm install -g style-dictionary" elif [ "$FIGMA_AVAILABLE" = true ]; then STATUS="AWAITING FIGMA SYNC" STATUS_MSG="Run: dss_sync_figma or /dss-figma to populate tokens" else STATUS="AWAITING SETUP" STATUS_MSG="Set FIGMA_TOKEN environment variable first" fi echo "╔══════════════════════════════════════════════════════════════╗" echo "║ DSS INITIALIZATION COMPLETE ║" echo "╚══════════════════════════════════════════════════════════════╝" echo "" echo " Status: $STATUS" echo " → $STATUS_MSG" echo "" echo " 3-Layer Architecture:" echo " .dss/core/primitives.json ← Core Tailwind primitives (immutable)" echo " .dss/skins/*/tokens.json ← Skins (semantic mappings)" echo " .dss/themes/*.json ← Themes (brand overrides)" echo " .dss/schema/skin-contract ← Contract for skin compatibility" echo "" echo " Output:" echo " .dss/data/_system/themes/ ← CSS output for admin-ui" echo " .dss/data/_system/tokens/ ← Token JSON files" echo " admin-ui/src/stories/ ← Storybook stories" echo "" echo " Workflow:" echo " 1. scripts/dss-init.sh --reset # Fresh start" echo " 2. dss_sync_figma # Populate from Figma" echo " 3. scripts/dss-init.sh # Validate + Build CSS" echo " 4. admin-ui imports themes/ # Ready to use" echo ""