ultra-dex 2.2.1 → 3.2.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 (87) hide show
  1. package/README.md +112 -151
  2. package/assets/agents/00-AGENT_INDEX.md +1 -1
  3. package/assets/code-patterns/clerk-middleware.ts +138 -0
  4. package/assets/code-patterns/prisma-schema.prisma +224 -0
  5. package/assets/code-patterns/rls-policies.sql +246 -0
  6. package/assets/code-patterns/server-actions.ts +191 -0
  7. package/assets/code-patterns/trpc-router.ts +258 -0
  8. package/assets/cursor-rules/13-ai-integration.mdc +155 -0
  9. package/assets/cursor-rules/14-server-components.mdc +81 -0
  10. package/assets/cursor-rules/15-server-actions.mdc +102 -0
  11. package/assets/cursor-rules/16-edge-middleware.mdc +105 -0
  12. package/assets/cursor-rules/17-streaming-ssr.mdc +138 -0
  13. package/assets/docs/LAUNCH-POSTS.md +1 -1
  14. package/assets/docs/QUICK-REFERENCE.md +9 -4
  15. package/assets/docs/VISION-V2.md +1 -1
  16. package/assets/hooks/pre-commit +98 -0
  17. package/assets/saas-plan/04-Imp-Template.md +1 -1
  18. package/bin/ultra-dex.js +132 -4
  19. package/lib/commands/advanced.js +471 -0
  20. package/lib/commands/agent-builder.js +226 -0
  21. package/lib/commands/agents.js +102 -42
  22. package/lib/commands/auto-implement.js +68 -0
  23. package/lib/commands/banner.js +43 -21
  24. package/lib/commands/build.js +78 -183
  25. package/lib/commands/ci-monitor.js +84 -0
  26. package/lib/commands/config.js +207 -0
  27. package/lib/commands/dashboard.js +770 -0
  28. package/lib/commands/diff.js +233 -0
  29. package/lib/commands/doctor.js +416 -0
  30. package/lib/commands/export.js +408 -0
  31. package/lib/commands/fix.js +96 -0
  32. package/lib/commands/generate.js +105 -78
  33. package/lib/commands/hooks.js +251 -76
  34. package/lib/commands/init.js +102 -54
  35. package/lib/commands/memory.js +80 -0
  36. package/lib/commands/plan.js +82 -0
  37. package/lib/commands/review.js +34 -5
  38. package/lib/commands/run.js +233 -0
  39. package/lib/commands/scaffold.js +151 -0
  40. package/lib/commands/serve.js +179 -146
  41. package/lib/commands/state.js +327 -0
  42. package/lib/commands/swarm.js +306 -0
  43. package/lib/commands/sync.js +82 -23
  44. package/lib/commands/team.js +275 -0
  45. package/lib/commands/upgrade.js +190 -0
  46. package/lib/commands/validate.js +34 -0
  47. package/lib/commands/verify.js +81 -0
  48. package/lib/commands/watch.js +79 -0
  49. package/lib/config/theme.js +47 -0
  50. package/lib/mcp/graph.js +92 -0
  51. package/lib/mcp/memory.js +95 -0
  52. package/lib/mcp/resources.js +152 -0
  53. package/lib/mcp/server.js +34 -0
  54. package/lib/mcp/tools.js +481 -0
  55. package/lib/mcp/websocket.js +117 -0
  56. package/lib/providers/index.js +49 -4
  57. package/lib/providers/ollama.js +136 -0
  58. package/lib/providers/router.js +63 -0
  59. package/lib/quality/scanner.js +128 -0
  60. package/lib/swarm/coordinator.js +97 -0
  61. package/lib/swarm/index.js +598 -0
  62. package/lib/swarm/protocol.js +677 -0
  63. package/lib/swarm/tiers.js +485 -0
  64. package/lib/templates/code/clerk-middleware.ts +138 -0
  65. package/lib/templates/code/prisma-schema.prisma +224 -0
  66. package/lib/templates/code/rls-policies.sql +246 -0
  67. package/lib/templates/code/server-actions.ts +191 -0
  68. package/lib/templates/code/trpc-router.ts +258 -0
  69. package/lib/templates/custom-agent.md +10 -0
  70. package/lib/themes/doomsday.js +229 -0
  71. package/lib/ui/index.js +5 -0
  72. package/lib/ui/interface.js +241 -0
  73. package/lib/ui/spinners.js +116 -0
  74. package/lib/ui/theme.js +183 -0
  75. package/lib/utils/agents.js +32 -0
  76. package/lib/utils/files.js +14 -0
  77. package/lib/utils/graph.js +108 -0
  78. package/lib/utils/help.js +64 -0
  79. package/lib/utils/messages.js +35 -0
  80. package/lib/utils/progress.js +24 -0
  81. package/lib/utils/prompts.js +47 -0
  82. package/lib/utils/spinners.js +46 -0
  83. package/lib/utils/status.js +31 -0
  84. package/lib/utils/tables.js +41 -0
  85. package/lib/utils/theme-state.js +9 -0
  86. package/lib/utils/version-display.js +32 -0
  87. package/package.json +31 -13
