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,215 @@
#!/usr/bin/env node
/**
* DSS Complexity Monitor Hook
* Tracks code complexity metrics and warns on high-complexity code.
* Written from scratch for DSS.
*/
const fs = require('fs');
const path = require('path');
// Configuration
const DEFAULT_CONFIG = {
complexity_monitor: {
enabled: true,
max_function_lines: 50,
max_component_lines: 200,
max_props: 10,
max_nesting_depth: 4,
warn_only: true
}
};
function loadConfig() {
const configPath = path.join(process.env.HOME || '', '.dss', 'hooks-config.json');
try {
if (fs.existsSync(configPath)) {
const userConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));
return { ...DEFAULT_CONFIG, ...userConfig };
}
} catch (e) {
// Use defaults
}
return DEFAULT_CONFIG;
}
function countLines(content) {
return content.split('\n').length;
}
function countProps(content) {
// Count props in interface/type definition
const propsMatch = content.match(/(?:interface|type)\s+\w*Props[^{]*\{([^}]+)\}/);
if (propsMatch) {
const propsContent = propsMatch[1];
// Count semicolons or newlines with property definitions
const props = propsContent.split(/[;\n]/).filter(line => {
const trimmed = line.trim();
return trimmed && !trimmed.startsWith('//') && trimmed.includes(':');
});
return props.length;
}
return 0;
}
function countNestingDepth(content) {
let maxDepth = 0;
let currentDepth = 0;
for (const char of content) {
if (char === '{' || char === '(') {
currentDepth++;
maxDepth = Math.max(maxDepth, currentDepth);
} else if (char === '}' || char === ')') {
currentDepth = Math.max(0, currentDepth - 1);
}
}
return maxDepth;
}
function countFunctions(content) {
const patterns = [
/function\s+\w+\s*\([^)]*\)\s*\{/g,
/const\s+\w+\s*=\s*(?:async\s*)?\([^)]*\)\s*=>/g,
/const\s+\w+\s*=\s*(?:async\s*)?function/g
];
let count = 0;
for (const pattern of patterns) {
const matches = content.match(pattern);
if (matches) count += matches.length;
}
return count;
}
function analyzeComplexity(content, filePath, config) {
const issues = [];
const monitorConfig = config.complexity_monitor || {};
const ext = path.extname(filePath).toLowerCase();
// Only analyze JS/TS files
if (!['.js', '.jsx', '.ts', '.tsx'].includes(ext)) {
return issues;
}
const lines = countLines(content);
const props = countProps(content);
const nesting = countNestingDepth(content);
const functions = countFunctions(content);
// Check component size (for tsx/jsx files)
if (['.tsx', '.jsx'].includes(ext)) {
if (lines > monitorConfig.max_component_lines) {
issues.push({
type: 'component_size',
severity: 'medium',
message: `Component has ${lines} lines (max: ${monitorConfig.max_component_lines})`,
suggestion: 'Consider breaking into smaller components'
});
}
if (props > monitorConfig.max_props) {
issues.push({
type: 'prop_count',
severity: 'medium',
message: `Component has ${props} props (max: ${monitorConfig.max_props})`,
suggestion: 'Consider grouping related props or using composition'
});
}
}
// Check nesting depth
if (nesting > monitorConfig.max_nesting_depth) {
issues.push({
type: 'nesting_depth',
severity: 'high',
message: `Nesting depth of ${nesting} (max: ${monitorConfig.max_nesting_depth})`,
suggestion: 'Extract nested logic into separate functions'
});
}
// Check function count (indicator of file doing too much)
if (functions > 10) {
issues.push({
type: 'function_count',
severity: 'low',
message: `File contains ${functions} functions`,
suggestion: 'Consider splitting into multiple modules'
});
}
return issues;
}
function formatOutput(issues, filePath) {
if (issues.length === 0) return '';
const severityIcons = {
high: '[HIGH]',
medium: '[MED]',
low: '[LOW]'
};
const lines = [`\n=== DSS Complexity Monitor: ${filePath} ===\n`];
for (const issue of issues) {
const icon = severityIcons[issue.severity] || '[?]';
lines.push(`${icon} ${issue.message}`);
lines.push(` Suggestion: ${issue.suggestion}\n`);
}
lines.push('='.repeat(50));
return lines.join('\n');
}
async function main() {
const config = loadConfig();
if (!config.complexity_monitor?.enabled) {
process.exit(0);
}
// Read input from stdin
let inputData;
try {
const chunks = [];
for await (const chunk of process.stdin) {
chunks.push(chunk);
}
inputData = JSON.parse(Buffer.concat(chunks).toString());
} catch (e) {
process.exit(0);
}
const toolName = inputData.tool_name || '';
const toolInput = inputData.tool_input || {};
if (!['Edit', 'Write'].includes(toolName)) {
process.exit(0);
}
const filePath = toolInput.file_path || '';
let content = '';
if (toolName === 'Write') {
content = toolInput.content || '';
} else if (toolName === 'Edit') {
content = toolInput.new_string || '';
}
if (!content || !filePath) {
process.exit(0);
}
const issues = analyzeComplexity(content, filePath, config);
if (issues.length > 0) {
const output = formatOutput(issues, filePath);
console.error(output);
}
process.exit(0);
}
main().catch(() => process.exit(0));