@nolrm/contextkit 0.13.5 → 0.14.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.
- package/README.md +78 -47
- package/bin/contextkit.js +22 -2
- package/lib/commands/analyze.js +131 -91
- package/lib/commands/check.js +24 -18
- package/lib/commands/gates.js +119 -0
- package/lib/commands/install.js +447 -142
- package/lib/commands/note.js +12 -20
- package/lib/commands/run.js +20 -22
- package/lib/commands/status.js +61 -32
- package/lib/commands/update.js +119 -80
- package/lib/index.js +3 -1
- package/lib/integrations/aider-integration.js +1 -1
- package/lib/integrations/base-integration.js +13 -6
- package/lib/integrations/claude-integration.js +103 -41
- package/lib/integrations/continue-integration.js +5 -5
- package/lib/integrations/copilot-integration.js +1 -1
- package/lib/integrations/cursor-integration.js +70 -28
- package/lib/integrations/gemini-integration.js +13 -11
- package/lib/integrations/index.js +11 -1
- package/lib/utils/banner.js +14 -11
- package/lib/utils/download.js +3 -4
- package/lib/utils/git-hooks.js +3 -4
- package/lib/utils/migrations.js +6 -4
- package/lib/utils/migrations.md +4 -3
- package/lib/utils/notifier.js +1 -1
- package/lib/utils/project-detector.js +11 -5
- package/lib/utils/status-manager.js +6 -7
- package/lib/utils/tool-detector.js +19 -21
- package/package.json +8 -2
package/lib/commands/note.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
|
-
const path = require('path');
|
|
4
3
|
|
|
5
4
|
class NoteCommand {
|
|
6
5
|
constructor() {
|
|
@@ -14,7 +13,7 @@ class NoteCommand {
|
|
|
14
13
|
return;
|
|
15
14
|
}
|
|
16
15
|
|
|
17
|
-
if (!await fs.pathExists(this.correctionsPath)) {
|
|
16
|
+
if (!(await fs.pathExists(this.correctionsPath))) {
|
|
18
17
|
console.log(chalk.red('❌ Corrections log not found'));
|
|
19
18
|
console.log(chalk.yellow(' Run: contextkit install'));
|
|
20
19
|
return;
|
|
@@ -23,48 +22,42 @@ class NoteCommand {
|
|
|
23
22
|
try {
|
|
24
23
|
const content = await fs.readFile(this.correctionsPath, 'utf-8');
|
|
25
24
|
const today = new Date().toISOString().split('T')[0];
|
|
26
|
-
|
|
25
|
+
|
|
27
26
|
// Find or create today's session
|
|
28
27
|
const sessionHeader = `### ${today} - ${options.task || 'Development Session'}`;
|
|
29
|
-
|
|
28
|
+
|
|
30
29
|
let updatedContent = content;
|
|
31
|
-
|
|
30
|
+
|
|
32
31
|
// Check if today's session exists
|
|
33
32
|
if (content.includes(sessionHeader)) {
|
|
34
33
|
// Add to existing session
|
|
35
34
|
const category = options.category || 'AI Behavior';
|
|
36
35
|
const priority = options.priority || 'MEDIUM';
|
|
37
36
|
const note = `- ${category} | ${message} [${priority}]`;
|
|
38
|
-
|
|
37
|
+
|
|
39
38
|
// Find the session and add note to appropriate section
|
|
40
39
|
const sections = ['Rule Updates', 'AI Behavior', 'Preferences', 'Trend Indicators'];
|
|
41
40
|
let sectionFound = false;
|
|
42
|
-
|
|
41
|
+
|
|
43
42
|
for (const section of sections) {
|
|
44
43
|
if (category.toLowerCase().includes(section.toLowerCase().substring(0, 5))) {
|
|
45
44
|
const sectionHeader = `#### ${section}`;
|
|
46
45
|
const sectionRegex = new RegExp(`(${sectionHeader}[\\s\\S]*?)(?=####|###|##|$)`, 'm');
|
|
47
46
|
const match = content.match(sectionRegex);
|
|
48
|
-
|
|
47
|
+
|
|
49
48
|
if (match) {
|
|
50
|
-
updatedContent = content.replace(
|
|
51
|
-
sectionRegex,
|
|
52
|
-
`$1\n${note}`
|
|
53
|
-
);
|
|
49
|
+
updatedContent = content.replace(sectionRegex, `$1\n${note}`);
|
|
54
50
|
sectionFound = true;
|
|
55
51
|
break;
|
|
56
52
|
}
|
|
57
53
|
}
|
|
58
54
|
}
|
|
59
|
-
|
|
55
|
+
|
|
60
56
|
if (!sectionFound) {
|
|
61
57
|
// Add to AI Behavior section as default
|
|
62
58
|
const aiBehaviorRegex = /(#### AI Behavior[\s\S]*?)(?=####|###|##|$)/m;
|
|
63
59
|
if (content.match(aiBehaviorRegex)) {
|
|
64
|
-
updatedContent = content.replace(
|
|
65
|
-
aiBehaviorRegex,
|
|
66
|
-
`$1\n${note}`
|
|
67
|
-
);
|
|
60
|
+
updatedContent = content.replace(aiBehaviorRegex, `$1\n${note}`);
|
|
68
61
|
}
|
|
69
62
|
}
|
|
70
63
|
} else {
|
|
@@ -91,7 +84,7 @@ ${sessionHeader}
|
|
|
91
84
|
- [No trends yet]
|
|
92
85
|
|
|
93
86
|
`;
|
|
94
|
-
|
|
87
|
+
|
|
95
88
|
// Insert after "## Recent Sessions"
|
|
96
89
|
const sessionsRegex = /(## Recent Sessions\n)/;
|
|
97
90
|
if (content.match(sessionsRegex)) {
|
|
@@ -101,7 +94,7 @@ ${sessionHeader}
|
|
|
101
94
|
updatedContent = `## Recent Sessions${newSession}\n${content}`;
|
|
102
95
|
}
|
|
103
96
|
}
|
|
104
|
-
|
|
97
|
+
|
|
105
98
|
await fs.writeFile(this.correctionsPath, updatedContent);
|
|
106
99
|
console.log(chalk.green('✅ Note added to corrections log'));
|
|
107
100
|
console.log(chalk.dim(` ${message}`));
|
|
@@ -117,4 +110,3 @@ async function note(message, options) {
|
|
|
117
110
|
}
|
|
118
111
|
|
|
119
112
|
module.exports = note;
|
|
120
|
-
|
package/lib/commands/run.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const ora = require('ora');
|
|
5
3
|
|
|
6
4
|
class RunCommand {
|
|
7
5
|
constructor() {
|
|
@@ -18,7 +16,7 @@ class RunCommand {
|
|
|
18
16
|
const possiblePaths = [
|
|
19
17
|
`.contextkit/instructions/core/${workflowName}.md`,
|
|
20
18
|
`.contextkit/instructions/${workflowName}.md`,
|
|
21
|
-
`.contextkit/commands/${workflowName}.md
|
|
19
|
+
`.contextkit/commands/${workflowName}.md`,
|
|
22
20
|
];
|
|
23
21
|
|
|
24
22
|
let workflowPath = null;
|
|
@@ -32,7 +30,7 @@ class RunCommand {
|
|
|
32
30
|
if (!workflowPath) {
|
|
33
31
|
console.log(chalk.red(`❌ Workflow not found: ${workflowName}`));
|
|
34
32
|
console.log(chalk.yellow(' Searched in:'));
|
|
35
|
-
possiblePaths.forEach(p => console.log(chalk.dim(` - ${p}`)));
|
|
33
|
+
possiblePaths.forEach((p) => console.log(chalk.dim(` - ${p}`)));
|
|
36
34
|
return;
|
|
37
35
|
}
|
|
38
36
|
|
|
@@ -41,7 +39,7 @@ class RunCommand {
|
|
|
41
39
|
|
|
42
40
|
// Parse workflow
|
|
43
41
|
const parsed = this.parseWorkflow(this.workflowContent);
|
|
44
|
-
|
|
42
|
+
|
|
45
43
|
if (!parsed) {
|
|
46
44
|
console.log(chalk.red('❌ Failed to parse workflow'));
|
|
47
45
|
return;
|
|
@@ -55,15 +53,15 @@ class RunCommand {
|
|
|
55
53
|
// Execute workflow steps
|
|
56
54
|
if (parsed.steps && parsed.steps.length > 0) {
|
|
57
55
|
console.log(chalk.blue(`\n📋 Executing ${parsed.steps.length} step(s)...\n`));
|
|
58
|
-
|
|
56
|
+
|
|
59
57
|
for (let i = 0; i < parsed.steps.length; i++) {
|
|
60
58
|
const step = parsed.steps[i];
|
|
61
59
|
this.currentStep = i + 1;
|
|
62
|
-
|
|
60
|
+
|
|
63
61
|
console.log(chalk.cyan(`\n${'─'.repeat(60)}`));
|
|
64
62
|
console.log(chalk.bold(`Step ${step.number}: ${step.name || 'Unnamed Step'}`));
|
|
65
63
|
console.log(chalk.cyan(`${'─'.repeat(60)}\n`));
|
|
66
|
-
|
|
64
|
+
|
|
67
65
|
await this.executeStep(step, options);
|
|
68
66
|
}
|
|
69
67
|
}
|
|
@@ -80,7 +78,7 @@ class RunCommand {
|
|
|
80
78
|
const result = {
|
|
81
79
|
preFlight: null,
|
|
82
80
|
steps: [],
|
|
83
|
-
postFlight: null
|
|
81
|
+
postFlight: null,
|
|
84
82
|
};
|
|
85
83
|
|
|
86
84
|
// Extract pre-flight
|
|
@@ -93,17 +91,18 @@ class RunCommand {
|
|
|
93
91
|
const processFlowMatch = content.match(/<process_flow>([\s\S]*?)<\/process_flow>/);
|
|
94
92
|
if (processFlowMatch) {
|
|
95
93
|
const processFlow = processFlowMatch[1];
|
|
96
|
-
|
|
94
|
+
|
|
97
95
|
// Extract all steps
|
|
98
|
-
const stepRegex =
|
|
96
|
+
const stepRegex =
|
|
97
|
+
/<step\s+number="(\d+)"(?:\s+subagent="([^"]+)")?(?:\s+name="([^"]+)")?>([\s\S]*?)<\/step>/g;
|
|
99
98
|
let stepMatch;
|
|
100
|
-
|
|
99
|
+
|
|
101
100
|
while ((stepMatch = stepRegex.exec(processFlow)) !== null) {
|
|
102
101
|
result.steps.push({
|
|
103
102
|
number: parseInt(stepMatch[1]),
|
|
104
103
|
subagent: stepMatch[2] || null,
|
|
105
104
|
name: stepMatch[3] || null,
|
|
106
|
-
content: stepMatch[4].trim()
|
|
105
|
+
content: stepMatch[4].trim(),
|
|
107
106
|
});
|
|
108
107
|
}
|
|
109
108
|
}
|
|
@@ -119,12 +118,12 @@ class RunCommand {
|
|
|
119
118
|
|
|
120
119
|
async executePreFlight(preFlightContent) {
|
|
121
120
|
console.log(chalk.blue('🔍 Pre-flight checks...\n'));
|
|
122
|
-
|
|
121
|
+
|
|
123
122
|
// Check for EXECUTE directive
|
|
124
123
|
const executeMatch = preFlightContent.match(/EXECUTE:\s*(.+)/);
|
|
125
124
|
if (executeMatch) {
|
|
126
125
|
const filePath = executeMatch[1].trim().replace('@.contextkit/', '.contextkit/');
|
|
127
|
-
|
|
126
|
+
|
|
128
127
|
if (await fs.pathExists(filePath)) {
|
|
129
128
|
const preFlightFile = await fs.readFile(filePath, 'utf-8');
|
|
130
129
|
console.log(chalk.dim(preFlightFile));
|
|
@@ -151,7 +150,7 @@ class RunCommand {
|
|
|
151
150
|
|
|
152
151
|
// Extract instructions from step content
|
|
153
152
|
const instructions = this.extractInstructions(step.content);
|
|
154
|
-
|
|
153
|
+
|
|
155
154
|
// For now, display instructions and wait for user/AI to execute
|
|
156
155
|
if (instructions.length > 0) {
|
|
157
156
|
console.log(chalk.blue('📝 Instructions to execute:'));
|
|
@@ -167,7 +166,7 @@ class RunCommand {
|
|
|
167
166
|
if (options.interactive) {
|
|
168
167
|
const readline = require('readline').createInterface({
|
|
169
168
|
input: process.stdin,
|
|
170
|
-
output: process.stdout
|
|
169
|
+
output: process.stdout,
|
|
171
170
|
});
|
|
172
171
|
|
|
173
172
|
return new Promise((resolve) => {
|
|
@@ -181,7 +180,7 @@ class RunCommand {
|
|
|
181
180
|
|
|
182
181
|
extractInstructions(content) {
|
|
183
182
|
const instructions = [];
|
|
184
|
-
|
|
183
|
+
|
|
185
184
|
// Extract ACTION directives
|
|
186
185
|
const actionMatches = content.matchAll(/ACTION:\s*(.+)/gi);
|
|
187
186
|
for (const match of actionMatches) {
|
|
@@ -199,17 +198,17 @@ class RunCommand {
|
|
|
199
198
|
|
|
200
199
|
async executePostFlight(postFlightContent) {
|
|
201
200
|
console.log(chalk.blue('\n🔍 Post-flight checks...\n'));
|
|
202
|
-
|
|
201
|
+
|
|
203
202
|
// Check for EXECUTE directive
|
|
204
203
|
const executeMatch = postFlightContent.match(/EXECUTE:\s*(.+)/);
|
|
205
204
|
if (executeMatch) {
|
|
206
205
|
const filePath = executeMatch[1].trim().replace('@.contextkit/', '.contextkit/');
|
|
207
|
-
|
|
206
|
+
|
|
208
207
|
if (await fs.pathExists(filePath)) {
|
|
209
208
|
const postFlightFile = await fs.readFile(filePath, 'utf-8');
|
|
210
209
|
console.log(chalk.dim(postFlightFile));
|
|
211
210
|
console.log('');
|
|
212
|
-
|
|
211
|
+
|
|
213
212
|
// Check for corrections log update instructions
|
|
214
213
|
if (postFlightFile.includes('corrections log')) {
|
|
215
214
|
console.log(chalk.yellow('💡 Remember to update corrections.md if any issues occurred'));
|
|
@@ -229,4 +228,3 @@ async function run(workflowName, options) {
|
|
|
229
228
|
}
|
|
230
229
|
|
|
231
230
|
module.exports = run;
|
|
232
|
-
|
package/lib/commands/status.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
|
-
const ora = require('ora');
|
|
3
2
|
const fs = require('fs-extra');
|
|
4
3
|
const path = require('path');
|
|
5
4
|
const StatusManager = require('../utils/status-manager');
|
|
@@ -11,49 +10,59 @@ class StatusCommand {
|
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
async status() {
|
|
14
|
-
if (!await fs.pathExists(this.configPath)) {
|
|
13
|
+
if (!(await fs.pathExists(this.configPath))) {
|
|
15
14
|
console.log(chalk.red('❌ ContextKit is not installed in this project'));
|
|
16
15
|
console.log(chalk.yellow('💡 Run: contextkit install'));
|
|
17
16
|
return;
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
try {
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
20
|
+
const _config = await this.parseConfig();
|
|
21
|
+
const _projectType = await this.detectProjectType();
|
|
22
|
+
const _packageManager = await this.detectPackageManager();
|
|
24
23
|
const status = await this.statusManager.getStatus();
|
|
25
24
|
const analyzeInfo = await this.statusManager.getAnalyzeInfo();
|
|
26
25
|
|
|
27
26
|
console.log(chalk.green('🎵 ContextKit Status'));
|
|
28
27
|
console.log('');
|
|
29
|
-
|
|
28
|
+
|
|
30
29
|
console.log(chalk.blue('📦 Installation:'));
|
|
31
30
|
console.log(` Version: ${status.version}`);
|
|
32
31
|
console.log(` Installed: ${new Date(status.installed_at).toLocaleDateString()}`);
|
|
33
32
|
console.log(` Last Updated: ${new Date(status.last_updated).toLocaleDateString()}`);
|
|
34
33
|
console.log('');
|
|
35
|
-
|
|
34
|
+
|
|
36
35
|
console.log(chalk.blue('🔍 Analysis:'));
|
|
37
36
|
if (analyzeInfo.isFirstTime) {
|
|
38
37
|
console.log(chalk.yellow(' Status: Not analyzed'));
|
|
39
|
-
console.log(
|
|
38
|
+
console.log(
|
|
39
|
+
chalk.blue(
|
|
40
|
+
' Recommendation: Run @.contextkit/commands/analyze.md to customize standards'
|
|
41
|
+
)
|
|
42
|
+
);
|
|
40
43
|
} else {
|
|
41
|
-
console.log(
|
|
44
|
+
console.log(
|
|
45
|
+
chalk.green(
|
|
46
|
+
` Status: Completed (${new Date(analyzeInfo.lastRun).toLocaleDateString()})`
|
|
47
|
+
)
|
|
48
|
+
);
|
|
42
49
|
console.log(chalk.blue(` Project: ${analyzeInfo.projectType || 'Unknown'}`));
|
|
43
50
|
console.log(chalk.blue(` Package Manager: ${analyzeInfo.packageManager || 'Unknown'}`));
|
|
44
51
|
if (analyzeInfo.customizations.length > 0) {
|
|
45
|
-
console.log(
|
|
52
|
+
console.log(
|
|
53
|
+
chalk.blue(` Customizations: ${analyzeInfo.customizations.length} applied`)
|
|
54
|
+
);
|
|
46
55
|
}
|
|
47
56
|
}
|
|
48
57
|
console.log('');
|
|
49
|
-
|
|
58
|
+
|
|
50
59
|
console.log(chalk.blue('✅ Features:'));
|
|
51
60
|
console.log(` Pre-push hook: ${status.features.pre_push_hook ? '✅' : '❌'}`);
|
|
52
61
|
console.log(` Commit-msg hook: ${status.features.commit_msg_hook ? '✅' : '❌'}`);
|
|
53
62
|
console.log(` Standards: ${status.features.standards ? '✅' : '❌'}`);
|
|
54
63
|
console.log(` Templates: ${status.features.templates ? '✅' : '❌'}`);
|
|
55
64
|
console.log('');
|
|
56
|
-
|
|
65
|
+
|
|
57
66
|
// Check context files
|
|
58
67
|
console.log(chalk.blue('📚 Context Files (Loaded with ck "prompt"):'));
|
|
59
68
|
const contextFiles = await this.checkContextFiles();
|
|
@@ -63,7 +72,7 @@ class StatusCommand {
|
|
|
63
72
|
console.log(` architecture.md: ${contextFiles.architecture ? '✅' : '❌'}`);
|
|
64
73
|
console.log(` ai-guidelines.md: ${contextFiles.guidelines ? '✅' : '❌'}`);
|
|
65
74
|
console.log(` glossary.md: ${contextFiles.glossary ? '✅' : '❌'}`);
|
|
66
|
-
|
|
75
|
+
|
|
67
76
|
if (contextFiles.allPresent) {
|
|
68
77
|
console.log(chalk.green('\n✅ All context files ready for AI prompts!'));
|
|
69
78
|
} else {
|
|
@@ -86,7 +95,6 @@ class StatusCommand {
|
|
|
86
95
|
} else {
|
|
87
96
|
console.log(chalk.green('✅ ContextKit is up to date'));
|
|
88
97
|
}
|
|
89
|
-
|
|
90
98
|
} catch (error) {
|
|
91
99
|
console.log(chalk.red('❌ Error reading ContextKit configuration:'), error.message);
|
|
92
100
|
}
|
|
@@ -95,7 +103,7 @@ class StatusCommand {
|
|
|
95
103
|
async parseConfig() {
|
|
96
104
|
const configContent = await fs.readFile(this.configPath, 'utf8');
|
|
97
105
|
const config = {};
|
|
98
|
-
|
|
106
|
+
|
|
99
107
|
// Simple YAML parsing for our config format
|
|
100
108
|
const lines = configContent.split('\n');
|
|
101
109
|
for (const line of lines) {
|
|
@@ -144,7 +152,10 @@ class StatusCommand {
|
|
|
144
152
|
return 'react';
|
|
145
153
|
} else if (packageJson.dependencies?.vue || packageJson.devDependencies?.vue) {
|
|
146
154
|
return 'vue';
|
|
147
|
-
} else if (
|
|
155
|
+
} else if (
|
|
156
|
+
packageJson.dependencies?.['@angular/core'] ||
|
|
157
|
+
packageJson.devDependencies?.['@angular/core']
|
|
158
|
+
) {
|
|
148
159
|
return 'angular';
|
|
149
160
|
} else if (packageJson.dependencies?.next || packageJson.devDependencies?.next) {
|
|
150
161
|
return 'nextjs';
|
|
@@ -154,7 +165,10 @@ class StatusCommand {
|
|
|
154
165
|
return 'svelte';
|
|
155
166
|
}
|
|
156
167
|
return 'node';
|
|
157
|
-
} else if (
|
|
168
|
+
} else if (
|
|
169
|
+
(await fs.pathExists('requirements.txt')) ||
|
|
170
|
+
(await fs.pathExists('pyproject.toml'))
|
|
171
|
+
) {
|
|
158
172
|
return 'python';
|
|
159
173
|
} else if (await fs.pathExists('Cargo.toml')) {
|
|
160
174
|
return 'rust';
|
|
@@ -180,24 +194,27 @@ class StatusCommand {
|
|
|
180
194
|
async checkForUpdates(currentVersion) {
|
|
181
195
|
try {
|
|
182
196
|
const axios = require('axios');
|
|
183
|
-
const response = await axios.get(
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
197
|
+
const response = await axios.get(
|
|
198
|
+
'https://api.github.com/repos/nolrm/contextkit/releases/latest',
|
|
199
|
+
{
|
|
200
|
+
timeout: 5000,
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
|
|
187
204
|
const latestVersion = response.data.tag_name.replace('v', '');
|
|
188
205
|
const hasUpdate = this.isNewerVersion(latestVersion, currentVersion);
|
|
189
|
-
|
|
206
|
+
|
|
190
207
|
return {
|
|
191
208
|
hasUpdate,
|
|
192
209
|
currentVersion,
|
|
193
|
-
latestVersion
|
|
210
|
+
latestVersion,
|
|
194
211
|
};
|
|
195
212
|
} catch (error) {
|
|
196
213
|
return {
|
|
197
214
|
hasUpdate: false,
|
|
198
215
|
currentVersion,
|
|
199
216
|
latestVersion: 'unknown',
|
|
200
|
-
error: error.message
|
|
217
|
+
error: error.message,
|
|
201
218
|
};
|
|
202
219
|
}
|
|
203
220
|
}
|
|
@@ -205,15 +222,15 @@ class StatusCommand {
|
|
|
205
222
|
isNewerVersion(latest, current) {
|
|
206
223
|
const latestParts = latest.split('.').map(Number);
|
|
207
224
|
const currentParts = current.split('.').map(Number);
|
|
208
|
-
|
|
225
|
+
|
|
209
226
|
for (let i = 0; i < Math.max(latestParts.length, currentParts.length); i++) {
|
|
210
227
|
const latestPart = latestParts[i] || 0;
|
|
211
228
|
const currentPart = currentParts[i] || 0;
|
|
212
|
-
|
|
229
|
+
|
|
213
230
|
if (latestPart > currentPart) return true;
|
|
214
231
|
if (latestPart < currentPart) return false;
|
|
215
232
|
}
|
|
216
|
-
|
|
233
|
+
|
|
217
234
|
return false;
|
|
218
235
|
}
|
|
219
236
|
|
|
@@ -228,11 +245,17 @@ class StatusCommand {
|
|
|
228
245
|
if (allFiles.length === 0) continue;
|
|
229
246
|
|
|
230
247
|
if (result.valid) {
|
|
231
|
-
console.log(
|
|
248
|
+
console.log(
|
|
249
|
+
` ${integration.displayName}: ${chalk.green('✅')} (${result.present.length} files)`
|
|
250
|
+
);
|
|
232
251
|
} else if (result.present.length > 0) {
|
|
233
|
-
console.log(
|
|
252
|
+
console.log(
|
|
253
|
+
` ${integration.displayName}: ${chalk.yellow('⚠️')} (${result.present.length}/${allFiles.length} files)`
|
|
254
|
+
);
|
|
234
255
|
} else {
|
|
235
|
-
console.log(
|
|
256
|
+
console.log(
|
|
257
|
+
` ${integration.displayName}: ${chalk.dim('not installed')} → run: ck ${name}`
|
|
258
|
+
);
|
|
236
259
|
}
|
|
237
260
|
}
|
|
238
261
|
}
|
|
@@ -244,10 +267,16 @@ class StatusCommand {
|
|
|
244
267
|
testing: await fs.pathExists('.contextkit/standards/testing.md'),
|
|
245
268
|
architecture: await fs.pathExists('.contextkit/standards/architecture.md'),
|
|
246
269
|
guidelines: await fs.pathExists('.contextkit/standards/ai-guidelines.md'),
|
|
247
|
-
glossary: await fs.pathExists('.contextkit/standards/glossary.md')
|
|
270
|
+
glossary: await fs.pathExists('.contextkit/standards/glossary.md'),
|
|
248
271
|
};
|
|
249
272
|
|
|
250
|
-
checks.allPresent =
|
|
273
|
+
checks.allPresent =
|
|
274
|
+
checks.context &&
|
|
275
|
+
checks.codeStyle &&
|
|
276
|
+
checks.testing &&
|
|
277
|
+
checks.architecture &&
|
|
278
|
+
checks.guidelines &&
|
|
279
|
+
checks.glossary;
|
|
251
280
|
|
|
252
281
|
return checks;
|
|
253
282
|
}
|