@@ -10,11 +10,15 @@ import fs from 'fs/promises';
10
10
  import path from 'path';
11
11
  import { createProvider, getDefaultProvider, checkConfiguredProviders } from '../providers/index.js';
12
12
  import { SYSTEM_PROMPT, generateUserPrompt } from '../templates/prompts/generate-plan.js';
13
+ import { validateSafePath } from '../utils/validation.js';
14
+ import { githubTreeUrl, githubWebUrl } from '../config/urls.js';
15
+ import { saveState } from './plan.js';
16
+ import { getRandomMessage } from '../utils/messages.js';
13
17
 
14
18
  export function registerGenerateCommand(program) {
15
19
  program
16
20
  .command('generate [idea]')
17
- .description('Generate a full implementation plan from an idea using AI')
21
+ .description('Create the plan (Thanos style) - AI Generates Full Plan')
18
22
  .option('-p, --provider <provider>', 'AI provider (claude, openai, gemini)')
19
23
  .option('-m, --model <model>', 'Specific model to use')
20
24
  .option('-o, --output <directory>', 'Output directory', '.')
@@ -22,14 +26,22 @@ export function registerGenerateCommand(program) {
22
26
  .option('--stream', 'Stream output in real-time', true)
23
27
  .option('--no-stream', 'Disable streaming')
24
28
  .action(async (idea, options) => {
25
- console.log(chalk.cyan('\n🚀 Ultra-Dex Plan Generator\n'));
29
+ console.log(chalk.cyan('\n🚀 Ultra-Dex Plan Generator (Reality Stone Mode)\n'));
30
+ console.log(chalk.hex('#7c3aed').italic(`"${getRandomMessage('start')}"`));
31
+ console.log('');
32
+
33
+ const dirValidation = validateSafePath(options.output, 'Output directory');
34
+ if (dirValidation !== true) {
35
+ console.log(chalk.red(dirValidation));
36
+ process.exit(1);
37
+ }
26
38
 
27
39
  // Check configured providers
28
40
  const configured = checkConfiguredProviders();
29
41
  const hasProvider = configured.some(p => p.configured) || options.key;
30
42
 
31
43
  if (!hasProvider) {
32
- console.log(chalk.yellow('⚠️ No AI provider configured.\n'));
44
+ console.log(chalk.yellow('⚠️ No Infinity Stones (AI Keys) configured.\n'));
33
45
  console.log(chalk.white('Set one of these environment variables:'));
34
46
  configured.forEach(p => {
35
47
  console.log(chalk.gray(` export ${p.envKey}=your-key-here`));
@@ -45,7 +57,7 @@ export function registerGenerateCommand(program) {
45
57
  {
46
58
  type: 'input',
47
59
  name: 'idea',
48
- message: 'Describe your SaaS idea:',
60
+ message: 'Describe the reality you wish to create:',
49
61
  validate: input => input.trim().length > 10 || 'Please provide a more detailed description',
50
62
  },
51
63
  ]);
@@ -76,7 +88,7 @@ export function registerGenerateCommand(program) {
76
88
  }
77
89
 
78
90
  // Generate the plan
79
- const spinner = ora('Generating your implementation plan...').start();
91
+ const spinner = ora('Reshaping reality (Generating Plan)...').start();
80
92
  const startTime = Date.now();
81
93
 
82
94
  try {
@@ -85,7 +97,7 @@ export function registerGenerateCommand(program) {
85
97
 
86
98
  if (options.stream) {
87
99
  spinner.stop();
88
- console.log(chalk.cyan('📝 Generating plan:\n'));
100
+ console.log(chalk.cyan('📝 Manifesting Reality:\n'));
89
101
  console.log(chalk.gray('─'.repeat(60)));
90
102
 
91
103
  result = await provider.generateStream(
@@ -119,99 +131,114 @@ export function registerGenerateCommand(program) {
119
131
  // Add header to plan
120
132
  const header = `# Implementation Plan
121
133
 
122
- > Generated by Ultra-Dex on ${new Date().toISOString().split('T')[0]}
123
- > Idea: "${idea}"
124
-
125
- ---
134
+ > Generated by Ultra-Dex AI Plan Generator (Doomsday Edition)
126
135
 
127
136
  `;
128
- await fs.writeFile(planPath, header + planContent);
137
+ if (!planContent.startsWith('#')) {
138
+ planContent = header + planContent;
139
+ }
140
+
141
+ await fs.writeFile(planPath, planContent);
142
+
143
+ // --- NEW: Generate state.json (ACTIVE SCALFOLDING) ---
144
+ const projectName = idea.split(' ').slice(0, 3).join('-').toLowerCase().replace(/[^a-z0-9-]/g, '');
145
+
146
+ const state = {
147
+ project: {
148
+ name: projectName,
149
+ version: '0.1.0',
150
+ mode: 'AI-First',
151
+ idea: idea
152
+ },
153
+ phases: [
154
+ {
155
+ id: '1',
156
+ name: 'Phase 1: Foundation',
157
+ status: 'in_progress',
158
+ steps: [
159
+ { id: '1.1', task: 'Setup project boilerplate', status: 'pending' },
160
+ { id: '1.2', task: 'Database schema design', status: 'pending' },
161
+ { id: '1.3', task: 'Authentication implementation', status: 'pending' }
162
+ ]
163
+ },
164
+ {
165
+ id: '2',
166
+ name: 'Phase 2: Core Features',
167
+ status: 'pending',
168
+ steps: [
169
+ { id: '2.1', task: 'Implement primary feature loop', status: 'pending' },
170
+ { id: '2.2', task: 'API endpoint development', status: 'pending' }
171
+ ]
172
+ }
173
+ ],
174
+ agents: {
175
+ active: ['planner', 'cto'],
176
+ registry: ['planner', 'cto', 'backend', 'frontend', 'database', 'testing', 'reviewer']
177
+ }
178
+ };
179
+
180
+ await saveState(state);
129
181
 
130
182
  // Generate CONTEXT.md
131
183
  const contextContent = `# Project Context
132
184
 
133
- ## Overview
185
+ ## Project Info
186
+ **Created:** ${new Date().toLocaleDateString()}
187
+ **Idea:** ${idea}
188
+ **Status:** Planning
189
+
190
+ ## Summary
134
191
  ${idea}
135
192
 
136
- ## Generated
137
- - Date: ${new Date().toISOString().split('T')[0]}
138
- - Provider: ${provider.getName()}
139
- - Model: ${provider.model}
140
-
141
- ## Files
142
- - IMPLEMENTATION-PLAN.md - Full 34-section plan
143
- - QUICK-START.md - Quick reference
144
- - CONTEXT.md - This file
145
-
146
- ## Usage
147
- Provide this context to any AI agent:
148
- \`\`\`
149
- Act as @Backend. Read CONTEXT.md and IMPLEMENTATION-PLAN.md first.
150
- Task: [your task]
151
- \`\`\`
193
+ ## Current Focus
194
+ Review implementation plan and begin development.
195
+
196
+ ## Ultra-Dex Resources
197
+ - Official Template: ${githubWebUrl()}
198
+ - Documentation: ${githubTreeUrl('docs')}
152
199
  `;
200
+
153
201
  await fs.writeFile(contextPath, contextContent);
154
202
 
155
203
  // Generate QUICK-START.md
156
204
  const quickStartContent = `# Quick Start
157
205
 
158
- ## Your Idea
206
+ ## Project Idea
159
207
  ${idea}
160
208
 
161
209
  ## Next Steps
162
-
163
- 1. **Review the plan**: Open IMPLEMENTATION-PLAN.md
164
- 2. **Load into AI**: Copy CONTEXT.md to your AI tool
165
- 3. **Start building**: Use \`npx ultra-dex build\` or paste prompts
166
-
167
- ## Useful Commands
168
-
169
- \`\`\`bash
170
- npx ultra-dex build # Start AI-assisted build
171
- npx ultra-dex review # Check code against plan
172
- npx ultra-dex serve # Serve context via HTTP
173
- npx ultra-dex agents # List available agents
174
- \`\`\`
175
-
176
- ## Agent Quick Start
177
-
178
- \`\`\`
179
- @Planner - Break down tasks
180
- @Backend - API endpoints
181
- @Frontend - UI components
182
- @Database - Schema design
183
- @Auth - Authentication
184
- @Testing - Write tests
185
- \`\`\`
210
+ 1. Review IMPLEMENTATION-PLAN.md
211
+ 2. Start with the first feature
212
+ 3. Use Ultra-Dex agents for guidance
213
+
214
+ ## AI Agents (The Avengers)
215
+ - @Planner (Nick Fury): Break down tasks
216
+ - @CTO (Iron Man): Architecture decisions
217
+ - @Backend (Thor): API logic
218
+ - @Frontend (Spider-Man): UI components
219
+ - @Testing (Ant-Man): QA and tests
186
220
  `;
187
- await fs.writeFile(quickStartPath, quickStartContent);
188
-
189
- // Print summary
190
- console.log(chalk.green('\n✅ Plan generated successfully!\n'));
191
- console.log(chalk.white('Files created:'));
192
- console.log(chalk.gray(` 📄 ${planPath}`));
193
- console.log(chalk.gray(` 📄 ${contextPath}`));
194
- console.log(chalk.gray(` 📄 ${quickStartPath}`));
195
-
196
- console.log(chalk.white('\nStats:'));
197
- console.log(chalk.gray(` ⏱️ Time: ${elapsed}s`));
198
- console.log(chalk.gray(` 📊 Tokens: ${result.usage.inputTokens} in / ${result.usage.outputTokens} out`));
199
- console.log(chalk.gray(` 💰 Cost: ~$${cost.total.toFixed(4)}`));
200
221
 
201
- console.log(chalk.cyan('\n📋 Next steps:'));
202
- console.log(chalk.white(' 1. Review IMPLEMENTATION-PLAN.md'));
203
- console.log(chalk.white(' 2. Run: npx ultra-dex build'));
204
- console.log(chalk.white(' 3. Start coding with AI agents\n'));
222
+ await fs.writeFile(quickStartPath, quickStartContent);
205
223
 
224
+ spinner.succeed(chalk.green('Reality successfully rewritten!'));
225
+
226
+ console.log(chalk.green('\n✅ Files created:'));
227
+ console.log(chalk.gray(` ${planPath}`));
228
+ console.log(chalk.gray(` ${contextPath}`));
229
+ console.log(chalk.gray(` ${quickStartPath}`));
230
+ console.log(chalk.gray(` .ultra/state.json (GOD MODE ACTIVE)`));
231
+ console.log(chalk.gray(`\n⏱️ Time: ${elapsed}s`));
232
+ console.log(chalk.gray(`💰 Est. cost: ${cost}`));
233
+
234
+ console.log(chalk.bold('\nNext steps:'));
235
+ console.log(chalk.cyan(' 1. Review IMPLEMENTATION-PLAN.md'));
236
+ console.log(chalk.cyan(' 2. Run `ultra-dex dashboard` to visualize your progress'));
237
+ console.log(chalk.cyan(' 3. Run `ultra-dex build` to let Auto-Pilot take the first task'));
238
+ console.log(chalk.cyan(' 4. Summon Avengers (AI agents) for guidance\n'));
206
239
  } catch (err) {
207
- spinner.fail('Generation failed');
208
- console.log(chalk.red(`\nError: ${err.message}`));
209
-
210
- if (err.message.includes('API')) {
211
- console.log(chalk.yellow('\nTip: Check your API key and try again.'));
212
- }
240
+ spinner.fail(chalk.red('Failed to manifest reality'));
241
+ console.error(chalk.red('Error:'), err.message);
213
242
  }
214
243
  });
215
244
  }
216
-
217
- export default { registerGenerateCommand };
@@ -1,105 +1,280 @@
1
1
  import chalk from 'chalk';
2
2
  import fs from 'fs/promises';
3
3
  import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
4
8
 
5
9
  export function registerHooksCommand(program) {
6
- program
10
+ const hooks = program
7
11
  .command('hooks')
8
- .description('Set up git hooks for automated verification')
9
- .option('--remove', 'Remove Ultra-Dex git hooks')
12
+ .description('Manage Ultra-Dex git hooks for automated verification');
13
+
14
+ // Install subcommand
15
+ hooks
16
+ .command('install')
17
+ .description('Install Ultra-Dex pre-commit hook to .git/hooks/')
18
+ .option('--force', 'Overwrite existing hooks')
19
+ .option('--min-score <score>', 'Minimum alignment score (default: 70)', '70')
10
20
  .action(async (options) => {
11
- console.log(chalk.cyan('\n🪝 Ultra-Dex Git Hooks Setup\n'));
21
+ console.log(chalk.cyan('\n🪝 Ultra-Dex Git Hooks Installation\n'));
22
+ await installHook(options);
23
+ });
12
24
 
13
- const gitDir = path.join(process.cwd(), '.git');
14
- const hooksDir = path.join(gitDir, 'hooks');
25
+ // Remove subcommand
26
+ hooks
27
+ .command('remove')
28
+ .alias('uninstall')
29
+ .description('Remove Ultra-Dex git hooks')
30
+ .action(async () => {
31
+ console.log(chalk.cyan('\n🪝 Ultra-Dex Git Hooks Removal\n'));
32
+ await removeHook();
33
+ });
15
34
 
16
- try {
17
- await fs.access(gitDir);
18
- } catch {
19
- console.log(chalk.red(' Not a git repository. Run "git init" first.\n'));
20
- process.exit(1);
35
+ // Status subcommand
36
+ hooks
37
+ .command('status')
38
+ .description('Check if Ultra-Dex hooks are installed')
39
+ .action(async () => {
40
+ console.log(chalk.cyan('\n🪝 Ultra-Dex Git Hooks Status\n'));
41
+ await checkHookStatus();
42
+ });
43
+
44
+ // Default action (legacy support)
45
+ hooks
46
+ .option('--remove', 'Remove Ultra-Dex git hooks (deprecated: use "hooks remove")')
47
+ .action(async (options) => {
48
+ if (options.remove) {
49
+ console.log(chalk.cyan('\n🪝 Ultra-Dex Git Hooks Removal\n'));
50
+ await removeHook();
51
+ } else {
52
+ // Show help if no subcommand
53
+ hooks.outputHelp();
21
54
  }
55
+ });
56
+ }
22
57
 
23
- await fs.mkdir(hooksDir, { recursive: true });
58
+ async function getGitHooksDir() {
59
+ const gitDir = path.join(process.cwd(), '.git');
60
+ const hooksDir = path.join(gitDir, 'hooks');
24
61
 
25
- const preCommitPath = path.join(hooksDir, 'pre-commit');
62
+ try {
63
+ await fs.access(gitDir);
64
+ } catch {
65
+ console.log(chalk.red('❌ Not a git repository. Run "git init" first.\n'));
66
+ process.exit(1);
67
+ }
26
68
 
27
- if (options.remove) {
28
- try {
29
- const content = await fs.readFile(preCommitPath, 'utf-8');
30
- if (content.includes('ultra-dex')) {
31
- await fs.unlink(preCommitPath);
32
- console.log(chalk.green('✅ Ultra-Dex pre-commit hook removed.\n'));
33
- } else {
34
- console.log(chalk.yellow('⚠️ Pre-commit hook exists but is not from Ultra-Dex.\n'));
35
- }
36
- } catch {
37
- console.log(chalk.gray('No Ultra-Dex hooks found.\n'));
38
- }
69
+ await fs.mkdir(hooksDir, { recursive: true });
70
+ return hooksDir;
71
+ }
72
+
73
+ async function getPreCommitHookPath() {
74
+ // Try to find the bundled hook first
75
+ const possiblePaths = [
76
+ path.join(__dirname, '..', '..', 'assets', 'hooks', 'pre-commit'),
77
+ path.join(__dirname, '..', '..', '..', 'assets', 'hooks', 'pre-commit'),
78
+ ];
79
+
80
+ for (const hookPath of possiblePaths) {
81
+ try {
82
+ await fs.access(hookPath);
83
+ return hookPath;
84
+ } catch {
85
+ // Continue to next path
86
+ }
87
+ }
88
+
89
+ return null;
90
+ }
91
+
92
+ async function installHook(options) {
93
+ const hooksDir = await getGitHooksDir();
94
+ const preCommitPath = path.join(hooksDir, 'pre-commit');
95
+ const minScore = parseInt(options.minScore, 10) || 70;
96
+
97
+ // Try to use bundled hook
98
+ const bundledHookPath = await getPreCommitHookPath();
99
+ let hookScript;
100
+
101
+ if (bundledHookPath) {
102
+ hookScript = await fs.readFile(bundledHookPath, 'utf-8');
103
+ // Update minimum score if specified
104
+ hookScript = hookScript.replace(/MIN_ALIGNMENT_SCORE=\d+/, `MIN_ALIGNMENT_SCORE=${minScore}`);
105
+ console.log(chalk.gray(` Using bundled hook from: ${bundledHookPath}`));
106
+ } else {
107
+ // Fallback to embedded script
108
+ hookScript = generatePreCommitScript(minScore);
109
+ console.log(chalk.gray(' Using embedded hook script'));
110
+ }
111
+
112
+ try {
113
+ const existing = await fs.readFile(preCommitPath, 'utf-8');
114
+ if (existing.includes('ultra-dex') || existing.includes('Ultra-Dex')) {
115
+ if (options.force) {
116
+ await fs.writeFile(preCommitPath, hookScript);
117
+ await fs.chmod(preCommitPath, '755');
118
+ console.log(chalk.green('✅ Ultra-Dex pre-commit hook updated (--force).\n'));
119
+ } else {
120
+ console.log(chalk.yellow('⚠️ Ultra-Dex pre-commit hook already exists.\n'));
121
+ console.log(chalk.gray(' Use --force to overwrite, or "hooks remove" first.\n'));
39
122
  return;
40
123
  }
124
+ } else {
125
+ // Append to existing hook
126
+ const combined = existing + '\n\n' + hookScript;
127
+ await fs.writeFile(preCommitPath, combined);
128
+ await fs.chmod(preCommitPath, '755');
129
+ console.log(chalk.green('✅ Ultra-Dex hook appended to existing pre-commit.\n'));
130
+ }
131
+ } catch {
132
+ // No existing hook, create new one
133
+ await fs.writeFile(preCommitPath, hookScript);
134
+ await fs.chmod(preCommitPath, '755');
135
+ console.log(chalk.green('✅ Pre-commit hook installed.\n'));
136
+ }
137
+
138
+ printHookInfo(minScore);
139
+ }
41
140
 
42
- const preCommitScript = `#!/bin/sh
43
- # Ultra-Dex Pre-Commit Hook
44
- # Validates project structure before allowing commits
45
- # Remove with: npx ultra-dex hooks --remove
141
+ async function removeHook() {
142
+ const hooksDir = await getGitHooksDir();
143
+ const preCommitPath = path.join(hooksDir, 'pre-commit');
46
144
 
47
- echo "🔍 Ultra-Dex: Validating project structure..."
145
+ try {
146
+ const content = await fs.readFile(preCommitPath, 'utf-8');
147
+ if (content.includes('ultra-dex') || content.includes('Ultra-Dex')) {
148
+ await fs.unlink(preCommitPath);
149
+ console.log(chalk.green('✅ Ultra-Dex pre-commit hook removed.\n'));
150
+ } else {
151
+ console.log(chalk.yellow('⚠️ Pre-commit hook exists but is not from Ultra-Dex.\n'));
152
+ }
153
+ } catch {
154
+ console.log(chalk.gray('No Ultra-Dex hooks found.\n'));
155
+ }
156
+ }
48
157
 
49
- # Run validation
50
- npx ultra-dex validate --dir . > /tmp/ultra-dex-validate.log 2>&1
51
- RESULT=$?
52
-
53
- if [ $RESULT -ne 0 ]; then
54
- echo ""
55
- echo "❌ Ultra-Dex validation failed. Commit blocked."
56
- echo ""
57
- echo "Run 'npx ultra-dex validate' to see details."
58
- echo "Fix issues or bypass with: git commit --no-verify"
59
- echo ""
60
- exit 1
158
+ async function checkHookStatus() {
159
+ const hooksDir = await getGitHooksDir();
160
+ const preCommitPath = path.join(hooksDir, 'pre-commit');
161
+
162
+ try {
163
+ const content = await fs.readFile(preCommitPath, 'utf-8');
164
+ if (content.includes('ultra-dex') || content.includes('Ultra-Dex')) {
165
+ console.log(chalk.green('✅ Ultra-Dex pre-commit hook is installed.\n'));
166
+
167
+ // Extract min score if present
168
+ const scoreMatch = content.match(/MIN_ALIGNMENT_SCORE=(\d+)/);
169
+ if (scoreMatch) {
170
+ console.log(chalk.gray(` Minimum alignment score: ${scoreMatch[1]}%\n`));
171
+ }
172
+ } else {
173
+ console.log(chalk.yellow('⚠️ Pre-commit hook exists but is not from Ultra-Dex.\n'));
174
+ }
175
+ } catch {
176
+ console.log(chalk.gray('❌ No pre-commit hook installed.\n'));
177
+ console.log(chalk.cyan(' Install with: npx ultra-dex hooks install\n'));
178
+ }
179
+ }
180
+
181
+ function printHookInfo(minScore) {
182
+ console.log(chalk.bold('What this does:\n'));
183
+ console.log(chalk.gray(` • Checks alignment score (minimum: ${minScore}%)`));
184
+ console.log(chalk.gray(' • Runs "ultra-dex validate" before each commit'));
185
+ console.log(chalk.gray(' • Blocks commits if validation fails'));
186
+ console.log(chalk.gray(' • Warns about missing documentation\n'));
187
+
188
+ console.log(chalk.bold('To bypass (not recommended):\n'));
189
+ console.log(chalk.cyan(' git commit --no-verify\n'));
190
+
191
+ console.log(chalk.bold('To check status:\n'));
192
+ console.log(chalk.cyan(' npx ultra-dex hooks status\n'));
193
+
194
+ console.log(chalk.bold('To remove:\n'));
195
+ console.log(chalk.cyan(' npx ultra-dex hooks remove\n'));
196
+ }
197
+
198
+ function generatePreCommitScript(minScore = 70) {
199
+ return `#!/bin/sh
200
+ # Ultra-Dex Pre-Commit Hook v3.0
201
+ # Validates project alignment and structure before allowing commits
202
+ # Install with: npx ultra-dex hooks install
203
+ # Remove with: npx ultra-dex hooks remove
204
+
205
+ set -e
206
+
207
+ echo ""
208
+ echo "🎯 Ultra-Dex: Running pre-commit validation..."
209
+ echo ""
210
+
211
+ # Configuration
212
+ MIN_ALIGNMENT_SCORE=${minScore}
213
+ VALIDATION_LOG="/tmp/ultra-dex-validate.log"
214
+ ALIGN_LOG="/tmp/ultra-dex-align.log"
215
+
216
+ # Check if ultra-dex is available
217
+ if ! command -v ultra-dex &> /dev/null && ! npx ultra-dex --version &> /dev/null 2>&1; then
218
+ echo "⚠️ Ultra-Dex not found. Skipping validation."
219
+ echo " Install with: npm install -g ultra-dex"
220
+ exit 0
61
221
  fi
62
222
 
63
- # Check for required files
64
- if [ ! -f "QUICK-START.md" ]; then
65
- echo "⚠️ Warning: QUICK-START.md not found"
223
+ # Run alignment check and capture score
224
+ echo "📊 Checking alignment score..."
225
+ npx ultra-dex align --dir . > "$ALIGN_LOG" 2>&1 || true
226
+
227
+ # Extract score from output
228
+ SCORE=$(grep -oE '[0-9]+%' "$ALIGN_LOG" | head -1 | tr -d '%' || echo "0")
229
+
230
+ if [ -z "$SCORE" ] || [ "$SCORE" = "0" ]; then
231
+ SCORE=$(grep -oE 'Score: [0-9]+' "$ALIGN_LOG" | grep -oE '[0-9]+' | head -1 || echo "85")
66
232
  fi
67
233
 
68
- if [ ! -f "IMPLEMENTATION-PLAN.md" ]; then
69
- echo "⚠️ Warning: IMPLEMENTATION-PLAN.md not found"
234
+ echo " Current alignment score: \${SCORE}%"
235
+
236
+ # Check minimum score threshold
237
+ if [ "$SCORE" -lt "$MIN_ALIGNMENT_SCORE" ]; then
238
+ echo ""
239
+ echo "❌ COMMIT BLOCKED: Alignment score (\$SCORE%) is below minimum ($MIN_ALIGNMENT_SCORE%)"
240
+ echo ""
241
+ echo "📋 To fix this:"
242
+ echo " 1. Run: npx ultra-dex validate"
243
+ echo " 2. Run: npx ultra-dex fix (to auto-fix issues)"
244
+ echo " 3. Review and commit again"
245
+ echo ""
246
+ echo "🔓 To bypass (not recommended):"
247
+ echo " git commit --no-verify"
248
+ echo ""
249
+ exit 1
70
250
  fi
71
251
 
72
- echo "✅ Ultra-Dex validation passed."
73
- exit 0
74
- `;
252
+ # Run validation
253
+ echo "🔍 Running validation checks..."
254
+ npx ultra-dex validate --dir . --scan > "$VALIDATION_LOG" 2>&1
255
+ VALIDATE_RESULT=$?
75
256
 
76
- try {
77
- const existing = await fs.readFile(preCommitPath, 'utf-8');
78
- if (existing.includes('ultra-dex')) {
79
- console.log(chalk.yellow('⚠️ Ultra-Dex pre-commit hook already exists.\n'));
80
- console.log(chalk.gray(' Use --remove to remove it first.\n'));
81
- return;
82
- } else {
83
- const combined = existing + '\n\n' + preCommitScript;
84
- await fs.writeFile(preCommitPath, combined);
85
- await fs.chmod(preCommitPath, '755');
86
- console.log(chalk.green('✅ Ultra-Dex hook appended to existing pre-commit.\n'));
87
- }
88
- } catch {
89
- await fs.writeFile(preCommitPath, preCommitScript);
90
- await fs.chmod(preCommitPath, '755');
91
- console.log(chalk.green('✅ Pre-commit hook installed.\n'));
92
- }
257
+ if [ $VALIDATE_RESULT -ne 0 ]; then
258
+ echo ""
259
+ echo "❌ COMMIT BLOCKED: Validation failed"
260
+ echo ""
261
+ cat "$VALIDATION_LOG"
262
+ echo ""
263
+ echo "📋 Run 'npx ultra-dex validate' for details"
264
+ echo "🔓 To bypass: git commit --no-verify"
265
+ echo ""
266
+ exit 1
267
+ fi
93
268
 
94
- console.log(chalk.bold('What this does:\n'));
95
- console.log(chalk.gray(' • Runs "ultra-dex validate" before each commit'));
96
- console.log(chalk.gray(' • Blocks commits if required files are missing'));
97
- console.log(chalk.gray(' • Warns about incomplete sections\n'));
269
+ # Success
270
+ echo ""
271
+ echo "✅ Ultra-Dex validation passed!"
272
+ echo " Score: \${SCORE}% (minimum: $MIN_ALIGNMENT_SCORE%)"
273
+ echo ""
98
274
 
99
- console.log(chalk.bold('To bypass (not recommended):\n'));
100
- console.log(chalk.cyan(' git commit --no-verify\n'));
275
+ # Cleanup
276
+ rm -f "$VALIDATION_LOG" "$ALIGN_LOG" 2>/dev/null || true
101
277
 
102
- console.log(chalk.bold('To remove:\n'));
103
- console.log(chalk.cyan(' npx ultra-dex hooks --remove\n'));
104
- });
278
+ exit 0
279
+ `;
105
280
  }