claude-autopm 1.13.1 → 1.13.3
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.
- package/README.md +80 -1
- package/bin/autopm.js +26 -1
- package/bin/commands/mcp.js +17 -13
- package/install/install.js +14 -8
- package/install/post-install-check.js +384 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -199,6 +199,42 @@ autopm config switch github
|
|
|
199
199
|
autopm config validate
|
|
200
200
|
```
|
|
201
201
|
|
|
202
|
+
#### 4.6 Verify Installation & Configuration
|
|
203
|
+
|
|
204
|
+
After installation, verify that everything is properly configured:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# Comprehensive configuration check
|
|
208
|
+
autopm validate
|
|
209
|
+
|
|
210
|
+
# Shows:
|
|
211
|
+
# ✅ Essential Components (.claude directory, config, provider, git)
|
|
212
|
+
# ✅ Optional Components (MCP servers, git hooks, Node.js version)
|
|
213
|
+
# 📋 Next steps for incomplete setup
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Example Output:**
|
|
217
|
+
```
|
|
218
|
+
╔════════════════════════════════════════════════════════════════╗
|
|
219
|
+
║ 🔍 ClaudeAutoPM Configuration Status ║
|
|
220
|
+
╚════════════════════════════════════════════════════════════════╝
|
|
221
|
+
|
|
222
|
+
Essential Components:
|
|
223
|
+
✅ .claude directory - Framework installed
|
|
224
|
+
✅ Configuration file - Provider: github
|
|
225
|
+
✅ Provider setup - GitHub (configured)
|
|
226
|
+
✅ Git repository - Initialized
|
|
227
|
+
|
|
228
|
+
Optional Components:
|
|
229
|
+
✅ MCP servers - 2 active (context7-docs, github-mcp)
|
|
230
|
+
⚠️ Git hooks - Not installed (run: bash scripts/setup-hooks.sh)
|
|
231
|
+
✅ Node.js version - v20.10.0 (compatible)
|
|
232
|
+
|
|
233
|
+
Next Steps:
|
|
234
|
+
1. Install git hooks: bash scripts/setup-hooks.sh
|
|
235
|
+
2. Run MCP configuration check: autopm mcp check
|
|
236
|
+
```
|
|
237
|
+
|
|
202
238
|
#### 4. Ship Your First Feature (90 seconds)
|
|
203
239
|
|
|
204
240
|
##### Option A: Using Templates (Works Everywhere)
|
|
@@ -353,8 +389,9 @@ autopm mcp tree # Dependency tree
|
|
|
353
389
|
|
|
354
390
|
#### **Configuration & Diagnostics**
|
|
355
391
|
```bash
|
|
392
|
+
autopm mcp check # Quick configuration check
|
|
356
393
|
autopm mcp setup # Interactive API key setup
|
|
357
|
-
autopm mcp diagnose # Run diagnostics
|
|
394
|
+
autopm mcp diagnose # Run full diagnostics
|
|
358
395
|
autopm mcp test <server> # Test server connection
|
|
359
396
|
autopm mcp status # Show servers status
|
|
360
397
|
```
|
|
@@ -461,6 +498,48 @@ autopm pm:prd-parse user-authentication --overwrite
|
|
|
461
498
|
autopm pm:epic-close user-auth "All authentication features complete"
|
|
462
499
|
```
|
|
463
500
|
|
|
501
|
+
##### **Splitting Large PRDs into Multiple Epics**
|
|
502
|
+
|
|
503
|
+
For complex features, you can split a single PRD into multiple focused epics:
|
|
504
|
+
|
|
505
|
+
```bash
|
|
506
|
+
# 1. Create a comprehensive PRD
|
|
507
|
+
autopm pm:prd-new payment-system --template
|
|
508
|
+
|
|
509
|
+
# 2. Split into focused epics using AI analysis
|
|
510
|
+
/pm:prd-split payment-system
|
|
511
|
+
|
|
512
|
+
# This creates multiple epics from one PRD:
|
|
513
|
+
# ├─ payment-system-backend (API, database, payment gateway integration)
|
|
514
|
+
# ├─ payment-system-frontend (UI components, checkout flow)
|
|
515
|
+
# └─ payment-system-security (PCI compliance, encryption, audit logging)
|
|
516
|
+
|
|
517
|
+
# 3. Work on each epic independently
|
|
518
|
+
/pm:epic-decompose payment-system-backend
|
|
519
|
+
/pm:epic-sync payment-system-backend
|
|
520
|
+
|
|
521
|
+
# 4. Track overall PRD progress
|
|
522
|
+
autopm pm:prd-status payment-system
|
|
523
|
+
# Shows:
|
|
524
|
+
# Epic: payment-system-backend [████████░░] 80% (8/10 tasks)
|
|
525
|
+
# Epic: payment-system-frontend [████░░░░░░] 40% (4/10 tasks)
|
|
526
|
+
# Epic: payment-system-security [░░░░░░░░░░] 0% (0/8 tasks)
|
|
527
|
+
# Overall: 44% complete (12/28 tasks)
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
**When to split PRDs:**
|
|
531
|
+
- ✅ Feature requires multiple specialized teams (frontend, backend, DevOps)
|
|
532
|
+
- ✅ Different components have separate deployment timelines
|
|
533
|
+
- ✅ Epic would exceed 15-20 tasks (becomes hard to manage)
|
|
534
|
+
- ✅ Clear architectural boundaries exist (UI, API, infrastructure)
|
|
535
|
+
|
|
536
|
+
**Best practices:**
|
|
537
|
+
- 📝 Keep original PRD as the source of truth
|
|
538
|
+
- 🏷️ Use consistent naming: `<prd-name>-<component>`
|
|
539
|
+
- 🔗 Link epics back to parent PRD in description
|
|
540
|
+
- 📊 Track overall progress across all child epics
|
|
541
|
+
- 🎯 Each epic should be independently deployable when possible
|
|
542
|
+
|
|
464
543
|
#### **Issue Lifecycle**
|
|
465
544
|
```bash
|
|
466
545
|
# Start working on an issue
|
package/bin/autopm.js
CHANGED
|
@@ -180,6 +180,29 @@ function main() {
|
|
|
180
180
|
.command(require('./commands/config'))
|
|
181
181
|
// MCP management command
|
|
182
182
|
.command(require('./commands/mcp'))
|
|
183
|
+
// Validation command
|
|
184
|
+
.command('validate', 'Validate ClaudeAutoPM configuration and setup',
|
|
185
|
+
(yargs) => {
|
|
186
|
+
return yargs
|
|
187
|
+
.example('autopm validate', 'Check all configuration requirements')
|
|
188
|
+
.example('autopm validate --verbose', 'Show detailed validation info');
|
|
189
|
+
},
|
|
190
|
+
async (argv) => {
|
|
191
|
+
const PostInstallChecker = require('../install/post-install-check.js');
|
|
192
|
+
const checker = new PostInstallChecker();
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
await checker.runAllChecks();
|
|
196
|
+
process.exit(0);
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.error(`❌ Validation error: ${error.message}`);
|
|
199
|
+
if (argv.debug) {
|
|
200
|
+
console.error(error.stack);
|
|
201
|
+
}
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
)
|
|
183
206
|
// Global options
|
|
184
207
|
.option('verbose', {
|
|
185
208
|
type: 'boolean',
|
|
@@ -203,6 +226,7 @@ function main() {
|
|
|
203
226
|
.epilogue(`
|
|
204
227
|
📖 Quick Start:
|
|
205
228
|
autopm install # Install ClaudeAutoPM in current directory
|
|
229
|
+
autopm validate # Check configuration status
|
|
206
230
|
autopm update # Update to latest framework version
|
|
207
231
|
autopm team load frontend # Load React/UI development agents
|
|
208
232
|
claude --dangerously-skip-permissions . # Open Claude Code
|
|
@@ -392,7 +416,8 @@ function main() {
|
|
|
392
416
|
→ Updates epic progress tracking
|
|
393
417
|
|
|
394
418
|
🛠️ Troubleshooting:
|
|
395
|
-
# Check installation
|
|
419
|
+
# Check installation and configuration
|
|
420
|
+
autopm validate # Comprehensive status check
|
|
396
421
|
ls -la .claude/ # Should show: agents/, commands/, config.json
|
|
397
422
|
|
|
398
423
|
# Verify configuration
|
package/bin/commands/mcp.js
CHANGED
|
@@ -7,7 +7,7 @@ const path = require('path');
|
|
|
7
7
|
const MCPHandler = require('../../scripts/mcp-handler.js');
|
|
8
8
|
|
|
9
9
|
module.exports = {
|
|
10
|
-
command: 'mcp <action> [
|
|
10
|
+
command: 'mcp <action> [name]',
|
|
11
11
|
describe: 'Manage MCP (Model Context Protocol) servers and configuration',
|
|
12
12
|
|
|
13
13
|
builder: (yargs) => {
|
|
@@ -20,6 +20,10 @@ module.exports = {
|
|
|
20
20
|
'agents', 'agent', 'usage', 'setup', 'check', 'diagnose', 'test', 'tree', 'status'
|
|
21
21
|
]
|
|
22
22
|
})
|
|
23
|
+
.positional('name', {
|
|
24
|
+
describe: 'Server or agent name (for actions that require it)',
|
|
25
|
+
type: 'string'
|
|
26
|
+
})
|
|
23
27
|
.option('server', {
|
|
24
28
|
alias: 's',
|
|
25
29
|
describe: 'Server name',
|
|
@@ -64,27 +68,27 @@ module.exports = {
|
|
|
64
68
|
break;
|
|
65
69
|
|
|
66
70
|
case 'remove':
|
|
67
|
-
if (!argv.
|
|
71
|
+
if (!argv.name && !argv.server) {
|
|
68
72
|
console.error('❌ Please specify a server name: autopm mcp remove <server-name>');
|
|
69
73
|
process.exit(1);
|
|
70
74
|
}
|
|
71
|
-
handler.remove(argv.
|
|
75
|
+
handler.remove(argv.name || argv.server);
|
|
72
76
|
break;
|
|
73
77
|
|
|
74
78
|
case 'enable':
|
|
75
|
-
if (!argv.
|
|
79
|
+
if (!argv.name && !argv.server) {
|
|
76
80
|
console.error('❌ Please specify a server name: autopm mcp enable <server-name>');
|
|
77
81
|
process.exit(1);
|
|
78
82
|
}
|
|
79
|
-
handler.enable(argv.
|
|
83
|
+
handler.enable(argv.name || argv.server);
|
|
80
84
|
break;
|
|
81
85
|
|
|
82
86
|
case 'disable':
|
|
83
|
-
if (!argv.
|
|
87
|
+
if (!argv.name && !argv.server) {
|
|
84
88
|
console.error('❌ Please specify a server name: autopm mcp disable <server-name>');
|
|
85
89
|
process.exit(1);
|
|
86
90
|
}
|
|
87
|
-
handler.disable(argv.
|
|
91
|
+
handler.disable(argv.name || argv.server);
|
|
88
92
|
break;
|
|
89
93
|
|
|
90
94
|
case 'sync':
|
|
@@ -96,11 +100,11 @@ module.exports = {
|
|
|
96
100
|
break;
|
|
97
101
|
|
|
98
102
|
case 'info':
|
|
99
|
-
if (!argv.
|
|
103
|
+
if (!argv.name && !argv.server) {
|
|
100
104
|
console.error('❌ Please specify a server name: autopm mcp info <server-name>');
|
|
101
105
|
process.exit(1);
|
|
102
106
|
}
|
|
103
|
-
handler.info(argv.
|
|
107
|
+
handler.info(argv.name || argv.server);
|
|
104
108
|
break;
|
|
105
109
|
|
|
106
110
|
// Agent analysis commands
|
|
@@ -109,11 +113,11 @@ module.exports = {
|
|
|
109
113
|
break;
|
|
110
114
|
|
|
111
115
|
case 'agent':
|
|
112
|
-
if (!argv.
|
|
116
|
+
if (!argv.name && !argv.agent) {
|
|
113
117
|
console.error('❌ Please specify an agent name: autopm mcp agent <agent-name>');
|
|
114
118
|
process.exit(1);
|
|
115
119
|
}
|
|
116
|
-
handler.mcpAgent(argv.
|
|
120
|
+
handler.mcpAgent(argv.name || argv.agent);
|
|
117
121
|
break;
|
|
118
122
|
|
|
119
123
|
case 'usage':
|
|
@@ -134,11 +138,11 @@ module.exports = {
|
|
|
134
138
|
break;
|
|
135
139
|
|
|
136
140
|
case 'test':
|
|
137
|
-
if (!argv.
|
|
141
|
+
if (!argv.name && !argv.server) {
|
|
138
142
|
console.error('❌ Please specify a server name: autopm mcp test <server-name>');
|
|
139
143
|
process.exit(1);
|
|
140
144
|
}
|
|
141
|
-
const result = await handler.testServer(argv.
|
|
145
|
+
const result = await handler.testServer(argv.name || argv.server);
|
|
142
146
|
if (result.success) {
|
|
143
147
|
console.log(`✅ ${result.message}`);
|
|
144
148
|
} else {
|
package/install/install.js
CHANGED
|
@@ -797,6 +797,18 @@ See: https://github.com/rafeekpro/ClaudeAutoPM
|
|
|
797
797
|
}
|
|
798
798
|
}
|
|
799
799
|
|
|
800
|
+
async runPostInstallCheck() {
|
|
801
|
+
const PostInstallChecker = require('./post-install-check.js');
|
|
802
|
+
const checker = new PostInstallChecker();
|
|
803
|
+
|
|
804
|
+
try {
|
|
805
|
+
await checker.runAllChecks();
|
|
806
|
+
} catch (error) {
|
|
807
|
+
this.printWarning(`Configuration check failed: ${error.message}`);
|
|
808
|
+
console.log('You can run the check later with: autopm config validate\n');
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
800
812
|
async run() {
|
|
801
813
|
// Handle help and version
|
|
802
814
|
if (this.options.help) {
|
|
@@ -852,14 +864,8 @@ See: https://github.com/rafeekpro/ClaudeAutoPM
|
|
|
852
864
|
this.printMsg('GREEN', '╚══════════════════════════════════════════╝');
|
|
853
865
|
console.log('');
|
|
854
866
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
this.printStep('Next steps:');
|
|
858
|
-
console.log(' 1. Review CLAUDE.md for project configuration');
|
|
859
|
-
console.log(' 2. Run: ./scripts/setup-hooks.sh to setup git hooks');
|
|
860
|
-
console.log(' 3. Open Claude Code in this directory');
|
|
861
|
-
console.log(' 4. In Claude, run: /pm:validate');
|
|
862
|
-
console.log('');
|
|
867
|
+
// Run post-installation configuration check
|
|
868
|
+
await this.runPostInstallCheck();
|
|
863
869
|
|
|
864
870
|
process.exit(0);
|
|
865
871
|
}
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Post-Installation Configuration Checker
|
|
5
|
+
* Validates that all required components are properly configured
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { execSync } = require('child_process');
|
|
11
|
+
|
|
12
|
+
class PostInstallChecker {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.projectRoot = process.cwd();
|
|
15
|
+
this.results = {
|
|
16
|
+
essential: [],
|
|
17
|
+
optional: [],
|
|
18
|
+
nextSteps: []
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Run all configuration checks
|
|
24
|
+
*/
|
|
25
|
+
async runAllChecks() {
|
|
26
|
+
console.log('\n╔════════════════════════════════════════════════════════════════╗');
|
|
27
|
+
console.log('║ 🔍 ClaudeAutoPM Configuration Status ║');
|
|
28
|
+
console.log('╚════════════════════════════════════════════════════════════════╝\n');
|
|
29
|
+
|
|
30
|
+
// Essential checks
|
|
31
|
+
this.checkClaudeDirectory();
|
|
32
|
+
this.checkConfigFile();
|
|
33
|
+
this.checkProvider();
|
|
34
|
+
this.checkGitRepository();
|
|
35
|
+
|
|
36
|
+
// Optional but recommended
|
|
37
|
+
this.checkMCPConfiguration();
|
|
38
|
+
this.checkGitHooks();
|
|
39
|
+
this.checkNodeVersion();
|
|
40
|
+
|
|
41
|
+
// Display results
|
|
42
|
+
this.displayResults();
|
|
43
|
+
this.displayNextSteps();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Check if .claude directory exists
|
|
48
|
+
*/
|
|
49
|
+
checkClaudeDirectory() {
|
|
50
|
+
const claudeDir = path.join(this.projectRoot, '.claude');
|
|
51
|
+
const exists = fs.existsSync(claudeDir);
|
|
52
|
+
|
|
53
|
+
this.results.essential.push({
|
|
54
|
+
name: '.claude directory',
|
|
55
|
+
status: exists,
|
|
56
|
+
message: exists
|
|
57
|
+
? 'Framework installed'
|
|
58
|
+
: 'Not found - run: autopm install'
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (exists) {
|
|
62
|
+
// Check subdirectories
|
|
63
|
+
const subdirs = ['agents', 'commands', 'rules', 'scripts'];
|
|
64
|
+
subdirs.forEach(dir => {
|
|
65
|
+
const dirPath = path.join(claudeDir, dir);
|
|
66
|
+
const dirExists = fs.existsSync(dirPath);
|
|
67
|
+
this.results.optional.push({
|
|
68
|
+
name: ` └─ ${dir}/`,
|
|
69
|
+
status: dirExists,
|
|
70
|
+
message: dirExists ? 'Present' : 'Missing'
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Check configuration file
|
|
78
|
+
*/
|
|
79
|
+
checkConfigFile() {
|
|
80
|
+
const configPath = path.join(this.projectRoot, '.claude', 'config.json');
|
|
81
|
+
let config = null;
|
|
82
|
+
|
|
83
|
+
if (fs.existsSync(configPath)) {
|
|
84
|
+
try {
|
|
85
|
+
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
86
|
+
this.results.essential.push({
|
|
87
|
+
name: 'Configuration file',
|
|
88
|
+
status: true,
|
|
89
|
+
message: `Provider: ${config.provider || 'not set'}`
|
|
90
|
+
});
|
|
91
|
+
this.config = config;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
this.results.essential.push({
|
|
94
|
+
name: 'Configuration file',
|
|
95
|
+
status: false,
|
|
96
|
+
message: 'Invalid JSON format'
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
this.results.essential.push({
|
|
101
|
+
name: 'Configuration file',
|
|
102
|
+
status: false,
|
|
103
|
+
message: 'Not found'
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Check provider configuration (GitHub or Azure DevOps)
|
|
110
|
+
*/
|
|
111
|
+
checkProvider() {
|
|
112
|
+
if (!this.config) {
|
|
113
|
+
this.results.essential.push({
|
|
114
|
+
name: 'Provider setup',
|
|
115
|
+
status: false,
|
|
116
|
+
message: 'No configuration file'
|
|
117
|
+
});
|
|
118
|
+
this.results.nextSteps.push('Run: autopm config set provider github|azure');
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const provider = this.config.provider;
|
|
123
|
+
|
|
124
|
+
if (!provider) {
|
|
125
|
+
this.results.essential.push({
|
|
126
|
+
name: 'Provider setup',
|
|
127
|
+
status: false,
|
|
128
|
+
message: 'Provider not configured'
|
|
129
|
+
});
|
|
130
|
+
this.results.nextSteps.push('Run: autopm config set provider github|azure');
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Check GitHub configuration
|
|
135
|
+
if (provider === 'github') {
|
|
136
|
+
const hasToken = !!process.env.GITHUB_TOKEN;
|
|
137
|
+
const hasOwner = !!this.config.github?.owner;
|
|
138
|
+
const hasRepo = !!this.config.github?.repo;
|
|
139
|
+
|
|
140
|
+
this.results.essential.push({
|
|
141
|
+
name: 'GitHub Provider',
|
|
142
|
+
status: hasToken && hasOwner && hasRepo,
|
|
143
|
+
message: this.getGitHubStatus(hasToken, hasOwner, hasRepo)
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
if (!hasToken) {
|
|
147
|
+
this.results.nextSteps.push('Set GITHUB_TOKEN environment variable');
|
|
148
|
+
}
|
|
149
|
+
if (!hasOwner || !hasRepo) {
|
|
150
|
+
this.results.nextSteps.push('Run: autopm config set github.owner <username>');
|
|
151
|
+
this.results.nextSteps.push('Run: autopm config set github.repo <repository>');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Check Azure DevOps configuration
|
|
156
|
+
if (provider === 'azure') {
|
|
157
|
+
const hasToken = !!process.env.AZURE_DEVOPS_PAT;
|
|
158
|
+
const hasOrg = !!this.config.azure?.organization;
|
|
159
|
+
const hasProject = !!this.config.azure?.project;
|
|
160
|
+
|
|
161
|
+
this.results.essential.push({
|
|
162
|
+
name: 'Azure DevOps Provider',
|
|
163
|
+
status: hasToken && hasOrg && hasProject,
|
|
164
|
+
message: this.getAzureStatus(hasToken, hasOrg, hasProject)
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
if (!hasToken) {
|
|
168
|
+
this.results.nextSteps.push('Set AZURE_DEVOPS_PAT environment variable');
|
|
169
|
+
}
|
|
170
|
+
if (!hasOrg || !hasProject) {
|
|
171
|
+
this.results.nextSteps.push('Run: autopm config set azure.organization <org>');
|
|
172
|
+
this.results.nextSteps.push('Run: autopm config set azure.project <project>');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Get GitHub configuration status message
|
|
179
|
+
*/
|
|
180
|
+
getGitHubStatus(hasToken, hasOwner, hasRepo) {
|
|
181
|
+
if (hasToken && hasOwner && hasRepo) {
|
|
182
|
+
return `Configured: ${this.config.github.owner}/${this.config.github.repo}`;
|
|
183
|
+
}
|
|
184
|
+
const missing = [];
|
|
185
|
+
if (!hasToken) missing.push('token');
|
|
186
|
+
if (!hasOwner) missing.push('owner');
|
|
187
|
+
if (!hasRepo) missing.push('repo');
|
|
188
|
+
return `Missing: ${missing.join(', ')}`;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Get Azure DevOps configuration status message
|
|
193
|
+
*/
|
|
194
|
+
getAzureStatus(hasToken, hasOrg, hasProject) {
|
|
195
|
+
if (hasToken && hasOrg && hasProject) {
|
|
196
|
+
return `Configured: ${this.config.azure.organization}/${this.config.azure.project}`;
|
|
197
|
+
}
|
|
198
|
+
const missing = [];
|
|
199
|
+
if (!hasToken) missing.push('PAT');
|
|
200
|
+
if (!hasOrg) missing.push('organization');
|
|
201
|
+
if (!hasProject) missing.push('project');
|
|
202
|
+
return `Missing: ${missing.join(', ')}`;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Check MCP server configuration
|
|
207
|
+
*/
|
|
208
|
+
checkMCPConfiguration() {
|
|
209
|
+
const mcpServersPath = path.join(this.projectRoot, '.claude', 'mcp-servers.json');
|
|
210
|
+
const envPath = path.join(this.projectRoot, '.claude', '.env');
|
|
211
|
+
|
|
212
|
+
let mcpConfigured = false;
|
|
213
|
+
let message = 'Not configured';
|
|
214
|
+
|
|
215
|
+
if (fs.existsSync(mcpServersPath)) {
|
|
216
|
+
try {
|
|
217
|
+
const mcpConfig = JSON.parse(fs.readFileSync(mcpServersPath, 'utf8'));
|
|
218
|
+
const serverCount = Object.keys(mcpConfig.mcpServers || {}).length;
|
|
219
|
+
|
|
220
|
+
if (serverCount > 0) {
|
|
221
|
+
mcpConfigured = true;
|
|
222
|
+
message = `${serverCount} server(s) configured`;
|
|
223
|
+
} else {
|
|
224
|
+
message = 'No servers enabled';
|
|
225
|
+
}
|
|
226
|
+
} catch (error) {
|
|
227
|
+
message = 'Invalid configuration';
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
this.results.optional.push({
|
|
232
|
+
name: 'MCP Servers',
|
|
233
|
+
status: mcpConfigured,
|
|
234
|
+
message: message
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const hasEnv = fs.existsSync(envPath);
|
|
238
|
+
this.results.optional.push({
|
|
239
|
+
name: 'MCP Environment',
|
|
240
|
+
status: hasEnv,
|
|
241
|
+
message: hasEnv ? 'Environment file exists' : 'No .env file'
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
if (!mcpConfigured) {
|
|
245
|
+
this.results.nextSteps.push('Run: autopm mcp check (to see MCP requirements)');
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Check Git repository
|
|
251
|
+
*/
|
|
252
|
+
checkGitRepository() {
|
|
253
|
+
try {
|
|
254
|
+
execSync('git rev-parse --is-inside-work-tree', {
|
|
255
|
+
stdio: 'pipe',
|
|
256
|
+
cwd: this.projectRoot
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
this.results.essential.push({
|
|
260
|
+
name: 'Git repository',
|
|
261
|
+
status: true,
|
|
262
|
+
message: 'Initialized'
|
|
263
|
+
});
|
|
264
|
+
} catch (error) {
|
|
265
|
+
this.results.essential.push({
|
|
266
|
+
name: 'Git repository',
|
|
267
|
+
status: false,
|
|
268
|
+
message: 'Not initialized'
|
|
269
|
+
});
|
|
270
|
+
this.results.nextSteps.push('Run: git init');
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Check Git hooks installation
|
|
276
|
+
*/
|
|
277
|
+
checkGitHooks() {
|
|
278
|
+
const hooksDir = path.join(this.projectRoot, '.git', 'hooks');
|
|
279
|
+
const preCommit = path.join(hooksDir, 'pre-commit');
|
|
280
|
+
const prePush = path.join(hooksDir, 'pre-push');
|
|
281
|
+
|
|
282
|
+
const hasPreCommit = fs.existsSync(preCommit);
|
|
283
|
+
const hasPrePush = fs.existsSync(prePush);
|
|
284
|
+
|
|
285
|
+
this.results.optional.push({
|
|
286
|
+
name: 'Git hooks',
|
|
287
|
+
status: hasPreCommit || hasPrePush,
|
|
288
|
+
message: hasPreCommit && hasPrePush
|
|
289
|
+
? 'Installed'
|
|
290
|
+
: hasPreCommit || hasPrePush
|
|
291
|
+
? 'Partially installed'
|
|
292
|
+
: 'Not installed'
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Check Node.js version
|
|
298
|
+
*/
|
|
299
|
+
checkNodeVersion() {
|
|
300
|
+
const version = process.version;
|
|
301
|
+
const major = parseInt(version.split('.')[0].substring(1));
|
|
302
|
+
const isSupported = major >= 18;
|
|
303
|
+
|
|
304
|
+
this.results.optional.push({
|
|
305
|
+
name: 'Node.js version',
|
|
306
|
+
status: isSupported,
|
|
307
|
+
message: isSupported
|
|
308
|
+
? `${version} (supported)`
|
|
309
|
+
: `${version} (upgrade recommended)`
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
if (!isSupported) {
|
|
313
|
+
this.results.nextSteps.push('Upgrade Node.js to v18 or higher');
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Display check results
|
|
319
|
+
*/
|
|
320
|
+
displayResults() {
|
|
321
|
+
console.log('📋 Essential Components:\n');
|
|
322
|
+
|
|
323
|
+
this.results.essential.forEach(check => {
|
|
324
|
+
const icon = check.status ? '✅' : '❌';
|
|
325
|
+
const status = check.status ? 'OK' : 'MISSING';
|
|
326
|
+
console.log(`${icon} ${check.name.padEnd(25)} ${status.padEnd(10)} ${check.message}`);
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
if (this.results.optional.length > 0) {
|
|
330
|
+
console.log('\n🔧 Optional Components:\n');
|
|
331
|
+
|
|
332
|
+
this.results.optional.forEach(check => {
|
|
333
|
+
const icon = check.status ? '✅' : '⚪';
|
|
334
|
+
console.log(`${icon} ${check.name.padEnd(25)} ${check.message}`);
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
console.log('\n' + '─'.repeat(70) + '\n');
|
|
339
|
+
|
|
340
|
+
// Overall status
|
|
341
|
+
const essentialPassed = this.results.essential.every(c => c.status);
|
|
342
|
+
|
|
343
|
+
if (essentialPassed) {
|
|
344
|
+
console.log('✅ All essential components are configured!\n');
|
|
345
|
+
} else {
|
|
346
|
+
console.log('⚠️ Some essential components need configuration\n');
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Display next steps
|
|
352
|
+
*/
|
|
353
|
+
displayNextSteps() {
|
|
354
|
+
if (this.results.nextSteps.length === 0) {
|
|
355
|
+
console.log('🚀 Ready to start! Try:\n');
|
|
356
|
+
console.log(' claude --dangerously-skip-permissions .');
|
|
357
|
+
console.log(' /pm:validate\n');
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
console.log('📝 Next Steps:\n');
|
|
362
|
+
|
|
363
|
+
this.results.nextSteps.forEach((step, index) => {
|
|
364
|
+
console.log(` ${index + 1}. ${step}`);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
console.log('\n💡 Quick Setup:\n');
|
|
368
|
+
console.log(' autopm config show # View current configuration');
|
|
369
|
+
console.log(' autopm config validate # Validate settings');
|
|
370
|
+
console.log(' autopm mcp check # Check MCP requirements');
|
|
371
|
+
console.log(' autopm --help # See all commands\n');
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Run if executed directly
|
|
376
|
+
if (require.main === module) {
|
|
377
|
+
const checker = new PostInstallChecker();
|
|
378
|
+
checker.runAllChecks().catch(error => {
|
|
379
|
+
console.error('Error during configuration check:', error.message);
|
|
380
|
+
process.exit(1);
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
module.exports = PostInstallChecker;
|