aiknowsys 0.0.1
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/AGENTS.template.md +207 -0
- package/CODEBASE_CHANGELOG.template.md +145 -0
- package/CODEBASE_ESSENTIALS.template.md +382 -0
- package/LICENSE +21 -0
- package/README.md +714 -0
- package/bin/cli.js +81 -0
- package/lib/commands/init.js +227 -0
- package/lib/commands/install-agents.js +100 -0
- package/lib/commands/install-skills.js +92 -0
- package/lib/commands/migrate.js +161 -0
- package/lib/commands/scan.js +418 -0
- package/lib/utils.js +93 -0
- package/package.json +53 -0
- package/scripts/migrate-existing.sh +222 -0
- package/scripts/scan-codebase.sh +379 -0
- package/scripts/setup.sh +273 -0
- package/templates/agents/README.md +270 -0
- package/templates/agents/architect.agent.template.md +58 -0
- package/templates/agents/developer.agent.template.md +27 -0
- package/templates/agents/setup-agents.sh +65 -0
- package/templates/skills/code-refactoring/SKILL.md +662 -0
- package/templates/skills/dependency-updates/SKILL.md +561 -0
- package/templates/skills/documentation-management/SKILL.md +744 -0
- package/templates/skills/skill-creator/SKILL.md +252 -0
- package/templates/skills/skill-creator/template.md +89 -0
package/bin/cli.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { readFileSync } from 'fs';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { dirname, join } from 'path';
|
|
8
|
+
import { init } from '../lib/commands/init.js';
|
|
9
|
+
import { scan } from '../lib/commands/scan.js';
|
|
10
|
+
import { migrate } from '../lib/commands/migrate.js';
|
|
11
|
+
import { installAgents } from '../lib/commands/install-agents.js';
|
|
12
|
+
import { installSkills } from '../lib/commands/install-skills.js';
|
|
13
|
+
|
|
14
|
+
// Get version from package.json
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = dirname(__filename);
|
|
17
|
+
|
|
18
|
+
let packageJson;
|
|
19
|
+
try {
|
|
20
|
+
packageJson = JSON.parse(
|
|
21
|
+
readFileSync(join(__dirname, '../package.json'), 'utf-8')
|
|
22
|
+
);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error(chalk.red('Error: Could not read package.json'));
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const program = new Command();
|
|
29
|
+
|
|
30
|
+
program
|
|
31
|
+
.name('aiknowsys')
|
|
32
|
+
.description('AI-Powered Development Workflow for Consistent, High-Quality Code')
|
|
33
|
+
.version(packageJson.version);
|
|
34
|
+
|
|
35
|
+
program
|
|
36
|
+
.command('init')
|
|
37
|
+
.description('Initialize knowledge system for a new project')
|
|
38
|
+
.option('-d, --dir <directory>', 'Target directory', '.')
|
|
39
|
+
.option('-y, --yes', 'Skip prompts and use defaults')
|
|
40
|
+
.action(init);
|
|
41
|
+
|
|
42
|
+
program
|
|
43
|
+
.command('scan')
|
|
44
|
+
.description('Scan existing codebase and generate draft ESSENTIALS')
|
|
45
|
+
.option('-d, --dir <directory>', 'Project directory to scan', '.')
|
|
46
|
+
.option('-o, --output <file>', 'Output file name', 'CODEBASE_ESSENTIALS.draft.md')
|
|
47
|
+
.action(scan);
|
|
48
|
+
|
|
49
|
+
program
|
|
50
|
+
.command('migrate')
|
|
51
|
+
.description('Full migration workflow for existing projects')
|
|
52
|
+
.option('-d, --dir <directory>', 'Project directory', '.')
|
|
53
|
+
.action(migrate);
|
|
54
|
+
|
|
55
|
+
program
|
|
56
|
+
.command('install-agents')
|
|
57
|
+
.description('Install Developer + Architect custom agents')
|
|
58
|
+
.option('-d, --dir <directory>', 'Target directory', '.')
|
|
59
|
+
.option('-e, --essentials <file>', 'ESSENTIALS file name', 'CODEBASE_ESSENTIALS.md')
|
|
60
|
+
.action(installAgents);
|
|
61
|
+
|
|
62
|
+
program
|
|
63
|
+
.command('install-skills')
|
|
64
|
+
.description('Install universal skills to .github/skills/')
|
|
65
|
+
.option('-d, --dir <directory>', 'Target directory', '.')
|
|
66
|
+
.option('-s, --skills <skills...>', 'Specific skills to install')
|
|
67
|
+
.action(installSkills);
|
|
68
|
+
|
|
69
|
+
// Default command - show help with styled banner
|
|
70
|
+
program
|
|
71
|
+
.action(() => {
|
|
72
|
+
console.log('');
|
|
73
|
+
console.log(chalk.cyan(' ╔════════════════════════════════════════════════════════╗'));
|
|
74
|
+
console.log(chalk.cyan(' ║') + chalk.bold.white(' 🎯 Knowledge System Template ') + chalk.cyan('║'));
|
|
75
|
+
console.log(chalk.cyan(' ║') + chalk.gray(' AI-Powered Development Workflow ') + chalk.cyan('║'));
|
|
76
|
+
console.log(chalk.cyan(' ╚════════════════════════════════════════════════════════╝'));
|
|
77
|
+
console.log('');
|
|
78
|
+
program.outputHelp();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
program.parse();
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { execSync } from 'child_process';
|
|
4
|
+
import inquirer from 'inquirer';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import ora from 'ora';
|
|
7
|
+
import { getPackageDir, copyTemplate, hasExistingProject } from '../utils.js';
|
|
8
|
+
|
|
9
|
+
export async function init(options) {
|
|
10
|
+
const targetDir = path.resolve(options.dir);
|
|
11
|
+
|
|
12
|
+
console.log('');
|
|
13
|
+
console.log(chalk.cyan.bold('🎯 Knowledge System Setup'));
|
|
14
|
+
console.log('');
|
|
15
|
+
|
|
16
|
+
// Check for existing project
|
|
17
|
+
if (hasExistingProject(targetDir)) {
|
|
18
|
+
console.log(chalk.yellow('🔍 Existing project detected!'));
|
|
19
|
+
console.log('');
|
|
20
|
+
|
|
21
|
+
if (!options.yes) {
|
|
22
|
+
const { mode } = await inquirer.prompt([{
|
|
23
|
+
type: 'list',
|
|
24
|
+
name: 'mode',
|
|
25
|
+
message: 'Choose setup mode:',
|
|
26
|
+
choices: [
|
|
27
|
+
{ name: 'Scan existing codebase (recommended)', value: 'scan' },
|
|
28
|
+
{ name: 'Manual setup (blank templates)', value: 'manual' }
|
|
29
|
+
]
|
|
30
|
+
}]);
|
|
31
|
+
|
|
32
|
+
if (mode === 'scan') {
|
|
33
|
+
const { migrate } = await import('./migrate.js');
|
|
34
|
+
return migrate({ dir: targetDir });
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
console.log(chalk.blue('📝 Starting fresh project setup...'));
|
|
40
|
+
console.log('');
|
|
41
|
+
|
|
42
|
+
// Step 1: Technology Stack
|
|
43
|
+
const answers = await inquirer.prompt([
|
|
44
|
+
{
|
|
45
|
+
type: 'list',
|
|
46
|
+
name: 'language',
|
|
47
|
+
message: 'What\'s your primary language?',
|
|
48
|
+
choices: [
|
|
49
|
+
{ name: 'TypeScript/JavaScript', value: 'typescript' },
|
|
50
|
+
{ name: 'Python', value: 'python' },
|
|
51
|
+
{ name: 'Rust', value: 'rust' },
|
|
52
|
+
{ name: 'Go', value: 'go' },
|
|
53
|
+
{ name: 'Other', value: 'other' }
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: 'input',
|
|
58
|
+
name: 'customLanguage',
|
|
59
|
+
message: 'Enter language name:',
|
|
60
|
+
when: (ans) => ans.language === 'other'
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
type: 'list',
|
|
64
|
+
name: 'framework',
|
|
65
|
+
message: 'Frontend framework?',
|
|
66
|
+
when: (ans) => ans.language === 'typescript',
|
|
67
|
+
choices: [
|
|
68
|
+
{ name: 'Vue', value: 'vue' },
|
|
69
|
+
{ name: 'React', value: 'react' },
|
|
70
|
+
{ name: 'Svelte', value: 'svelte' },
|
|
71
|
+
{ name: 'Angular', value: 'angular' },
|
|
72
|
+
{ name: 'Next.js', value: 'nextjs' },
|
|
73
|
+
{ name: 'Vanilla/Other', value: 'vanilla' }
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
type: 'list',
|
|
78
|
+
name: 'framework',
|
|
79
|
+
message: 'Backend framework?',
|
|
80
|
+
when: (ans) => ans.language === 'python',
|
|
81
|
+
choices: [
|
|
82
|
+
{ name: 'Django', value: 'django' },
|
|
83
|
+
{ name: 'FastAPI', value: 'fastapi' },
|
|
84
|
+
{ name: 'Flask', value: 'flask' },
|
|
85
|
+
{ name: 'Other', value: 'other' }
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
type: 'input',
|
|
90
|
+
name: 'projectName',
|
|
91
|
+
message: 'Project name:',
|
|
92
|
+
default: path.basename(targetDir)
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
type: 'confirm',
|
|
96
|
+
name: 'useOpenSpec',
|
|
97
|
+
message: 'Use OpenSpec for spec-driven development? (recommended for teams)',
|
|
98
|
+
default: false
|
|
99
|
+
}
|
|
100
|
+
]);
|
|
101
|
+
|
|
102
|
+
const spinner = ora('Creating knowledge system files...').start();
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const packageDir = getPackageDir();
|
|
106
|
+
|
|
107
|
+
// Ensure target directory exists
|
|
108
|
+
if (!fs.existsSync(targetDir)) {
|
|
109
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Copy template files
|
|
113
|
+
copyTemplate(
|
|
114
|
+
path.join(packageDir, 'CODEBASE_ESSENTIALS.template.md'),
|
|
115
|
+
path.join(targetDir, 'CODEBASE_ESSENTIALS.md'),
|
|
116
|
+
{
|
|
117
|
+
'{{PROJECT_NAME}}': answers.projectName,
|
|
118
|
+
'{{LANGUAGE}}': answers.customLanguage || getLanguageName(answers.language),
|
|
119
|
+
'{{FRAMEWORK}}': getFrameworkName(answers.framework),
|
|
120
|
+
'{{DATE}}': new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
copyTemplate(
|
|
125
|
+
path.join(packageDir, 'AGENTS.template.md'),
|
|
126
|
+
path.join(targetDir, 'AGENTS.md')
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
copyTemplate(
|
|
130
|
+
path.join(packageDir, 'CODEBASE_CHANGELOG.template.md'),
|
|
131
|
+
path.join(targetDir, 'CODEBASE_CHANGELOG.md'),
|
|
132
|
+
{
|
|
133
|
+
'{{PROJECT_NAME}}': answers.projectName,
|
|
134
|
+
'{{DATE}}': new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
spinner.succeed('Core files created');
|
|
139
|
+
|
|
140
|
+
// Install agents
|
|
141
|
+
const agentSpinner = ora('Installing custom agents...').start();
|
|
142
|
+
const { installAgents } = await import('./install-agents.js');
|
|
143
|
+
await installAgents({ dir: targetDir, essentials: 'CODEBASE_ESSENTIALS.md', _silent: true });
|
|
144
|
+
agentSpinner.succeed('Custom agents installed');
|
|
145
|
+
|
|
146
|
+
// Install skills
|
|
147
|
+
const skillsSpinner = ora('Installing universal skills...').start();
|
|
148
|
+
const { installSkills } = await import('./install-skills.js');
|
|
149
|
+
await installSkills({ dir: targetDir, _silent: true });
|
|
150
|
+
skillsSpinner.succeed('Universal skills installed');
|
|
151
|
+
|
|
152
|
+
console.log('');
|
|
153
|
+
console.log(chalk.green.bold('✅ Knowledge system initialized!'));
|
|
154
|
+
console.log('');
|
|
155
|
+
console.log(chalk.white('📁 Created files:'));
|
|
156
|
+
console.log(chalk.gray(' • CODEBASE_ESSENTIALS.md'));
|
|
157
|
+
console.log(chalk.gray(' • AGENTS.md'));
|
|
158
|
+
console.log(chalk.gray(' • CODEBASE_CHANGELOG.md'));
|
|
159
|
+
console.log(chalk.gray(' • .github/agents/developer.agent.md'));
|
|
160
|
+
console.log(chalk.gray(' • .github/agents/architect.agent.md'));
|
|
161
|
+
console.log(chalk.gray(' • .github/skills/'));
|
|
162
|
+
console.log('');
|
|
163
|
+
console.log(chalk.cyan('📖 Next steps:'));
|
|
164
|
+
console.log(chalk.white(' 1. Complete TODO sections in CODEBASE_ESSENTIALS.md'));
|
|
165
|
+
console.log(chalk.white(' 2. Customize validation matrix in AGENTS.md'));
|
|
166
|
+
console.log(chalk.white(' 3. Start using: @Developer <your request>'));
|
|
167
|
+
|
|
168
|
+
// OpenSpec installation
|
|
169
|
+
if (answers.useOpenSpec) {
|
|
170
|
+
console.log('');
|
|
171
|
+
const openSpecSpinner = ora('Installing OpenSpec...').start();
|
|
172
|
+
try {
|
|
173
|
+
// Check if openspec is already installed globally
|
|
174
|
+
try {
|
|
175
|
+
execSync('openspec --version', { stdio: 'pipe' });
|
|
176
|
+
openSpecSpinner.text = 'OpenSpec already installed, initializing...';
|
|
177
|
+
} catch {
|
|
178
|
+
// Not installed, install it
|
|
179
|
+
execSync('npm install -g openspec', { stdio: 'pipe', cwd: targetDir });
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Initialize openspec in the project
|
|
183
|
+
execSync('openspec init', { stdio: 'pipe', cwd: targetDir });
|
|
184
|
+
openSpecSpinner.succeed('OpenSpec installed and initialized');
|
|
185
|
+
|
|
186
|
+
console.log(chalk.gray(' • openspec/project.md'));
|
|
187
|
+
console.log(chalk.gray(' • openspec/AGENTS.md'));
|
|
188
|
+
} catch (error) {
|
|
189
|
+
openSpecSpinner.warn('OpenSpec installation failed (you can install manually)');
|
|
190
|
+
if (error.message) {
|
|
191
|
+
console.log(chalk.gray(` Reason: ${error.message.split('\n')[0]}`));
|
|
192
|
+
}
|
|
193
|
+
console.log(chalk.gray(' Run: npm install -g openspec && openspec init'));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
console.log('');
|
|
197
|
+
|
|
198
|
+
} catch (error) {
|
|
199
|
+
spinner.fail('Failed to initialize');
|
|
200
|
+
console.error(chalk.red(error.message));
|
|
201
|
+
process.exit(1);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function getLanguageName(key) {
|
|
206
|
+
const names = {
|
|
207
|
+
typescript: 'TypeScript',
|
|
208
|
+
python: 'Python',
|
|
209
|
+
rust: 'Rust',
|
|
210
|
+
go: 'Go'
|
|
211
|
+
};
|
|
212
|
+
return names[key] || key;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function getFrameworkName(key) {
|
|
216
|
+
const names = {
|
|
217
|
+
vue: 'Vue 3',
|
|
218
|
+
react: 'React',
|
|
219
|
+
svelte: 'Svelte',
|
|
220
|
+
angular: 'Angular',
|
|
221
|
+
nextjs: 'Next.js',
|
|
222
|
+
django: 'Django',
|
|
223
|
+
fastapi: 'FastAPI',
|
|
224
|
+
flask: 'Flask'
|
|
225
|
+
};
|
|
226
|
+
return names[key] || key || 'None specified';
|
|
227
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import { getPackageDir, copyTemplate } from '../utils.js';
|
|
7
|
+
|
|
8
|
+
export async function installAgents(options) {
|
|
9
|
+
const targetDir = path.resolve(options.dir);
|
|
10
|
+
const essentialsFile = options.essentials || 'CODEBASE_ESSENTIALS.md';
|
|
11
|
+
const silent = options._silent || false;
|
|
12
|
+
|
|
13
|
+
if (!silent) {
|
|
14
|
+
console.log('');
|
|
15
|
+
console.log(chalk.cyan.bold('🤖 Installing Custom Agents (Developer + Architect Workflow)'));
|
|
16
|
+
console.log('');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const packageDir = getPackageDir();
|
|
20
|
+
const agentsDir = path.join(targetDir, '.github', 'agents');
|
|
21
|
+
|
|
22
|
+
// Create agents directory
|
|
23
|
+
if (!fs.existsSync(agentsDir)) {
|
|
24
|
+
fs.mkdirSync(agentsDir, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const spinner = silent ? null : ora('Copying agent templates...').start();
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
// Copy agent templates
|
|
31
|
+
copyTemplate(
|
|
32
|
+
path.join(packageDir, 'templates', 'agents', 'developer.agent.template.md'),
|
|
33
|
+
path.join(agentsDir, 'developer.agent.md'),
|
|
34
|
+
{
|
|
35
|
+
'{{ESSENTIALS_FILE}}': essentialsFile,
|
|
36
|
+
'{{PROJECT_GUIDELINES}}': 'None specified'
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
copyTemplate(
|
|
41
|
+
path.join(packageDir, 'templates', 'agents', 'architect.agent.template.md'),
|
|
42
|
+
path.join(agentsDir, 'architect.agent.md'),
|
|
43
|
+
{
|
|
44
|
+
'{{ESSENTIALS_FILE}}': essentialsFile
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
// Copy README
|
|
49
|
+
copyTemplate(
|
|
50
|
+
path.join(packageDir, 'templates', 'agents', 'README.md'),
|
|
51
|
+
path.join(agentsDir, 'README.md')
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
if (spinner) spinner.succeed('Agent templates installed');
|
|
55
|
+
|
|
56
|
+
// Ask for project-specific guidelines (only in interactive mode)
|
|
57
|
+
if (!silent) {
|
|
58
|
+
const { addGuidelines } = await inquirer.prompt([{
|
|
59
|
+
type: 'confirm',
|
|
60
|
+
name: 'addGuidelines',
|
|
61
|
+
message: 'Do you want to add project-specific guidelines for the Developer agent?',
|
|
62
|
+
default: false
|
|
63
|
+
}]);
|
|
64
|
+
|
|
65
|
+
if (addGuidelines) {
|
|
66
|
+
const { guidelines } = await inquirer.prompt([{
|
|
67
|
+
type: 'input',
|
|
68
|
+
name: 'guidelines',
|
|
69
|
+
message: 'Enter guidelines:'
|
|
70
|
+
}]);
|
|
71
|
+
|
|
72
|
+
if (guidelines) {
|
|
73
|
+
const devAgentPath = path.join(agentsDir, 'developer.agent.md');
|
|
74
|
+
let content = fs.readFileSync(devAgentPath, 'utf-8');
|
|
75
|
+
content = content.replace('None specified', guidelines);
|
|
76
|
+
fs.writeFileSync(devAgentPath, content);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log('');
|
|
81
|
+
console.log(chalk.green.bold('✅ Custom agents installed successfully!'));
|
|
82
|
+
console.log('');
|
|
83
|
+
console.log(chalk.white('📍 Location: .github/agents/'));
|
|
84
|
+
console.log(chalk.gray(' • developer.agent.md (Primary implementer)'));
|
|
85
|
+
console.log(chalk.gray(' • architect.agent.md (Code reviewer)'));
|
|
86
|
+
console.log(chalk.gray(' • README.md (Usage guide)'));
|
|
87
|
+
console.log('');
|
|
88
|
+
console.log(chalk.cyan.bold('🚀 Usage in VS Code:'));
|
|
89
|
+
console.log(chalk.white(' @Developer <your request> → Implements and auto-reviews'));
|
|
90
|
+
console.log(chalk.white(' @SeniorArchitect <file> → Direct review request'));
|
|
91
|
+
console.log('');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
} catch (error) {
|
|
95
|
+
if (spinner) spinner.fail('Failed to install agents');
|
|
96
|
+
console.error(chalk.red(error.message));
|
|
97
|
+
if (!silent) process.exit(1);
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import ora from 'ora';
|
|
5
|
+
import { getPackageDir, copyDirectory } from '../utils.js';
|
|
6
|
+
|
|
7
|
+
const AVAILABLE_SKILLS = [
|
|
8
|
+
'code-refactoring',
|
|
9
|
+
'dependency-updates',
|
|
10
|
+
'documentation-management',
|
|
11
|
+
'skill-creator'
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
export async function installSkills(options) {
|
|
15
|
+
const targetDir = path.resolve(options.dir);
|
|
16
|
+
const selectedSkills = options.skills || AVAILABLE_SKILLS;
|
|
17
|
+
const silent = options._silent || false;
|
|
18
|
+
|
|
19
|
+
if (!silent) {
|
|
20
|
+
console.log('');
|
|
21
|
+
console.log(chalk.cyan.bold('📚 Installing Universal Skills'));
|
|
22
|
+
console.log('');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const packageDir = getPackageDir();
|
|
26
|
+
const skillsDir = path.join(targetDir, '.github', 'skills');
|
|
27
|
+
|
|
28
|
+
// Create skills directory
|
|
29
|
+
if (!fs.existsSync(skillsDir)) {
|
|
30
|
+
fs.mkdirSync(skillsDir, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const spinner = silent ? null : ora('Installing skills...').start();
|
|
34
|
+
|
|
35
|
+
let installed = 0;
|
|
36
|
+
let skipped = 0;
|
|
37
|
+
|
|
38
|
+
try {
|
|
39
|
+
for (const skill of selectedSkills) {
|
|
40
|
+
const sourcePath = path.join(packageDir, 'templates', 'skills', skill);
|
|
41
|
+
const destPath = path.join(skillsDir, skill);
|
|
42
|
+
|
|
43
|
+
if (!fs.existsSync(sourcePath)) {
|
|
44
|
+
if (!silent) {
|
|
45
|
+
console.log(chalk.yellow(` ⚠️ Skill not found: ${skill}`));
|
|
46
|
+
}
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (fs.existsSync(destPath)) {
|
|
51
|
+
skipped++;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
copyDirectory(sourcePath, destPath);
|
|
56
|
+
installed++;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (spinner) {
|
|
60
|
+
if (installed > 0) {
|
|
61
|
+
spinner.succeed(`Installed ${installed} skill${installed > 1 ? 's' : ''}`);
|
|
62
|
+
} else if (skipped > 0) {
|
|
63
|
+
spinner.succeed('All skills already installed');
|
|
64
|
+
} else {
|
|
65
|
+
spinner.warn('No skills found to install');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!silent) {
|
|
70
|
+
console.log('');
|
|
71
|
+
console.log(chalk.white('📍 Location: .github/skills/'));
|
|
72
|
+
|
|
73
|
+
for (const skill of AVAILABLE_SKILLS) {
|
|
74
|
+
const destPath = path.join(skillsDir, skill);
|
|
75
|
+
if (fs.existsSync(destPath)) {
|
|
76
|
+
console.log(chalk.gray(` ✅ ${skill}`));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
console.log('');
|
|
81
|
+
console.log(chalk.cyan('💡 Skills provide domain-specific guidance for AI assistants'));
|
|
82
|
+
console.log(chalk.gray(' Use by asking about the topic, e.g., "How do I update dependencies?"'));
|
|
83
|
+
console.log('');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (spinner) spinner.fail('Failed to install skills');
|
|
88
|
+
console.error(chalk.red(error.message));
|
|
89
|
+
if (!silent) process.exit(1);
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import { scan } from './scan.js';
|
|
7
|
+
import { installAgents } from './install-agents.js';
|
|
8
|
+
import { installSkills } from './install-skills.js';
|
|
9
|
+
import { getPackageDir, copyTemplate } from '../utils.js';
|
|
10
|
+
|
|
11
|
+
export async function migrate(options) {
|
|
12
|
+
const targetDir = path.resolve(options.dir);
|
|
13
|
+
|
|
14
|
+
console.log('');
|
|
15
|
+
console.log(chalk.cyan.bold('🚀 Knowledge System Migration (Existing Project)'));
|
|
16
|
+
console.log('');
|
|
17
|
+
console.log(chalk.white('This will:'));
|
|
18
|
+
console.log(chalk.gray(' 1. Scan your codebase'));
|
|
19
|
+
console.log(chalk.gray(' 2. Generate draft documentation'));
|
|
20
|
+
console.log(chalk.gray(' 3. Install custom agents'));
|
|
21
|
+
console.log(chalk.gray(' 4. Set up skills'));
|
|
22
|
+
console.log(chalk.gray(' 5. Initialize changelog'));
|
|
23
|
+
console.log('');
|
|
24
|
+
|
|
25
|
+
const { proceed } = await inquirer.prompt([{
|
|
26
|
+
type: 'confirm',
|
|
27
|
+
name: 'proceed',
|
|
28
|
+
message: 'Continue?',
|
|
29
|
+
default: true
|
|
30
|
+
}]);
|
|
31
|
+
|
|
32
|
+
if (!proceed) {
|
|
33
|
+
console.log(chalk.yellow('Migration cancelled.'));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Step 1: Scan codebase
|
|
38
|
+
console.log('');
|
|
39
|
+
console.log(chalk.cyan('══════════════════════════════════════════'));
|
|
40
|
+
console.log(chalk.cyan.bold('Step 1/5: Scanning codebase...'));
|
|
41
|
+
console.log(chalk.cyan('══════════════════════════════════════════'));
|
|
42
|
+
|
|
43
|
+
const findings = await scan({ dir: targetDir, output: 'CODEBASE_ESSENTIALS.draft.md' });
|
|
44
|
+
|
|
45
|
+
// Step 2: Review draft
|
|
46
|
+
console.log('');
|
|
47
|
+
console.log(chalk.cyan('══════════════════════════════════════════'));
|
|
48
|
+
console.log(chalk.cyan.bold('Step 2/5: Review generated draft'));
|
|
49
|
+
console.log(chalk.cyan('══════════════════════════════════════════'));
|
|
50
|
+
console.log('');
|
|
51
|
+
console.log(chalk.yellow.bold('📝 CODEBASE_ESSENTIALS.draft.md has been created'));
|
|
52
|
+
console.log('');
|
|
53
|
+
console.log(chalk.white('IMPORTANT: You must complete the TODO sections!'));
|
|
54
|
+
console.log('');
|
|
55
|
+
console.log(chalk.gray('Required sections to fill in:'));
|
|
56
|
+
console.log(chalk.gray(' - Core Patterns (how you structure code, handle auth, make API calls)'));
|
|
57
|
+
console.log(chalk.gray(' - Critical Invariants (rules that must never be violated)'));
|
|
58
|
+
console.log(chalk.gray(' - Common Gotchas (issues new contributors encounter)'));
|
|
59
|
+
console.log(chalk.gray(' - Architecture Decisions (why you chose this approach)'));
|
|
60
|
+
console.log('');
|
|
61
|
+
|
|
62
|
+
const { reviewed } = await inquirer.prompt([{
|
|
63
|
+
type: 'confirm',
|
|
64
|
+
name: 'reviewed',
|
|
65
|
+
message: 'Have you completed and renamed the file to CODEBASE_ESSENTIALS.md?',
|
|
66
|
+
default: false
|
|
67
|
+
}]);
|
|
68
|
+
|
|
69
|
+
const essentialsPath = path.join(targetDir, 'CODEBASE_ESSENTIALS.md');
|
|
70
|
+
const draftPath = path.join(targetDir, 'CODEBASE_ESSENTIALS.draft.md');
|
|
71
|
+
|
|
72
|
+
if (!reviewed && !fs.existsSync(essentialsPath)) {
|
|
73
|
+
const { action } = await inquirer.prompt([{
|
|
74
|
+
type: 'list',
|
|
75
|
+
name: 'action',
|
|
76
|
+
message: 'CODEBASE_ESSENTIALS.md not found. What would you like to do?',
|
|
77
|
+
choices: [
|
|
78
|
+
{ name: 'Rename draft file now and continue', value: 'rename' },
|
|
79
|
+
{ name: 'Continue anyway (not recommended)', value: 'continue' },
|
|
80
|
+
{ name: 'Exit and complete the file first', value: 'exit' }
|
|
81
|
+
]
|
|
82
|
+
}]);
|
|
83
|
+
|
|
84
|
+
if (action === 'exit') {
|
|
85
|
+
console.log(chalk.yellow('Complete CODEBASE_ESSENTIALS.md and run: npx aiknowsys migrate'));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (action === 'rename' && fs.existsSync(draftPath)) {
|
|
90
|
+
fs.renameSync(draftPath, essentialsPath);
|
|
91
|
+
console.log(chalk.green('✅ Renamed to CODEBASE_ESSENTIALS.md'));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Step 3: Generate AGENTS.md
|
|
96
|
+
console.log('');
|
|
97
|
+
console.log(chalk.cyan('══════════════════════════════════════════'));
|
|
98
|
+
console.log(chalk.cyan.bold('Step 3/5: Creating AGENTS.md'));
|
|
99
|
+
console.log(chalk.cyan('══════════════════════════════════════════'));
|
|
100
|
+
|
|
101
|
+
const agentsPath = path.join(targetDir, 'AGENTS.md');
|
|
102
|
+
if (!fs.existsSync(agentsPath)) {
|
|
103
|
+
const packageDir = getPackageDir();
|
|
104
|
+
copyTemplate(
|
|
105
|
+
path.join(packageDir, 'AGENTS.template.md'),
|
|
106
|
+
agentsPath
|
|
107
|
+
);
|
|
108
|
+
console.log(chalk.green('✅ AGENTS.md created (customize validation matrix as needed)'));
|
|
109
|
+
} else {
|
|
110
|
+
console.log(chalk.gray('⏭️ AGENTS.md already exists, skipping'));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Step 4: Install custom agents
|
|
114
|
+
console.log('');
|
|
115
|
+
console.log(chalk.cyan('══════════════════════════════════════════'));
|
|
116
|
+
console.log(chalk.cyan.bold('Step 4/5: Installing custom agents...'));
|
|
117
|
+
console.log(chalk.cyan('══════════════════════════════════════════'));
|
|
118
|
+
|
|
119
|
+
await installAgents({ dir: targetDir, essentials: 'CODEBASE_ESSENTIALS.md' });
|
|
120
|
+
|
|
121
|
+
// Step 5: Install skills
|
|
122
|
+
console.log('');
|
|
123
|
+
console.log(chalk.cyan('══════════════════════════════════════════'));
|
|
124
|
+
console.log(chalk.cyan.bold('Step 5/5: Installing universal skills...'));
|
|
125
|
+
console.log(chalk.cyan('══════════════════════════════════════════'));
|
|
126
|
+
|
|
127
|
+
await installSkills({ dir: targetDir });
|
|
128
|
+
|
|
129
|
+
// Initialize changelog
|
|
130
|
+
const changelogPath = path.join(targetDir, 'CODEBASE_CHANGELOG.md');
|
|
131
|
+
if (!fs.existsSync(changelogPath)) {
|
|
132
|
+
const packageDir = getPackageDir();
|
|
133
|
+
const projectName = path.basename(targetDir);
|
|
134
|
+
copyTemplate(
|
|
135
|
+
path.join(packageDir, 'CODEBASE_CHANGELOG.template.md'),
|
|
136
|
+
changelogPath,
|
|
137
|
+
{
|
|
138
|
+
'{{PROJECT_NAME}}': projectName,
|
|
139
|
+
'{{DATE}}': new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
console.log(chalk.green('✅ CODEBASE_CHANGELOG.md initialized'));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Final summary
|
|
146
|
+
console.log('');
|
|
147
|
+
console.log(chalk.green.bold('═══════════════════════════════════════════'));
|
|
148
|
+
console.log(chalk.green.bold(' ✅ Migration Complete!'));
|
|
149
|
+
console.log(chalk.green.bold('═══════════════════════════════════════════'));
|
|
150
|
+
console.log('');
|
|
151
|
+
console.log(chalk.white('📁 Created files:'));
|
|
152
|
+
console.log(chalk.gray(' • CODEBASE_ESSENTIALS.md'));
|
|
153
|
+
console.log(chalk.gray(' • AGENTS.md'));
|
|
154
|
+
console.log(chalk.gray(' • CODEBASE_CHANGELOG.md'));
|
|
155
|
+
console.log(chalk.gray(' • .github/agents/'));
|
|
156
|
+
console.log(chalk.gray(' • .github/skills/'));
|
|
157
|
+
console.log('');
|
|
158
|
+
console.log(chalk.cyan.bold('🚀 Start using:'));
|
|
159
|
+
console.log(chalk.white(' @Developer <your request>'));
|
|
160
|
+
console.log('');
|
|
161
|
+
}
|