claude-context 1.2.4
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 +121 -0
- package/bin/claude-context.js +144 -0
- package/lib/diagnose.js +337 -0
- package/lib/generate.js +302 -0
- package/lib/hooks.js +150 -0
- package/lib/index.js +17 -0
- package/lib/sync.js +263 -0
- package/lib/validate.js +292 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# claude-context
|
|
2
|
+
|
|
3
|
+
CLI tools for managing Claude Context Engineering in your project.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Use directly with npx (recommended)
|
|
9
|
+
npx claude-context validate --all
|
|
10
|
+
|
|
11
|
+
# Or install globally
|
|
12
|
+
npm install -g claude-context
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
Run `npx create-claude-context` first to initialize context engineering in your project.
|
|
18
|
+
|
|
19
|
+
## Commands
|
|
20
|
+
|
|
21
|
+
### Validate
|
|
22
|
+
|
|
23
|
+
Validate your context engineering setup:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Run all validations
|
|
27
|
+
npx claude-context validate --all
|
|
28
|
+
|
|
29
|
+
# Specific validations
|
|
30
|
+
npx claude-context validate --schema # JSON schema validation
|
|
31
|
+
npx claude-context validate --links # Internal link validation
|
|
32
|
+
npx claude-context validate --placeholders # Check for unreplaced {{PLACEHOLDERS}}
|
|
33
|
+
npx claude-context validate --structure # Directory structure validation
|
|
34
|
+
npx claude-context validate --lines # Line number accuracy check
|
|
35
|
+
|
|
36
|
+
# With options
|
|
37
|
+
npx claude-context validate --all --verbose
|
|
38
|
+
npx claude-context validate --lines --threshold 70
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Sync
|
|
42
|
+
|
|
43
|
+
Synchronize documentation with code changes:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# Check for drift
|
|
47
|
+
npx claude-context sync --check
|
|
48
|
+
|
|
49
|
+
# Auto-fix line number drift
|
|
50
|
+
npx claude-context sync --fix
|
|
51
|
+
|
|
52
|
+
# Rebuild CODE_TO_WORKFLOW_MAP
|
|
53
|
+
npx claude-context sync --rebuild-map
|
|
54
|
+
|
|
55
|
+
# Strict mode (fail on any drift)
|
|
56
|
+
npx claude-context sync --check --strict
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Hooks
|
|
60
|
+
|
|
61
|
+
Manage git hooks for automatic validation:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Install pre-commit and post-commit hooks
|
|
65
|
+
npx claude-context hooks install
|
|
66
|
+
|
|
67
|
+
# Uninstall hooks
|
|
68
|
+
npx claude-context hooks uninstall
|
|
69
|
+
|
|
70
|
+
# Install only pre-commit
|
|
71
|
+
npx claude-context hooks install --pre-commit
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Diagnose
|
|
75
|
+
|
|
76
|
+
Run diagnostics on your setup:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Run diagnostics
|
|
80
|
+
npx claude-context diagnose
|
|
81
|
+
|
|
82
|
+
# Auto-fix detected issues
|
|
83
|
+
npx claude-context diagnose --fix
|
|
84
|
+
|
|
85
|
+
# Verbose output
|
|
86
|
+
npx claude-context diagnose --verbose
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Generate
|
|
90
|
+
|
|
91
|
+
Generate or regenerate documentation:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Regenerate CODE_TO_WORKFLOW_MAP.md
|
|
95
|
+
npx claude-context generate --code-map
|
|
96
|
+
|
|
97
|
+
# Rebuild all indexes
|
|
98
|
+
npx claude-context generate --indexes
|
|
99
|
+
|
|
100
|
+
# Regenerate semantic anchors
|
|
101
|
+
npx claude-context generate --anchors
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## CI/CD Integration
|
|
105
|
+
|
|
106
|
+
Add to your CI pipeline:
|
|
107
|
+
|
|
108
|
+
```yaml
|
|
109
|
+
# GitHub Actions example
|
|
110
|
+
- name: Validate context engineering
|
|
111
|
+
run: npx claude-context validate --all --strict
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Related
|
|
115
|
+
|
|
116
|
+
- [create-claude-context](https://www.npmjs.com/package/create-claude-context) - Initial setup
|
|
117
|
+
- [claude-context-plugin](https://www.npmjs.com/package/claude-context-plugin) - Claude Code plugin
|
|
118
|
+
|
|
119
|
+
## License
|
|
120
|
+
|
|
121
|
+
MIT
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Claude Context CLI
|
|
5
|
+
*
|
|
6
|
+
* Ongoing tools for managing Claude Context Engineering in your project.
|
|
7
|
+
* Use after initial setup with `npx create-claude-context`.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { program } = require('commander');
|
|
11
|
+
const chalk = require('chalk');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
|
|
15
|
+
const { validate } = require('../lib/validate');
|
|
16
|
+
const { sync } = require('../lib/sync');
|
|
17
|
+
const { hooks } = require('../lib/hooks');
|
|
18
|
+
const { diagnose } = require('../lib/diagnose');
|
|
19
|
+
const { generate } = require('../lib/generate');
|
|
20
|
+
|
|
21
|
+
const packageJson = require('../package.json');
|
|
22
|
+
|
|
23
|
+
// Check if we're in a project with .claude directory
|
|
24
|
+
function checkClaudeDir() {
|
|
25
|
+
const claudeDir = path.join(process.cwd(), '.claude');
|
|
26
|
+
if (!fs.existsSync(claudeDir)) {
|
|
27
|
+
console.error(chalk.red('\nError: No .claude directory found in current directory.'));
|
|
28
|
+
console.error(chalk.yellow('Run `npx create-claude-context` first to initialize.\n'));
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
return claudeDir;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
program
|
|
35
|
+
.name('claude-context')
|
|
36
|
+
.description('CLI tools for Claude Context Engineering')
|
|
37
|
+
.version(packageJson.version);
|
|
38
|
+
|
|
39
|
+
// Validate command
|
|
40
|
+
program
|
|
41
|
+
.command('validate')
|
|
42
|
+
.description('Validate context engineering setup')
|
|
43
|
+
.option('-a, --all', 'Run all validations')
|
|
44
|
+
.option('-s, --schema', 'Validate JSON schemas')
|
|
45
|
+
.option('-l, --links', 'Validate internal links')
|
|
46
|
+
.option('-p, --placeholders', 'Check for unreplaced placeholders')
|
|
47
|
+
.option('-S, --structure', 'Validate directory structure')
|
|
48
|
+
.option('-L, --lines', 'Check line number accuracy')
|
|
49
|
+
.option('-t, --threshold <number>', 'Line accuracy threshold (default: 60)', '60')
|
|
50
|
+
.option('-v, --verbose', 'Show detailed output')
|
|
51
|
+
.action(async (options) => {
|
|
52
|
+
checkClaudeDir();
|
|
53
|
+
try {
|
|
54
|
+
const result = await validate(process.cwd(), options);
|
|
55
|
+
process.exit(result.success ? 0 : 1);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Sync command
|
|
63
|
+
program
|
|
64
|
+
.command('sync')
|
|
65
|
+
.description('Synchronize documentation with code')
|
|
66
|
+
.option('-c, --check', 'Check for drift without fixing')
|
|
67
|
+
.option('-f, --fix', 'Auto-fix shifted line numbers')
|
|
68
|
+
.option('--rebuild-map', 'Regenerate CODE_TO_WORKFLOW_MAP')
|
|
69
|
+
.option('--strict', 'Fail on any drift detected')
|
|
70
|
+
.action(async (options) => {
|
|
71
|
+
checkClaudeDir();
|
|
72
|
+
try {
|
|
73
|
+
const result = await sync(process.cwd(), options);
|
|
74
|
+
process.exit(result.success ? 0 : 1);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Hooks command
|
|
82
|
+
program
|
|
83
|
+
.command('hooks')
|
|
84
|
+
.description('Manage git hooks for context engineering')
|
|
85
|
+
.argument('<action>', 'install or uninstall')
|
|
86
|
+
.option('--pre-commit', 'Only pre-commit hook')
|
|
87
|
+
.option('--post-commit', 'Only post-commit hook')
|
|
88
|
+
.action(async (action, options) => {
|
|
89
|
+
checkClaudeDir();
|
|
90
|
+
if (!['install', 'uninstall'].includes(action)) {
|
|
91
|
+
console.error(chalk.red(`Unknown action: ${action}. Use 'install' or 'uninstall'.`));
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const result = await hooks(process.cwd(), action, options);
|
|
96
|
+
process.exit(result.success ? 0 : 1);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// Diagnose command
|
|
104
|
+
program
|
|
105
|
+
.command('diagnose')
|
|
106
|
+
.description('Run diagnostics on context engineering setup')
|
|
107
|
+
.option('-f, --fix', 'Auto-fix detected issues')
|
|
108
|
+
.option('-v, --verbose', 'Show detailed output')
|
|
109
|
+
.action(async (options) => {
|
|
110
|
+
checkClaudeDir();
|
|
111
|
+
try {
|
|
112
|
+
const result = await diagnose(process.cwd(), options);
|
|
113
|
+
process.exit(result.success ? 0 : 1);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// Generate command
|
|
121
|
+
program
|
|
122
|
+
.command('generate')
|
|
123
|
+
.description('Generate or regenerate documentation')
|
|
124
|
+
.option('--code-map', 'Regenerate CODE_TO_WORKFLOW_MAP.md')
|
|
125
|
+
.option('--indexes', 'Rebuild all indexes')
|
|
126
|
+
.option('--anchors', 'Regenerate semantic anchors')
|
|
127
|
+
.action(async (options) => {
|
|
128
|
+
checkClaudeDir();
|
|
129
|
+
try {
|
|
130
|
+
const result = await generate(process.cwd(), options);
|
|
131
|
+
process.exit(result.success ? 0 : 1);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error(chalk.red(`Error: ${error.message}`));
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// Parse and run
|
|
139
|
+
program.parse();
|
|
140
|
+
|
|
141
|
+
// Show help if no command provided
|
|
142
|
+
if (!process.argv.slice(2).length) {
|
|
143
|
+
program.outputHelp();
|
|
144
|
+
}
|
package/lib/diagnose.js
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagnostics module for Claude Context Engineering
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const { glob } = require('glob');
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Run diagnostics on context engineering setup
|
|
12
|
+
*/
|
|
13
|
+
async function diagnose(projectRoot, options = {}) {
|
|
14
|
+
const claudeDir = path.join(projectRoot, '.claude');
|
|
15
|
+
const results = {
|
|
16
|
+
success: true,
|
|
17
|
+
checks: [],
|
|
18
|
+
issues: [],
|
|
19
|
+
fixed: 0
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
console.log(chalk.blue('\n🩺 Running diagnostics...\n'));
|
|
23
|
+
|
|
24
|
+
// Check 1: Directory structure
|
|
25
|
+
const structureCheck = checkStructure(claudeDir);
|
|
26
|
+
results.checks.push(structureCheck);
|
|
27
|
+
results.issues.push(...structureCheck.issues);
|
|
28
|
+
|
|
29
|
+
// Check 2: CLAUDE.md exists and is valid
|
|
30
|
+
const claudeMdCheck = checkClaudeMd(projectRoot);
|
|
31
|
+
results.checks.push(claudeMdCheck);
|
|
32
|
+
results.issues.push(...claudeMdCheck.issues);
|
|
33
|
+
|
|
34
|
+
// Check 3: Settings.json is valid
|
|
35
|
+
const settingsCheck = checkSettings(claudeDir);
|
|
36
|
+
results.checks.push(settingsCheck);
|
|
37
|
+
results.issues.push(...settingsCheck.issues);
|
|
38
|
+
|
|
39
|
+
// Check 4: Agent files are valid
|
|
40
|
+
const agentCheck = await checkAgents(claudeDir);
|
|
41
|
+
results.checks.push(agentCheck);
|
|
42
|
+
results.issues.push(...agentCheck.issues);
|
|
43
|
+
|
|
44
|
+
// Check 5: Command files are valid
|
|
45
|
+
const commandCheck = await checkCommands(claudeDir);
|
|
46
|
+
results.checks.push(commandCheck);
|
|
47
|
+
results.issues.push(...commandCheck.issues);
|
|
48
|
+
|
|
49
|
+
// Check 6: Workflow files exist
|
|
50
|
+
const workflowCheck = await checkWorkflows(claudeDir);
|
|
51
|
+
results.checks.push(workflowCheck);
|
|
52
|
+
results.issues.push(...workflowCheck.issues);
|
|
53
|
+
|
|
54
|
+
// Fix issues if requested
|
|
55
|
+
if (options.fix && results.issues.length > 0) {
|
|
56
|
+
results.fixed = await fixIssues(claudeDir, projectRoot, results.issues);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Determine success
|
|
60
|
+
const criticalIssues = results.issues.filter(i => i.severity === 'error');
|
|
61
|
+
results.success = criticalIssues.length === 0;
|
|
62
|
+
|
|
63
|
+
// Print summary
|
|
64
|
+
printDiagnosticsSummary(results, options);
|
|
65
|
+
|
|
66
|
+
return results;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Check directory structure
|
|
71
|
+
*/
|
|
72
|
+
function checkStructure(claudeDir) {
|
|
73
|
+
const check = { name: 'Directory Structure', passed: true, issues: [] };
|
|
74
|
+
|
|
75
|
+
const requiredDirs = ['agents', 'commands', 'context', 'indexes'];
|
|
76
|
+
|
|
77
|
+
for (const dir of requiredDirs) {
|
|
78
|
+
const dirPath = path.join(claudeDir, dir);
|
|
79
|
+
if (!fs.existsSync(dirPath)) {
|
|
80
|
+
check.passed = false;
|
|
81
|
+
check.issues.push({
|
|
82
|
+
type: 'missing_directory',
|
|
83
|
+
path: dir,
|
|
84
|
+
message: `Missing required directory: ${dir}`,
|
|
85
|
+
severity: 'error',
|
|
86
|
+
fix: () => fs.mkdirSync(dirPath, { recursive: true })
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
console.log(check.passed
|
|
92
|
+
? chalk.green('✓ Directory structure: OK')
|
|
93
|
+
: chalk.red(`✗ Directory structure: ${check.issues.length} issues`));
|
|
94
|
+
|
|
95
|
+
return check;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Check CLAUDE.md
|
|
100
|
+
*/
|
|
101
|
+
function checkClaudeMd(projectRoot) {
|
|
102
|
+
const check = { name: 'CLAUDE.md', passed: true, issues: [] };
|
|
103
|
+
const claudeMdPath = path.join(projectRoot, 'CLAUDE.md');
|
|
104
|
+
|
|
105
|
+
if (!fs.existsSync(claudeMdPath)) {
|
|
106
|
+
check.passed = false;
|
|
107
|
+
check.issues.push({
|
|
108
|
+
type: 'missing_file',
|
|
109
|
+
path: 'CLAUDE.md',
|
|
110
|
+
message: 'Missing CLAUDE.md at project root',
|
|
111
|
+
severity: 'error'
|
|
112
|
+
});
|
|
113
|
+
} else {
|
|
114
|
+
const content = fs.readFileSync(claudeMdPath, 'utf8');
|
|
115
|
+
|
|
116
|
+
// Check for unreplaced placeholders
|
|
117
|
+
const placeholders = content.match(/\{\{[A-Z_]+\}\}/g);
|
|
118
|
+
if (placeholders && placeholders.length > 10) {
|
|
119
|
+
check.passed = false;
|
|
120
|
+
check.issues.push({
|
|
121
|
+
type: 'too_many_placeholders',
|
|
122
|
+
path: 'CLAUDE.md',
|
|
123
|
+
message: `CLAUDE.md has ${placeholders.length} unreplaced placeholders`,
|
|
124
|
+
severity: 'warning'
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Check minimum content
|
|
129
|
+
if (content.length < 500) {
|
|
130
|
+
check.issues.push({
|
|
131
|
+
type: 'minimal_content',
|
|
132
|
+
path: 'CLAUDE.md',
|
|
133
|
+
message: 'CLAUDE.md seems too short',
|
|
134
|
+
severity: 'warning'
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
console.log(check.passed
|
|
140
|
+
? chalk.green('✓ CLAUDE.md: OK')
|
|
141
|
+
: chalk.yellow(`⚠ CLAUDE.md: ${check.issues.length} issues`));
|
|
142
|
+
|
|
143
|
+
return check;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Check settings.json
|
|
148
|
+
*/
|
|
149
|
+
function checkSettings(claudeDir) {
|
|
150
|
+
const check = { name: 'Settings', passed: true, issues: [] };
|
|
151
|
+
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
152
|
+
|
|
153
|
+
if (!fs.existsSync(settingsPath)) {
|
|
154
|
+
check.issues.push({
|
|
155
|
+
type: 'missing_file',
|
|
156
|
+
path: 'settings.json',
|
|
157
|
+
message: 'Missing settings.json',
|
|
158
|
+
severity: 'warning'
|
|
159
|
+
});
|
|
160
|
+
} else {
|
|
161
|
+
try {
|
|
162
|
+
const content = fs.readFileSync(settingsPath, 'utf8');
|
|
163
|
+
JSON.parse(content);
|
|
164
|
+
} catch (e) {
|
|
165
|
+
check.passed = false;
|
|
166
|
+
check.issues.push({
|
|
167
|
+
type: 'invalid_json',
|
|
168
|
+
path: 'settings.json',
|
|
169
|
+
message: `Invalid JSON: ${e.message}`,
|
|
170
|
+
severity: 'error'
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
console.log(check.passed
|
|
176
|
+
? chalk.green('✓ Settings: OK')
|
|
177
|
+
: chalk.red(`✗ Settings: ${check.issues.length} issues`));
|
|
178
|
+
|
|
179
|
+
return check;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Check agent files
|
|
184
|
+
*/
|
|
185
|
+
async function checkAgents(claudeDir) {
|
|
186
|
+
const check = { name: 'Agents', passed: true, issues: [] };
|
|
187
|
+
const agentDir = path.join(claudeDir, 'agents');
|
|
188
|
+
|
|
189
|
+
if (!fs.existsSync(agentDir)) {
|
|
190
|
+
check.issues.push({
|
|
191
|
+
type: 'missing_directory',
|
|
192
|
+
path: 'agents',
|
|
193
|
+
message: 'No agents directory',
|
|
194
|
+
severity: 'warning'
|
|
195
|
+
});
|
|
196
|
+
return check;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const agentFiles = await glob('*.md', { cwd: agentDir });
|
|
200
|
+
|
|
201
|
+
if (agentFiles.length === 0) {
|
|
202
|
+
check.issues.push({
|
|
203
|
+
type: 'no_agents',
|
|
204
|
+
path: 'agents',
|
|
205
|
+
message: 'No agent files found',
|
|
206
|
+
severity: 'warning'
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Check each agent has required sections
|
|
211
|
+
for (const file of agentFiles) {
|
|
212
|
+
const content = fs.readFileSync(path.join(agentDir, file), 'utf8');
|
|
213
|
+
|
|
214
|
+
if (!content.includes('## Role') && !content.includes('## Purpose')) {
|
|
215
|
+
check.issues.push({
|
|
216
|
+
type: 'missing_section',
|
|
217
|
+
path: `agents/${file}`,
|
|
218
|
+
message: `Agent ${file} missing Role/Purpose section`,
|
|
219
|
+
severity: 'warning'
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
console.log(check.issues.length === 0
|
|
225
|
+
? chalk.green(`✓ Agents: ${agentFiles.length} found`)
|
|
226
|
+
: chalk.yellow(`⚠ Agents: ${check.issues.length} issues`));
|
|
227
|
+
|
|
228
|
+
return check;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Check command files
|
|
233
|
+
*/
|
|
234
|
+
async function checkCommands(claudeDir) {
|
|
235
|
+
const check = { name: 'Commands', passed: true, issues: [] };
|
|
236
|
+
const commandDir = path.join(claudeDir, 'commands');
|
|
237
|
+
|
|
238
|
+
if (!fs.existsSync(commandDir)) {
|
|
239
|
+
check.issues.push({
|
|
240
|
+
type: 'missing_directory',
|
|
241
|
+
path: 'commands',
|
|
242
|
+
message: 'No commands directory',
|
|
243
|
+
severity: 'warning'
|
|
244
|
+
});
|
|
245
|
+
return check;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const commandFiles = await glob('*.md', { cwd: commandDir });
|
|
249
|
+
|
|
250
|
+
if (commandFiles.length === 0) {
|
|
251
|
+
check.issues.push({
|
|
252
|
+
type: 'no_commands',
|
|
253
|
+
path: 'commands',
|
|
254
|
+
message: 'No command files found',
|
|
255
|
+
severity: 'warning'
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
console.log(check.issues.length === 0
|
|
260
|
+
? chalk.green(`✓ Commands: ${commandFiles.length} found`)
|
|
261
|
+
: chalk.yellow(`⚠ Commands: ${check.issues.length} issues`));
|
|
262
|
+
|
|
263
|
+
return check;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Check workflow files
|
|
268
|
+
*/
|
|
269
|
+
async function checkWorkflows(claudeDir) {
|
|
270
|
+
const check = { name: 'Workflows', passed: true, issues: [] };
|
|
271
|
+
const workflowDir = path.join(claudeDir, 'context', 'workflows');
|
|
272
|
+
|
|
273
|
+
if (!fs.existsSync(workflowDir)) {
|
|
274
|
+
check.issues.push({
|
|
275
|
+
type: 'missing_directory',
|
|
276
|
+
path: 'context/workflows',
|
|
277
|
+
message: 'No workflows directory',
|
|
278
|
+
severity: 'info'
|
|
279
|
+
});
|
|
280
|
+
console.log(chalk.gray('- Workflows: Not configured (run @context-engineer to create)'));
|
|
281
|
+
return check;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const workflowFiles = await glob('*.md', { cwd: workflowDir });
|
|
285
|
+
|
|
286
|
+
console.log(workflowFiles.length > 0
|
|
287
|
+
? chalk.green(`✓ Workflows: ${workflowFiles.length} found`)
|
|
288
|
+
: chalk.gray('- Workflows: None yet'));
|
|
289
|
+
|
|
290
|
+
return check;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Fix detected issues
|
|
295
|
+
*/
|
|
296
|
+
async function fixIssues(claudeDir, projectRoot, issues) {
|
|
297
|
+
let fixed = 0;
|
|
298
|
+
|
|
299
|
+
for (const issue of issues) {
|
|
300
|
+
if (issue.fix && typeof issue.fix === 'function') {
|
|
301
|
+
try {
|
|
302
|
+
issue.fix();
|
|
303
|
+
fixed++;
|
|
304
|
+
console.log(chalk.green(` ✓ Fixed: ${issue.message}`));
|
|
305
|
+
} catch (e) {
|
|
306
|
+
console.log(chalk.red(` ✗ Failed to fix: ${issue.message}`));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return fixed;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Print diagnostics summary
|
|
316
|
+
*/
|
|
317
|
+
function printDiagnosticsSummary(results, options) {
|
|
318
|
+
const errors = results.issues.filter(i => i.severity === 'error').length;
|
|
319
|
+
const warnings = results.issues.filter(i => i.severity === 'warning').length;
|
|
320
|
+
|
|
321
|
+
console.log('\n' + chalk.bold('Diagnostics Summary:'));
|
|
322
|
+
console.log(` Checks run: ${results.checks.length}`);
|
|
323
|
+
console.log(` Errors: ${errors}`);
|
|
324
|
+
console.log(` Warnings: ${warnings}`);
|
|
325
|
+
|
|
326
|
+
if (options.fix) {
|
|
327
|
+
console.log(` Fixed: ${results.fixed}`);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (results.success) {
|
|
331
|
+
console.log(chalk.green('\n✓ System healthy!\n'));
|
|
332
|
+
} else {
|
|
333
|
+
console.log(chalk.red('\n✗ Issues detected. Run with --fix to auto-repair.\n'));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
module.exports = { diagnose };
|