anchi-kit 2.0.3 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of anchi-kit might be problematic. Click here for more details.
- package/.cursor/anchi-kit.config.yaml +32 -0
- package/.cursor/commands/context.md +76 -0
- package/.cursor/commands/cook/auto.md +80 -10
- package/.cursor/commands/generate/api.md +79 -0
- package/.cursor/commands/generate/component.md +80 -0
- package/.cursor/commands/generate/page.md +71 -0
- package/.cursor/commands/plan/auto.md +77 -0
- package/.cursor/commands/suggest.md +65 -0
- package/.cursor/custom-commands/example.md +30 -0
- package/.cursor/hooks.yaml +28 -0
- package/.cursor/team.yaml +63 -0
- package/.cursor/workflows/feature.yaml +51 -0
- package/.cursor/workflows/hotfix.yaml +35 -0
- package/.cursor/workflows/release.yaml +61 -0
- package/CURSOR.md +5 -5
- package/README.md +10 -5
- package/docs/{codebase-summary.md → CODEBASE.md} +2 -2
- package/docs/{code-standards.md → CODE_STYLE.md} +1 -1
- package/docs/FAQ.md +1 -1
- package/docs/{ONBOARDING_CHECKLIST.md → ONBOARDING.md} +4 -4
- package/docs/{project-overview-pdr.md → PROJECT.md} +2 -2
- package/docs/{TEAM_PIPELINE.md → WORKFLOW.md} +1 -1
- package/package.json +1 -1
- package/scripts/check-setup.ps1 +1 -1
- package/scripts/install-hooks.ps1 +60 -0
- package/scripts/install-hooks.sh +54 -0
- package/scripts/new-project.ps1 +1 -1
- package/scripts/new-project.sh +61 -61
- package/src/cli.js +6 -0
- package/src/commands/doctor.js +106 -0
- package/src/lib/configManager.js +200 -0
- package/docs/PROJECT_SUMMARY.md +0 -86
- /package/docs/{system-architecture.md → ARCHITECTURE.md} +0 -0
- /package/docs/{project-roadmap.md → ROADMAP.md} +0 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// anchi-kit Doctor Command
|
|
3
|
+
// Diagnose and check setup health
|
|
4
|
+
// =============================================================================
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
async function doctor(targetDir = process.cwd()) {
|
|
10
|
+
console.log('');
|
|
11
|
+
console.log('🩺 anchi-kit Doctor');
|
|
12
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
13
|
+
console.log('');
|
|
14
|
+
|
|
15
|
+
const checks = [];
|
|
16
|
+
|
|
17
|
+
// Check .cursor folder
|
|
18
|
+
const cursorDir = path.join(targetDir, '.cursor');
|
|
19
|
+
checks.push({
|
|
20
|
+
name: '.cursor folder',
|
|
21
|
+
ok: fs.existsSync(cursorDir),
|
|
22
|
+
fix: 'Run: npx anchi-kit init'
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Check commands
|
|
26
|
+
const commandsDir = path.join(cursorDir, 'commands');
|
|
27
|
+
const commandCount = fs.existsSync(commandsDir)
|
|
28
|
+
? fs.readdirSync(commandsDir, { recursive: true }).filter(f => f.endsWith('.md')).length
|
|
29
|
+
: 0;
|
|
30
|
+
checks.push({
|
|
31
|
+
name: 'Commands',
|
|
32
|
+
ok: commandCount > 0,
|
|
33
|
+
value: `${commandCount} files`,
|
|
34
|
+
fix: 'Run: npx anchi-kit install'
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Check agents
|
|
38
|
+
const agentsDir = path.join(cursorDir, 'agents');
|
|
39
|
+
const agentCount = fs.existsSync(agentsDir)
|
|
40
|
+
? fs.readdirSync(agentsDir).filter(f => f.endsWith('.md')).length
|
|
41
|
+
: 0;
|
|
42
|
+
checks.push({
|
|
43
|
+
name: 'Agents',
|
|
44
|
+
ok: agentCount > 0,
|
|
45
|
+
value: `${agentCount} files`,
|
|
46
|
+
fix: 'Run: npx anchi-kit install'
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Check .cursorrules
|
|
50
|
+
const rulesFile = path.join(targetDir, '.cursorrules');
|
|
51
|
+
checks.push({
|
|
52
|
+
name: '.cursorrules',
|
|
53
|
+
ok: fs.existsSync(rulesFile),
|
|
54
|
+
fix: 'Run: /use-preset [name]'
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Check config
|
|
58
|
+
const configFile = path.join(cursorDir, 'anchi-kit.config.yaml');
|
|
59
|
+
checks.push({
|
|
60
|
+
name: 'Config file',
|
|
61
|
+
ok: fs.existsSync(configFile),
|
|
62
|
+
fix: 'Run: npx anchi-kit init'
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Check docs
|
|
66
|
+
const docsDir = path.join(targetDir, 'docs');
|
|
67
|
+
checks.push({
|
|
68
|
+
name: 'Docs folder',
|
|
69
|
+
ok: fs.existsSync(docsDir),
|
|
70
|
+
fix: 'Run: npx anchi-kit install'
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Check package.json
|
|
74
|
+
const pkgFile = path.join(targetDir, 'package.json');
|
|
75
|
+
checks.push({
|
|
76
|
+
name: 'package.json',
|
|
77
|
+
ok: fs.existsSync(pkgFile),
|
|
78
|
+
fix: 'Run: npm init -y'
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Display results
|
|
82
|
+
let allOk = true;
|
|
83
|
+
for (const check of checks) {
|
|
84
|
+
const status = check.ok ? '✅' : '❌';
|
|
85
|
+
const value = check.value ? ` (${check.value})` : '';
|
|
86
|
+
console.log(` ${status} ${check.name}${value}`);
|
|
87
|
+
if (!check.ok) {
|
|
88
|
+
console.log(` 💡 Fix: ${check.fix}`);
|
|
89
|
+
allOk = false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
console.log('');
|
|
94
|
+
console.log('═══════════════════════════════════════════════════════════════');
|
|
95
|
+
|
|
96
|
+
if (allOk) {
|
|
97
|
+
console.log('✅ All checks passed! anchi-kit is healthy.');
|
|
98
|
+
} else {
|
|
99
|
+
console.log('⚠️ Some issues found. See fixes above.');
|
|
100
|
+
}
|
|
101
|
+
console.log('');
|
|
102
|
+
|
|
103
|
+
return allOk;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = { doctor };
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// anchi-kit Config Manager
|
|
3
|
+
// Handles loading, saving, and merging configuration
|
|
4
|
+
// =============================================================================
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
const CONFIG_FILENAME = 'anchi-kit.config.yaml';
|
|
10
|
+
|
|
11
|
+
// Default configuration
|
|
12
|
+
const DEFAULT_CONFIG = {
|
|
13
|
+
version: '2.1',
|
|
14
|
+
profile: 'developer',
|
|
15
|
+
|
|
16
|
+
model_preference: {
|
|
17
|
+
default: 'auto',
|
|
18
|
+
complex: 'opus',
|
|
19
|
+
economy: 'haiku',
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
features: {
|
|
23
|
+
auto_commit: false,
|
|
24
|
+
auto_push: false,
|
|
25
|
+
progress_indicators: true,
|
|
26
|
+
summary_cards: true,
|
|
27
|
+
quick_actions: true,
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
team: {
|
|
31
|
+
role: null, // frontend, backend, fullstack, lead, etc.
|
|
32
|
+
slack_webhook: null,
|
|
33
|
+
notifications: true,
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
hooks: {
|
|
37
|
+
enabled: false,
|
|
38
|
+
pre_commit: [],
|
|
39
|
+
post_merge: [],
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Parse simple YAML (subset)
|
|
45
|
+
*/
|
|
46
|
+
function parseYaml(content) {
|
|
47
|
+
const result = {};
|
|
48
|
+
const lines = content.split('\n');
|
|
49
|
+
const stack = [{ obj: result, indent: -1 }];
|
|
50
|
+
|
|
51
|
+
for (const line of lines) {
|
|
52
|
+
if (line.trim() === '' || line.trim().startsWith('#')) continue;
|
|
53
|
+
|
|
54
|
+
const match = line.match(/^(\s*)([^:]+):\s*(.*)$/);
|
|
55
|
+
if (!match) continue;
|
|
56
|
+
|
|
57
|
+
const indent = match[1].length;
|
|
58
|
+
const key = match[2].trim();
|
|
59
|
+
let value = match[3].trim();
|
|
60
|
+
|
|
61
|
+
// Pop stack until we find parent
|
|
62
|
+
while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
|
|
63
|
+
stack.pop();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const parent = stack[stack.length - 1].obj;
|
|
67
|
+
|
|
68
|
+
if (value === '' || value === null) {
|
|
69
|
+
// Nested object
|
|
70
|
+
parent[key] = {};
|
|
71
|
+
stack.push({ obj: parent[key], indent: indent });
|
|
72
|
+
} else {
|
|
73
|
+
// Parse value
|
|
74
|
+
if (value === 'true') value = true;
|
|
75
|
+
else if (value === 'false') value = false;
|
|
76
|
+
else if (value === 'null') value = null;
|
|
77
|
+
else if (!isNaN(value)) value = Number(value);
|
|
78
|
+
else if (value.startsWith('"') && value.endsWith('"')) value = value.slice(1, -1);
|
|
79
|
+
else if (value.startsWith('[') && value.endsWith(']')) {
|
|
80
|
+
value = value.slice(1, -1).split(',').map(s => s.trim());
|
|
81
|
+
}
|
|
82
|
+
parent[key] = value;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Stringify to YAML
|
|
91
|
+
*/
|
|
92
|
+
function stringifyYaml(obj, indent = 0) {
|
|
93
|
+
let result = '';
|
|
94
|
+
const prefix = ' '.repeat(indent);
|
|
95
|
+
|
|
96
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
97
|
+
if (value === null) {
|
|
98
|
+
result += `${prefix}${key}: null\n`;
|
|
99
|
+
} else if (typeof value === 'object' && !Array.isArray(value)) {
|
|
100
|
+
result += `${prefix}${key}:\n`;
|
|
101
|
+
result += stringifyYaml(value, indent + 1);
|
|
102
|
+
} else if (Array.isArray(value)) {
|
|
103
|
+
result += `${prefix}${key}: [${value.join(', ')}]\n`;
|
|
104
|
+
} else if (typeof value === 'string') {
|
|
105
|
+
result += `${prefix}${key}: "${value}"\n`;
|
|
106
|
+
} else {
|
|
107
|
+
result += `${prefix}${key}: ${value}\n`;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Deep merge objects
|
|
116
|
+
*/
|
|
117
|
+
function deepMerge(target, source) {
|
|
118
|
+
const result = { ...target };
|
|
119
|
+
|
|
120
|
+
for (const key of Object.keys(source)) {
|
|
121
|
+
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
|
122
|
+
result[key] = deepMerge(target[key] || {}, source[key]);
|
|
123
|
+
} else {
|
|
124
|
+
result[key] = source[key];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Load config from target directory
|
|
133
|
+
*/
|
|
134
|
+
function loadConfig(targetDir) {
|
|
135
|
+
const configPath = path.join(targetDir, '.cursor', CONFIG_FILENAME);
|
|
136
|
+
|
|
137
|
+
if (!fs.existsSync(configPath)) {
|
|
138
|
+
return DEFAULT_CONFIG;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
143
|
+
const userConfig = parseYaml(content);
|
|
144
|
+
return deepMerge(DEFAULT_CONFIG, userConfig);
|
|
145
|
+
} catch (e) {
|
|
146
|
+
console.warn(`Warning: Could not parse config: ${e.message}`);
|
|
147
|
+
return DEFAULT_CONFIG;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Save config to target directory
|
|
153
|
+
*/
|
|
154
|
+
function saveConfig(targetDir, config) {
|
|
155
|
+
const cursorDir = path.join(targetDir, '.cursor');
|
|
156
|
+
const configPath = path.join(cursorDir, CONFIG_FILENAME);
|
|
157
|
+
|
|
158
|
+
if (!fs.existsSync(cursorDir)) {
|
|
159
|
+
fs.mkdirSync(cursorDir, { recursive: true });
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const header = `# anchi-kit Configuration
|
|
163
|
+
# https://github.com/ANCHI-STE/anchi-webkit-dev
|
|
164
|
+
# ═══════════════════════════════════════════════════════════════
|
|
165
|
+
|
|
166
|
+
`;
|
|
167
|
+
|
|
168
|
+
fs.writeFileSync(configPath, header + stringifyYaml(config));
|
|
169
|
+
return configPath;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Get config value by path (e.g., 'features.auto_commit')
|
|
174
|
+
*/
|
|
175
|
+
function getConfigValue(config, keyPath) {
|
|
176
|
+
return keyPath.split('.').reduce((obj, key) => obj?.[key], config);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Set config value by path
|
|
181
|
+
*/
|
|
182
|
+
function setConfigValue(config, keyPath, value) {
|
|
183
|
+
const keys = keyPath.split('.');
|
|
184
|
+
const lastKey = keys.pop();
|
|
185
|
+
const target = keys.reduce((obj, key) => obj[key] = obj[key] || {}, config);
|
|
186
|
+
target[lastKey] = value;
|
|
187
|
+
return config;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
module.exports = {
|
|
191
|
+
DEFAULT_CONFIG,
|
|
192
|
+
CONFIG_FILENAME,
|
|
193
|
+
loadConfig,
|
|
194
|
+
saveConfig,
|
|
195
|
+
parseYaml,
|
|
196
|
+
stringifyYaml,
|
|
197
|
+
deepMerge,
|
|
198
|
+
getConfigValue,
|
|
199
|
+
setConfigValue,
|
|
200
|
+
};
|
package/docs/PROJECT_SUMMARY.md
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# 📋 Project Summary - Executive View
|
|
2
|
-
|
|
3
|
-
> **Auto-generated by `/summary`** | Last updated: [DATE]
|
|
4
|
-
>
|
|
5
|
-
> 🎯 Quick overview for stakeholders. Chi tiết xem files bên dưới.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## 🎯 Project At a Glance
|
|
10
|
-
|
|
11
|
-
| Field | Value |
|
|
12
|
-
|-------|-------|
|
|
13
|
-
| **Name** | [Project Name] |
|
|
14
|
-
| **Status** | ⬜ Dev / 🔄 Staging / ✅ Production |
|
|
15
|
-
| **Version** | [0.0.0] |
|
|
16
|
-
| **Preset** | 🚀 Rapid / 🏢 Professional / 🏛️ Enterprise |
|
|
17
|
-
|
|
18
|
-
**Description:** [Mô tả 1 câu về dự án]
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
## � Progress Overview
|
|
23
|
-
|
|
24
|
-
| Total Features | Done | In Progress | Planned |
|
|
25
|
-
|----------------|------|-------------|---------|
|
|
26
|
-
| [X] | [X] ✅ | [X] 🔄 | [X] ⬜ |
|
|
27
|
-
|
|
28
|
-
### Current Sprint/Milestone
|
|
29
|
-
- 🎯 **Goal:** [Current goal]
|
|
30
|
-
- 📅 **Deadline:** [Date]
|
|
31
|
-
- 📈 **Progress:** [X%]
|
|
32
|
-
|
|
33
|
-
---
|
|
34
|
-
|
|
35
|
-
## � Quick Links
|
|
36
|
-
|
|
37
|
-
| Resource | Link |
|
|
38
|
-
|----------|------|
|
|
39
|
-
| 📖 **Planning Details** | [project-overview-pdr.md](./project-overview-pdr.md) |
|
|
40
|
-
| 💻 **Technical Details** | [codebase-summary.md](./codebase-summary.md) |
|
|
41
|
-
| �️ **Roadmap** | [project-roadmap.md](./project-roadmap.md) |
|
|
42
|
-
| 📏 **Code Standards** | [code-standards.md](./code-standards.md) |
|
|
43
|
-
| 🏗️ **Architecture** | [system-architecture.md](./system-architecture.md) |
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## 📈 Key Metrics
|
|
48
|
-
|
|
49
|
-
| Metric | Value | Target |
|
|
50
|
-
|--------|-------|--------|
|
|
51
|
-
| Features Done | [X/Y] | 100% |
|
|
52
|
-
| Test Coverage | [X%] | 80% |
|
|
53
|
-
| API Endpoints | [X] | - |
|
|
54
|
-
| DB Models | [X] | - |
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## � Blockers & Risks
|
|
59
|
-
|
|
60
|
-
| Issue | Impact | Owner |
|
|
61
|
-
|-------|--------|-------|
|
|
62
|
-
| [Blocker 1] | High | [Name] |
|
|
63
|
-
| [Risk 1] | Medium | [Name] |
|
|
64
|
-
|
|
65
|
-
---
|
|
66
|
-
|
|
67
|
-
## 👥 Contacts
|
|
68
|
-
|
|
69
|
-
| Role | Person |
|
|
70
|
-
|------|--------|
|
|
71
|
-
| Team Lead | [Name] |
|
|
72
|
-
| Tech Lead | [Name] |
|
|
73
|
-
|
|
74
|
-
---
|
|
75
|
-
|
|
76
|
-
## 📝 Recent Updates
|
|
77
|
-
|
|
78
|
-
| Date | Update |
|
|
79
|
-
|------|--------|
|
|
80
|
-
| [Date] | [Summary] |
|
|
81
|
-
|
|
82
|
-
---
|
|
83
|
-
|
|
84
|
-
> 💡 **Navigation:**
|
|
85
|
-
> - **Planning (WHY/WHAT):** [project-overview-pdr.md](./project-overview-pdr.md)
|
|
86
|
-
> - **Technical (HOW):** [codebase-summary.md](./codebase-summary.md)
|
|
File without changes
|
|
File without changes
|