claude-code-workflow 6.0.5 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/.claude/agents/action-planning-agent.md +1 -1
  2. package/.claude/agents/cli-execution-agent.md +269 -269
  3. package/.claude/agents/cli-explore-agent.md +182 -182
  4. package/.claude/agents/context-search-agent.md +582 -582
  5. package/.claude/agents/memory-bridge.md +93 -93
  6. package/.claude/commands/cli/cli-init.md +1 -1
  7. package/.claude/commands/memory/docs-full-cli.md +471 -471
  8. package/.claude/commands/memory/docs-related-cli.md +386 -386
  9. package/.claude/commands/memory/docs.md +615 -615
  10. package/.claude/commands/memory/load.md +1 -1
  11. package/.claude/commands/memory/update-full.md +332 -332
  12. package/.claude/commands/memory/update-related.md +5 -5
  13. package/.claude/commands/workflow/init.md +1 -1
  14. package/.claude/commands/workflow/lite-fix.md +621 -621
  15. package/.claude/commands/workflow/lite-plan.md +592 -592
  16. package/.claude/commands/workflow/tools/context-gather.md +434 -434
  17. package/.claude/commands/workflow/ui-design/generate.md +504 -504
  18. package/.claude/commands/workflow/ui-design/import-from-code.md +537 -537
  19. package/.claude/scripts/classify-folders.sh +4 -0
  20. package/.claude/scripts/convert_tokens_to_css.sh +4 -0
  21. package/.claude/scripts/detect_changed_modules.sh +5 -1
  22. package/.claude/scripts/discover-design-files.sh +87 -83
  23. package/.claude/scripts/generate_module_docs.sh +717 -713
  24. package/.claude/scripts/get_modules_by_depth.sh +5 -1
  25. package/.claude/scripts/ui-generate-preview.sh +4 -0
  26. package/.claude/scripts/ui-instantiate-prototypes.sh +4 -0
  27. package/.claude/scripts/update_module_claude.sh +4 -0
  28. package/.claude/skills/command-guide/index/all-commands.json +1 -12
  29. package/.claude/skills/command-guide/index/by-category.json +1 -12
  30. package/.claude/skills/command-guide/index/by-use-case.json +1 -12
  31. package/.claude/skills/command-guide/index/essential-commands.json +1 -12
  32. package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +127 -71
  33. package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +269 -269
  34. package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +182 -182
  35. package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +18 -38
  36. package/.claude/skills/command-guide/reference/agents/context-search-agent.md +582 -577
  37. package/.claude/skills/command-guide/reference/agents/memory-bridge.md +93 -93
  38. package/.claude/skills/command-guide/reference/commands/cli/cli-init.md +1 -1
  39. package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +471 -471
  40. package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +386 -386
  41. package/.claude/skills/command-guide/reference/commands/memory/docs.md +615 -610
  42. package/.claude/skills/command-guide/reference/commands/memory/load.md +1 -1
  43. package/.claude/skills/command-guide/reference/commands/memory/update-full.md +332 -332
  44. package/.claude/skills/command-guide/reference/commands/memory/update-related.md +5 -5
  45. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/artifacts.md +299 -451
  46. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +14 -37
  47. package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/synthesis.md +252 -350
  48. package/.claude/skills/command-guide/reference/commands/workflow/init.md +2 -2
  49. package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +52 -0
  50. package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +621 -602
  51. package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +46 -36
  52. package/.claude/skills/command-guide/reference/commands/workflow/review-fix.md +18 -58
  53. package/.claude/skills/command-guide/reference/commands/workflow/review-module-cycle.md +22 -52
  54. package/.claude/skills/command-guide/reference/commands/workflow/review-session-cycle.md +19 -48
  55. package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +25 -5
  56. package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +1 -1
  57. package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +7 -7
  58. package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +434 -434
  59. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +151 -11
  60. package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +4 -4
  61. package/.claude/skills/command-guide/reference/commands/workflow/tools/test-task-generate.md +1 -1
  62. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/generate.md +504 -504
  63. package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +537 -537
  64. package/.claude/workflows/context-search-strategy.md +77 -77
  65. package/.claude/workflows/tool-strategy.md +90 -71
  66. package/.claude/workflows/workflow-architecture.md +1 -1
  67. package/ccw/src/cli.js +7 -0
  68. package/ccw/src/commands/tool.js +181 -0
  69. package/ccw/src/core/dashboard-generator.js +18 -3
  70. package/ccw/src/core/lite-scanner.js +35 -11
  71. package/ccw/src/core/server.js +531 -46
  72. package/ccw/src/templates/dashboard-css/01-base.css +161 -0
  73. package/ccw/src/templates/dashboard-css/02-session.css +726 -0
  74. package/ccw/src/templates/dashboard-css/03-tasks.css +512 -0
  75. package/ccw/src/templates/dashboard-css/04-lite-tasks.css +843 -0
  76. package/ccw/src/templates/dashboard-css/05-context.css +2206 -0
  77. package/ccw/src/templates/dashboard-css/06-cards.css +1570 -0
  78. package/ccw/src/templates/dashboard-css/07-managers.css +936 -0
  79. package/ccw/src/templates/dashboard-css/08-review.css +1266 -0
  80. package/ccw/src/templates/dashboard-css/09-explorer.css +1397 -0
  81. package/ccw/src/templates/dashboard-js/components/global-notifications.js +219 -0
  82. package/ccw/src/templates/dashboard-js/components/hook-manager.js +10 -0
  83. package/ccw/src/templates/dashboard-js/components/mcp-manager.js +11 -1
  84. package/ccw/src/templates/dashboard-js/components/navigation.js +11 -5
  85. package/ccw/src/templates/dashboard-js/components/tabs-context.js +20 -20
  86. package/ccw/src/templates/dashboard-js/components/tabs-other.js +11 -11
  87. package/ccw/src/templates/dashboard-js/components/theme.js +29 -1
  88. package/ccw/src/templates/dashboard-js/main.js +4 -0
  89. package/ccw/src/templates/dashboard-js/state.js +5 -0
  90. package/ccw/src/templates/dashboard-js/views/explorer.js +852 -0
  91. package/ccw/src/templates/dashboard-js/views/home.js +13 -9
  92. package/ccw/src/templates/dashboard-js/views/hook-manager.js +8 -5
  93. package/ccw/src/templates/dashboard-js/views/lite-tasks.js +21 -16
  94. package/ccw/src/templates/dashboard-js/views/mcp-manager.js +90 -19
  95. package/ccw/src/templates/dashboard-js/views/project-overview.js +15 -11
  96. package/ccw/src/templates/dashboard-js/views/review-session.js +3 -3
  97. package/ccw/src/templates/dashboard-js/views/session-detail.js +38 -28
  98. package/ccw/src/templates/dashboard.html +129 -28
  99. package/ccw/src/tools/classify-folders.js +204 -0
  100. package/ccw/src/tools/convert-tokens-to-css.js +250 -0
  101. package/ccw/src/tools/detect-changed-modules.js +288 -0
  102. package/ccw/src/tools/discover-design-files.js +134 -0
  103. package/ccw/src/tools/edit-file.js +266 -0
  104. package/ccw/src/tools/generate-module-docs.js +416 -0
  105. package/ccw/src/tools/get-modules-by-depth.js +308 -0
  106. package/ccw/src/tools/index.js +176 -0
  107. package/ccw/src/tools/ui-generate-preview.js +327 -0
  108. package/ccw/src/tools/ui-instantiate-prototypes.js +301 -0
  109. package/ccw/src/tools/update-module-claude.js +380 -0
  110. package/package.json +1 -1
  111. package/.claude/skills/command-guide/reference/commands/workflow/status.md +0 -352
  112. package/ccw/src/core/server.js.bak +0 -385
  113. package/ccw/src/core/server_original.bak +0 -385
  114. package/ccw/src/templates/dashboard.css +0 -8187
  115. package/ccw/src/templates/dashboard_tailwind.html +0 -42
  116. package/ccw/src/templates/dashboard_test.html +0 -37
  117. package/ccw/src/templates/tailwind-base.css +0 -212
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Classify Folders Tool
3
+ * Categorize folders by type for documentation generation
4
+ * Types: code (API.md + README.md), navigation (README.md only), skip (empty)
5
+ */
6
+
7
+ import { readdirSync, statSync, existsSync } from 'fs';
8
+ import { join, resolve, extname } from 'path';
9
+
10
+ // Code file extensions
11
+ const CODE_EXTENSIONS = [
12
+ '.ts', '.tsx', '.js', '.jsx',
13
+ '.py', '.go', '.java', '.rs',
14
+ '.c', '.cpp', '.cs', '.rb',
15
+ '.php', '.swift', '.kt'
16
+ ];
17
+
18
+ /**
19
+ * Count code files in a directory (non-recursive)
20
+ */
21
+ function countCodeFiles(dirPath) {
22
+ try {
23
+ const entries = readdirSync(dirPath, { withFileTypes: true });
24
+ return entries.filter(e => {
25
+ if (!e.isFile()) return false;
26
+ const ext = extname(e.name).toLowerCase();
27
+ return CODE_EXTENSIONS.includes(ext);
28
+ }).length;
29
+ } catch (e) {
30
+ return 0;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Count subdirectories in a directory
36
+ */
37
+ function countSubdirs(dirPath) {
38
+ try {
39
+ const entries = readdirSync(dirPath, { withFileTypes: true });
40
+ return entries.filter(e => e.isDirectory() && !e.name.startsWith('.')).length;
41
+ } catch (e) {
42
+ return 0;
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Determine folder type
48
+ */
49
+ function classifyFolder(dirPath) {
50
+ const codeFiles = countCodeFiles(dirPath);
51
+ const subdirs = countSubdirs(dirPath);
52
+
53
+ if (codeFiles > 0) {
54
+ return { type: 'code', codeFiles, subdirs }; // Generates API.md + README.md
55
+ } else if (subdirs > 0) {
56
+ return { type: 'navigation', codeFiles, subdirs }; // README.md only
57
+ } else {
58
+ return { type: 'skip', codeFiles, subdirs }; // Empty or no relevant content
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Parse input from get_modules_by_depth format
64
+ * Format: depth:N|path:./path|files:N|types:[ext,ext]|has_claude:yes/no
65
+ */
66
+ function parseModuleInput(line) {
67
+ const parts = {};
68
+ line.split('|').forEach(part => {
69
+ const [key, value] = part.split(':');
70
+ if (key && value !== undefined) {
71
+ parts[key] = value;
72
+ }
73
+ });
74
+ return parts;
75
+ }
76
+
77
+ /**
78
+ * Main execute function
79
+ */
80
+ async function execute(params) {
81
+ const { input, path: targetPath } = params;
82
+
83
+ const results = [];
84
+
85
+ // Mode 1: Process piped input from get_modules_by_depth
86
+ if (input) {
87
+ let lines;
88
+
89
+ // Check if input is JSON (from ccw tool exec output)
90
+ if (typeof input === 'string' && input.trim().startsWith('{')) {
91
+ try {
92
+ const jsonInput = JSON.parse(input);
93
+ // Handle output from get_modules_by_depth tool (wrapped in result)
94
+ const output = jsonInput.result?.output || jsonInput.output;
95
+ if (output) {
96
+ lines = output.split('\n');
97
+ } else {
98
+ lines = [input];
99
+ }
100
+ } catch {
101
+ // Not JSON, treat as line-delimited text
102
+ lines = input.split('\n');
103
+ }
104
+ } else if (Array.isArray(input)) {
105
+ lines = input;
106
+ } else {
107
+ lines = input.split('\n');
108
+ }
109
+
110
+ for (const line of lines) {
111
+ if (!line.trim()) continue;
112
+
113
+ const parsed = parseModuleInput(line);
114
+ const folderPath = parsed.path;
115
+
116
+ if (!folderPath) continue;
117
+
118
+ const basePath = targetPath ? resolve(process.cwd(), targetPath) : process.cwd();
119
+ const fullPath = resolve(basePath, folderPath);
120
+
121
+ if (!existsSync(fullPath) || !statSync(fullPath).isDirectory()) {
122
+ continue;
123
+ }
124
+
125
+ const classification = classifyFolder(fullPath);
126
+
127
+ results.push({
128
+ path: folderPath,
129
+ type: classification.type,
130
+ code_files: classification.codeFiles,
131
+ subdirs: classification.subdirs
132
+ });
133
+ }
134
+ }
135
+ // Mode 2: Classify a single directory
136
+ else if (targetPath) {
137
+ const fullPath = resolve(process.cwd(), targetPath);
138
+
139
+ if (!existsSync(fullPath)) {
140
+ throw new Error(`Directory not found: ${fullPath}`);
141
+ }
142
+
143
+ if (!statSync(fullPath).isDirectory()) {
144
+ throw new Error(`Not a directory: ${fullPath}`);
145
+ }
146
+
147
+ const classification = classifyFolder(fullPath);
148
+
149
+ results.push({
150
+ path: targetPath,
151
+ type: classification.type,
152
+ code_files: classification.codeFiles,
153
+ subdirs: classification.subdirs
154
+ });
155
+ }
156
+ else {
157
+ throw new Error('Either "input" or "path" parameter is required');
158
+ }
159
+
160
+ // Format output
161
+ const output = results.map(r =>
162
+ `${r.path}|${r.type}|code:${r.code_files}|dirs:${r.subdirs}`
163
+ ).join('\n');
164
+
165
+ return {
166
+ total: results.length,
167
+ by_type: {
168
+ code: results.filter(r => r.type === 'code').length,
169
+ navigation: results.filter(r => r.type === 'navigation').length,
170
+ skip: results.filter(r => r.type === 'skip').length
171
+ },
172
+ results,
173
+ output
174
+ };
175
+ }
176
+
177
+ /**
178
+ * Tool Definition
179
+ */
180
+ export const classifyFoldersTool = {
181
+ name: 'classify_folders',
182
+ description: `Classify folders by type for documentation generation.
183
+ Types:
184
+ - code: Contains code files (generates API.md + README.md)
185
+ - navigation: Contains subdirectories only (generates README.md only)
186
+ - skip: Empty or no relevant content
187
+
188
+ Input: Either piped output from get_modules_by_depth or a single directory path.`,
189
+ parameters: {
190
+ type: 'object',
191
+ properties: {
192
+ input: {
193
+ type: 'string',
194
+ description: 'Piped input from get_modules_by_depth (one module per line)'
195
+ },
196
+ path: {
197
+ type: 'string',
198
+ description: 'Single directory path to classify'
199
+ }
200
+ },
201
+ required: []
202
+ },
203
+ execute
204
+ };
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Convert Tokens to CSS Tool
3
+ * Transform design-tokens.json to CSS custom properties
4
+ */
5
+
6
+ /**
7
+ * Generate Google Fonts import URL
8
+ */
9
+ function generateFontImport(fonts) {
10
+ if (!fonts || typeof fonts !== 'object') return '';
11
+
12
+ const fontParams = [];
13
+ const processedFonts = new Set();
14
+
15
+ // Extract font families from typography.font_family
16
+ Object.values(fonts).forEach(fontValue => {
17
+ if (typeof fontValue !== 'string') return;
18
+
19
+ // Get the primary font (before comma)
20
+ const primaryFont = fontValue.split(',')[0].trim().replace(/['"]/g, '');
21
+
22
+ // Skip system fonts
23
+ const systemFonts = ['system-ui', 'sans-serif', 'serif', 'monospace', 'cursive', 'fantasy'];
24
+ if (systemFonts.includes(primaryFont.toLowerCase())) return;
25
+ if (processedFonts.has(primaryFont)) return;
26
+
27
+ processedFonts.add(primaryFont);
28
+
29
+ // URL encode font name
30
+ const encodedFont = primaryFont.replace(/ /g, '+');
31
+
32
+ // Special handling for common fonts
33
+ const specialFonts = {
34
+ 'Comic Neue': 'Comic+Neue:wght@300;400;700',
35
+ 'Patrick Hand': 'Patrick+Hand:wght@400;700',
36
+ 'Caveat': 'Caveat:wght@400;700',
37
+ 'Dancing Script': 'Dancing+Script:wght@400;700'
38
+ };
39
+
40
+ if (specialFonts[primaryFont]) {
41
+ fontParams.push(`family=${specialFonts[primaryFont]}`);
42
+ } else {
43
+ fontParams.push(`family=${encodedFont}:wght@400;500;600;700`);
44
+ }
45
+ });
46
+
47
+ if (fontParams.length === 0) return '';
48
+
49
+ return `@import url('https://fonts.googleapis.com/css2?${fontParams.join('&')}&display=swap');`;
50
+ }
51
+
52
+ /**
53
+ * Generate CSS variables for a category
54
+ */
55
+ function generateCssVars(prefix, obj, indent = ' ') {
56
+ if (!obj || typeof obj !== 'object') return [];
57
+
58
+ const lines = [];
59
+ Object.entries(obj).forEach(([key, value]) => {
60
+ const varName = `--${prefix}-${key.replace(/_/g, '-')}`;
61
+ lines.push(`${indent}${varName}: ${value};`);
62
+ });
63
+ return lines;
64
+ }
65
+
66
+ /**
67
+ * Main execute function
68
+ */
69
+ async function execute(params) {
70
+ const { input } = params;
71
+
72
+ if (!input) {
73
+ throw new Error('Parameter "input" (design tokens JSON) is required');
74
+ }
75
+
76
+ // Parse input
77
+ let tokens;
78
+ try {
79
+ tokens = typeof input === 'string' ? JSON.parse(input) : input;
80
+ } catch (e) {
81
+ throw new Error(`Invalid JSON input: ${e.message}`);
82
+ }
83
+
84
+ const lines = [];
85
+
86
+ // Header
87
+ const styleName = tokens.meta?.name || 'Design Tokens';
88
+ lines.push('/* ========================================');
89
+ lines.push(` Design Tokens: ${styleName}`);
90
+ lines.push(' Auto-generated from design-tokens.json');
91
+ lines.push(' ======================================== */');
92
+ lines.push('');
93
+
94
+ // Google Fonts import
95
+ if (tokens.typography?.font_family) {
96
+ const fontImport = generateFontImport(tokens.typography.font_family);
97
+ if (fontImport) {
98
+ lines.push('/* Import Web Fonts */');
99
+ lines.push(fontImport);
100
+ lines.push('');
101
+ }
102
+ }
103
+
104
+ // CSS Custom Properties
105
+ lines.push(':root {');
106
+
107
+ // Colors
108
+ if (tokens.colors) {
109
+ if (tokens.colors.brand) {
110
+ lines.push(' /* Colors - Brand */');
111
+ lines.push(...generateCssVars('color-brand', tokens.colors.brand));
112
+ lines.push('');
113
+ }
114
+ if (tokens.colors.surface) {
115
+ lines.push(' /* Colors - Surface */');
116
+ lines.push(...generateCssVars('color-surface', tokens.colors.surface));
117
+ lines.push('');
118
+ }
119
+ if (tokens.colors.semantic) {
120
+ lines.push(' /* Colors - Semantic */');
121
+ lines.push(...generateCssVars('color-semantic', tokens.colors.semantic));
122
+ lines.push('');
123
+ }
124
+ if (tokens.colors.text) {
125
+ lines.push(' /* Colors - Text */');
126
+ lines.push(...generateCssVars('color-text', tokens.colors.text));
127
+ lines.push('');
128
+ }
129
+ if (tokens.colors.border) {
130
+ lines.push(' /* Colors - Border */');
131
+ lines.push(...generateCssVars('color-border', tokens.colors.border));
132
+ lines.push('');
133
+ }
134
+ }
135
+
136
+ // Typography
137
+ if (tokens.typography) {
138
+ if (tokens.typography.font_family) {
139
+ lines.push(' /* Typography - Font Family */');
140
+ lines.push(...generateCssVars('font-family', tokens.typography.font_family));
141
+ lines.push('');
142
+ }
143
+ if (tokens.typography.font_size) {
144
+ lines.push(' /* Typography - Font Size */');
145
+ lines.push(...generateCssVars('font-size', tokens.typography.font_size));
146
+ lines.push('');
147
+ }
148
+ if (tokens.typography.font_weight) {
149
+ lines.push(' /* Typography - Font Weight */');
150
+ lines.push(...generateCssVars('font-weight', tokens.typography.font_weight));
151
+ lines.push('');
152
+ }
153
+ if (tokens.typography.line_height) {
154
+ lines.push(' /* Typography - Line Height */');
155
+ lines.push(...generateCssVars('line-height', tokens.typography.line_height));
156
+ lines.push('');
157
+ }
158
+ if (tokens.typography.letter_spacing) {
159
+ lines.push(' /* Typography - Letter Spacing */');
160
+ lines.push(...generateCssVars('letter-spacing', tokens.typography.letter_spacing));
161
+ lines.push('');
162
+ }
163
+ }
164
+
165
+ // Spacing
166
+ if (tokens.spacing) {
167
+ lines.push(' /* Spacing */');
168
+ lines.push(...generateCssVars('spacing', tokens.spacing));
169
+ lines.push('');
170
+ }
171
+
172
+ // Border Radius
173
+ if (tokens.border_radius) {
174
+ lines.push(' /* Border Radius */');
175
+ lines.push(...generateCssVars('border-radius', tokens.border_radius));
176
+ lines.push('');
177
+ }
178
+
179
+ // Shadows
180
+ if (tokens.shadows) {
181
+ lines.push(' /* Shadows */');
182
+ lines.push(...generateCssVars('shadow', tokens.shadows));
183
+ lines.push('');
184
+ }
185
+
186
+ // Breakpoints
187
+ if (tokens.breakpoints) {
188
+ lines.push(' /* Breakpoints */');
189
+ lines.push(...generateCssVars('breakpoint', tokens.breakpoints));
190
+ lines.push('');
191
+ }
192
+
193
+ lines.push('}');
194
+ lines.push('');
195
+
196
+ // Global Font Application
197
+ lines.push('/* ========================================');
198
+ lines.push(' Global Font Application');
199
+ lines.push(' ======================================== */');
200
+ lines.push('');
201
+ lines.push('body {');
202
+ lines.push(' font-family: var(--font-family-body);');
203
+ lines.push(' font-size: var(--font-size-base);');
204
+ lines.push(' line-height: var(--line-height-normal);');
205
+ lines.push(' color: var(--color-text-primary);');
206
+ lines.push(' background-color: var(--color-surface-background);');
207
+ lines.push('}');
208
+ lines.push('');
209
+ lines.push('h1, h2, h3, h4, h5, h6, legend {');
210
+ lines.push(' font-family: var(--font-family-heading);');
211
+ lines.push('}');
212
+ lines.push('');
213
+ lines.push('/* Reset default margins for better control */');
214
+ lines.push('* {');
215
+ lines.push(' margin: 0;');
216
+ lines.push(' padding: 0;');
217
+ lines.push(' box-sizing: border-box;');
218
+ lines.push('}');
219
+
220
+ const css = lines.join('\n');
221
+
222
+ return {
223
+ style_name: styleName,
224
+ lines_count: lines.length,
225
+ css
226
+ };
227
+ }
228
+
229
+ /**
230
+ * Tool Definition
231
+ */
232
+ export const convertTokensToCssTool = {
233
+ name: 'convert_tokens_to_css',
234
+ description: `Transform design-tokens.json to CSS custom properties.
235
+ Generates:
236
+ - Google Fonts @import URL
237
+ - CSS custom properties for colors, typography, spacing, etc.
238
+ - Global font application rules`,
239
+ parameters: {
240
+ type: 'object',
241
+ properties: {
242
+ input: {
243
+ type: 'string',
244
+ description: 'Design tokens JSON string or object'
245
+ }
246
+ },
247
+ required: ['input']
248
+ },
249
+ execute
250
+ };