ai-developer-skill-os 7.0.2 → 7.5.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/AGENTS.md +44 -88
- package/.agents/CHANGELOG.md +70 -0
- package/.agents/LICENSE +21 -0
- package/.agents/README.md +100 -0
- package/.agents/docs/CHI_TIET_SKILLS.md +126 -0
- package/.agents/docs/GOVERNANCE.md +40 -0
- package/.agents/docs/HUONG_DAN_SU_DUNG.md +120 -0
- package/.agents/docs/SPEC.md +87 -0
- package/.agents/docs/adr/0001-intent-based-architecture.md +19 -0
- package/.agents/docs/adr/0002-kernel-freeze.md +21 -0
- package/.agents/docs/adr/0003-risk-based-verification.md +20 -0
- package/.agents/docs/adr/0004-progressive-evidence.md +19 -0
- package/.agents/docs/skill-classification.md +25 -0
- package/.agents/skills/qk-access-policy/SKILL.md +179 -0
- package/.agents/skills/qk-ai-builder/SKILL.md +215 -0
- package/.agents/skills/qk-api-lifecycle/SKILL.md +176 -0
- package/.agents/skills/qk-bug-resolution/SKILL.md +307 -0
- package/.agents/skills/qk-context-loader/SKILL.md +218 -0
- package/.agents/skills/qk-data-lifecycle/SKILL.md +192 -0
- package/.agents/skills/qk-db-optimizer/SKILL.md +196 -0
- package/.agents/skills/qk-docs/SKILL.md +198 -0
- package/.agents/skills/qk-engineering-standard/SKILL.md +351 -0
- package/.agents/skills/qk-engineering-standard/rules/backend.md +122 -0
- package/.agents/skills/qk-engineering-standard/rules/database.md +3 -0
- package/.agents/skills/qk-engineering-standard/rules/frontend.md +152 -0
- package/.agents/skills/qk-engineering-standard/rules/security.md +3 -0
- package/.agents/skills/qk-engineering-standard/rules/testing.md +3 -0
- package/.agents/skills/qk-fe-api-integration/SKILL.md +326 -0
- package/.agents/skills/qk-feature-delivery/SKILL.md +305 -0
- package/.agents/skills/qk-help/SKILL.md +193 -0
- package/.agents/skills/qk-orchestrator/SKILL.md +278 -0
- package/.agents/skills/qk-orchestrator/references/routing-table.md +78 -0
- package/.agents/skills/qk-production-release/SKILL.md +284 -0
- package/.agents/skills/qk-project-bootstrap/SKILL.md +235 -0
- package/.agents/skills/qk-project-health/SKILL.md +199 -0
- package/.agents/skills/qk-project-memory/SKILL.md +218 -0
- package/.agents/skills/qk-system-evolution/SKILL.md +281 -0
- package/.agents/skills/qk-ui-audit/SKILL.md +315 -0
- package/.agents/skills/qk-ui-audit/references/anti-slop-checklist.md +136 -0
- package/.agents/skills/qk-ui-builder/SKILL.md +446 -0
- package/.agents/skills/qk-ui-builder/references/anti-patterns.md +295 -0
- package/.agents/skills/qk-ui-builder/references/color.md +115 -0
- package/.agents/skills/qk-ui-builder/references/component-cookbook.md +1194 -0
- package/.agents/skills/qk-ui-builder/references/copy.md +250 -0
- package/.agents/skills/qk-ui-builder/references/interaction-and-states.md +115 -0
- package/.agents/skills/qk-ui-builder/references/layout-and-space.md +111 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/01-bento-grid.md +48 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/02-long-document.md +50 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/03-marquee-hero.md +51 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/04-stat-led.md +49 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/05-workbench.md +44 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/06-conversational-faq.md +50 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/07-manifesto.md +51 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/08-photographic.md +50 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/09-quote-led.md +50 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/11-catalogue.md +49 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/12-letter.md +49 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/13-index-first.md +49 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/14-narrative-workflow.md +48 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/15-split-studio.md +48 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/16-feature-stack.md +51 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/17-type-specimen.md +48 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/18-portfolio-grid.md +48 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/19-map-diagram.md +50 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/20-ecosystem-index.md +48 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures/21-component-playground.md +45 -0
- package/.agents/skills/qk-ui-builder/references/macrostructures.md +38 -0
- package/.agents/skills/qk-ui-builder/references/motion.md +95 -0
- package/.agents/skills/qk-ui-builder/references/responsive.md +115 -0
- package/.agents/skills/qk-ui-builder/references/slop-test.md +135 -0
- package/.agents/skills/qk-ui-builder/references/structure.md +280 -0
- package/.agents/skills/qk-ui-builder/references/themes/atmospheric.md +53 -0
- package/.agents/skills/qk-ui-builder/references/themes/carnival.md +52 -0
- package/.agents/skills/qk-ui-builder/references/themes/cobalt.md +52 -0
- package/.agents/skills/qk-ui-builder/references/themes/editorial.md +52 -0
- package/.agents/skills/qk-ui-builder/references/themes/garden.md +52 -0
- package/.agents/skills/qk-ui-builder/references/themes/hum.md +52 -0
- package/.agents/skills/qk-ui-builder/references/themes/lumen.md +52 -0
- package/.agents/skills/qk-ui-builder/references/themes/midnight.md +52 -0
- package/.agents/skills/qk-ui-builder/references/themes/modern-minimal.md +52 -0
- package/.agents/skills/qk-ui-builder/references/themes/playful.md +52 -0
- package/.agents/skills/qk-ui-builder/references/themes/specimen.md +52 -0
- package/.agents/skills/qk-ui-builder/references/themes/terminal.md +52 -0
- package/.agents/skills/qk-ui-builder/references/typography.md +129 -0
- package/.agents/skills/qk-ui-system-builder/SKILL.md +221 -0
- package/.agents/skills/qk-validation-gate/SKILL.md +359 -0
- package/.agents/skills.json +819 -0
- package/.github/workflows/ci.yml +1 -1
- package/CHANGELOG.md +2 -1
- package/CLAUDE.md +110 -0
- package/README.md +52 -10
- package/add_lang.js +21 -0
- package/add_lang.py +25 -0
- package/add_sections.py +53 -0
- package/bin/install.js +225 -170
- package/bin/lint.js +123 -0
- package/docs/CHI_TIET_SKILLS.md +27 -26
- package/docs/HUONG_DAN_SU_DUNG.md +3 -3
- package/docs/SPEC.md +70 -20
- package/framework/decision-primitives.md +2 -1
- package/framework/skill-schema.md +310 -0
- package/package.json +16 -5
- package/patch.js +15 -0
- package/patch.py +89 -0
- package/patch2.py +83 -0
- package/skills/_archive_old_skills/qk-accessibility-audit/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-agent-orchestrator/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-api-integration/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-auth-security/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-backend-architecture/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-bug-fix/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-component-generator/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-context-manager/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-database-engineer/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-deployment/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-design-system/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-form-builder/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-frontend-architecture/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-frontend-debug/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-frontend-performance/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-frontend-testing/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-git-engineer/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-help/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-migration/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-project-audit/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-refactor/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-state-management/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-table-crud-generator/SKILL.md +1 -0
- package/skills/_archive_old_skills/qk-ui-builder/SKILL.md +1 -0
- package/skills/_template/SKILL.md +239 -0
- package/skills/qk-access-policy/SKILL.md +180 -39
- package/skills/qk-ai-builder/SKILL.md +216 -40
- package/skills/qk-api-lifecycle/SKILL.md +177 -46
- package/skills/qk-bug-resolution/SKILL.md +308 -46
- package/skills/qk-context-loader/SKILL.md +219 -43
- package/skills/qk-data-lifecycle/SKILL.md +193 -44
- package/skills/qk-db-optimizer/SKILL.md +197 -41
- package/skills/qk-docs/SKILL.md +199 -40
- package/skills/qk-engineering-standard/SKILL.md +352 -42
- package/skills/qk-fe-api-integration/SKILL.md +327 -55
- package/skills/qk-feature-delivery/SKILL.md +306 -48
- package/skills/qk-help/SKILL.md +179 -23
- package/skills/qk-orchestrator/SKILL.md +279 -42
- package/skills/qk-orchestrator/references/routing-table.md +78 -0
- package/skills/qk-production-release/SKILL.md +285 -41
- package/skills/qk-project-bootstrap/SKILL.md +236 -38
- package/skills/qk-project-health/SKILL.md +200 -40
- package/skills/qk-project-memory/SKILL.md +219 -40
- package/skills/qk-system-evolution/SKILL.md +282 -40
- package/skills/qk-ui-audit/SKILL.md +316 -42
- package/skills/qk-ui-audit/references/anti-slop-checklist.md +136 -0
- package/skills/qk-ui-builder/SKILL.md +447 -0
- package/skills/qk-ui-builder/references/anti-patterns.md +295 -0
- package/skills/qk-ui-builder/references/color.md +115 -0
- package/skills/qk-ui-builder/references/component-cookbook.md +1194 -0
- package/skills/qk-ui-builder/references/copy.md +250 -0
- package/skills/qk-ui-builder/references/interaction-and-states.md +115 -0
- package/skills/qk-ui-builder/references/layout-and-space.md +111 -0
- package/skills/qk-ui-builder/references/macrostructures/01-bento-grid.md +48 -0
- package/skills/qk-ui-builder/references/macrostructures/02-long-document.md +50 -0
- package/skills/qk-ui-builder/references/macrostructures/03-marquee-hero.md +51 -0
- package/skills/qk-ui-builder/references/macrostructures/04-stat-led.md +49 -0
- package/skills/qk-ui-builder/references/macrostructures/05-workbench.md +44 -0
- package/skills/qk-ui-builder/references/macrostructures/06-conversational-faq.md +50 -0
- package/skills/qk-ui-builder/references/macrostructures/07-manifesto.md +51 -0
- package/skills/qk-ui-builder/references/macrostructures/08-photographic.md +50 -0
- package/skills/qk-ui-builder/references/macrostructures/09-quote-led.md +50 -0
- package/skills/qk-ui-builder/references/macrostructures/11-catalogue.md +49 -0
- package/skills/qk-ui-builder/references/macrostructures/12-letter.md +49 -0
- package/skills/qk-ui-builder/references/macrostructures/13-index-first.md +49 -0
- package/skills/qk-ui-builder/references/macrostructures/14-narrative-workflow.md +48 -0
- package/skills/qk-ui-builder/references/macrostructures/15-split-studio.md +48 -0
- package/skills/qk-ui-builder/references/macrostructures/16-feature-stack.md +51 -0
- package/skills/qk-ui-builder/references/macrostructures/17-type-specimen.md +48 -0
- package/skills/qk-ui-builder/references/macrostructures/18-portfolio-grid.md +48 -0
- package/skills/qk-ui-builder/references/macrostructures/19-map-diagram.md +50 -0
- package/skills/qk-ui-builder/references/macrostructures/20-ecosystem-index.md +48 -0
- package/skills/qk-ui-builder/references/macrostructures/21-component-playground.md +45 -0
- package/skills/qk-ui-builder/references/macrostructures.md +38 -0
- package/skills/qk-ui-builder/references/motion.md +95 -0
- package/skills/qk-ui-builder/references/responsive.md +115 -0
- package/skills/qk-ui-builder/references/slop-test.md +135 -0
- package/skills/qk-ui-builder/references/structure.md +280 -0
- package/skills/qk-ui-builder/references/themes/atmospheric.md +53 -0
- package/skills/qk-ui-builder/references/themes/carnival.md +52 -0
- package/skills/qk-ui-builder/references/themes/cobalt.md +52 -0
- package/skills/qk-ui-builder/references/themes/editorial.md +52 -0
- package/skills/qk-ui-builder/references/themes/garden.md +52 -0
- package/skills/qk-ui-builder/references/themes/hum.md +52 -0
- package/skills/qk-ui-builder/references/themes/lumen.md +52 -0
- package/skills/qk-ui-builder/references/themes/midnight.md +52 -0
- package/skills/qk-ui-builder/references/themes/modern-minimal.md +52 -0
- package/skills/qk-ui-builder/references/themes/playful.md +52 -0
- package/skills/qk-ui-builder/references/themes/specimen.md +52 -0
- package/skills/qk-ui-builder/references/themes/terminal.md +52 -0
- package/skills/qk-ui-builder/references/typography.md +129 -0
- package/skills/qk-ui-system-builder/SKILL.md +222 -43
- package/skills/qk-validation-gate/SKILL.md +360 -40
- package/skills.json +815 -825
- package/specs/fixtures/user-payload.json +12 -0
- package/specs/regressions/api-integration-null-fields.yaml +19 -0
- package/temp_fix.js +61 -0
- package/tests/registry.test.js +1 -1
- package/update_template.js +28 -0
- package/skills/qk-design-to-code/SKILL.md +0 -46
- package/skills/qk-policy-engine/SKILL.md +0 -39
package/bin/install.js
CHANGED
|
@@ -15,8 +15,13 @@ function copyRecursiveSync(src, dest) {
|
|
|
15
15
|
const exists = fs.existsSync(src);
|
|
16
16
|
const stats = exists && fs.statSync(src);
|
|
17
17
|
const isDirectory = exists && stats.isDirectory();
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
if (isDirectory) {
|
|
20
|
+
const dirName = path.basename(src);
|
|
21
|
+
if (dirName.startsWith('_')) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
20
25
|
if (!fs.existsSync(dest)) {
|
|
21
26
|
fs.mkdirSync(dest, { recursive: true });
|
|
22
27
|
}
|
|
@@ -69,7 +74,7 @@ function ensureKiloConfig(kiloJsonPath, kiloSkillsDir, kiloThemesDir, kiloComman
|
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
const skillPaths = [kiloSkillsDir];
|
|
72
|
-
if (!
|
|
77
|
+
if (!kiloConfig.skills || typeof kiloConfig.skills !== 'object' || !Array.isArray(kiloConfig.skills.paths)) {
|
|
73
78
|
kiloConfig.skills = { paths: skillPaths };
|
|
74
79
|
} else {
|
|
75
80
|
const exists = kiloConfig.skills.paths.some(p => path.resolve(p) === path.resolve(kiloSkillsDir));
|
|
@@ -82,38 +87,53 @@ function ensureKiloConfig(kiloJsonPath, kiloSkillsDir, kiloThemesDir, kiloComman
|
|
|
82
87
|
return kiloJsonPath;
|
|
83
88
|
}
|
|
84
89
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const questionIde = `Vui lòng chọn IDE/AI Assistant bạn đang sử dụng:
|
|
93
|
-
(1) Cursor
|
|
94
|
-
(2) Windsurf
|
|
95
|
-
(3) Cline / Roo Code
|
|
96
|
-
(4) Antigravity / Gemini
|
|
97
|
-
(5) Codex
|
|
98
|
-
(6) Kilo Code
|
|
99
|
-
(7) Tất cả các IDE (Multi-IDE)
|
|
100
|
-
(0) Bỏ qua (Không tạo config tự động)
|
|
90
|
+
function parseArgs() {
|
|
91
|
+
const args = process.argv.slice(2);
|
|
92
|
+
const parsed = { ide: null, scope: null };
|
|
93
|
+
for (const arg of args) {
|
|
94
|
+
if (arg.startsWith('--ide=')) parsed.ide = arg.split('=')[1];
|
|
95
|
+
if (arg.startsWith('--scope=')) parsed.scope = arg.split('=')[1];
|
|
96
|
+
}
|
|
101
97
|
|
|
102
|
-
|
|
98
|
+
const aliasMap = {
|
|
99
|
+
'antigravity': '4',
|
|
100
|
+
'gemini': '4',
|
|
101
|
+
'cursor': '1',
|
|
102
|
+
'windsurf': '2',
|
|
103
|
+
'claude': '3',
|
|
104
|
+
'cliner': '3',
|
|
105
|
+
'roo': '3',
|
|
106
|
+
'codex': '5',
|
|
107
|
+
'kilo': '6',
|
|
108
|
+
'multi-ide': '7',
|
|
109
|
+
'all': '7'
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
if (parsed.ide && aliasMap[parsed.ide.toLowerCase()]) {
|
|
113
|
+
parsed.ide = aliasMap[parsed.ide.toLowerCase()];
|
|
114
|
+
}
|
|
103
115
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
(
|
|
107
|
-
|
|
116
|
+
if (args.includes('--antigravity')) {
|
|
117
|
+
parsed.ide = '4';
|
|
118
|
+
if (!parsed.scope) parsed.scope = '2';
|
|
119
|
+
}
|
|
120
|
+
if (args.includes('--cursor')) {
|
|
121
|
+
parsed.ide = '1';
|
|
122
|
+
if (!parsed.scope) parsed.scope = '2';
|
|
123
|
+
}
|
|
124
|
+
if (args.includes('--kilo')) {
|
|
125
|
+
parsed.ide = '6';
|
|
126
|
+
if (!parsed.scope) parsed.scope = '2';
|
|
127
|
+
}
|
|
108
128
|
|
|
109
|
-
|
|
129
|
+
return parsed;
|
|
130
|
+
}
|
|
110
131
|
|
|
111
|
-
|
|
132
|
+
function runInstall(ideCode, answerScope) {
|
|
112
133
|
let isGemini = false;
|
|
113
134
|
let isKilo = false;
|
|
114
135
|
let isMultiIde = false;
|
|
115
136
|
let ruleFileName = null;
|
|
116
|
-
const ideCode = answerIde.trim();
|
|
117
137
|
|
|
118
138
|
switch(ideCode) {
|
|
119
139
|
case '1': ruleFileName = '.cursorrules'; break;
|
|
@@ -126,70 +146,69 @@ rl.question(questionIde, (answerIde) => {
|
|
|
126
146
|
case '0': default: break;
|
|
127
147
|
}
|
|
128
148
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
149
|
+
const isGlobal = answerScope.trim() === '2';
|
|
150
|
+
|
|
151
|
+
const homeDir = os.homedir();
|
|
152
|
+
const cwd = process.cwd();
|
|
153
|
+
let targetDir = '';
|
|
154
|
+
let ruleFilePath = null;
|
|
155
|
+
let baseFolderForPrompt = '';
|
|
156
|
+
let kiloJsonPath = null;
|
|
157
|
+
let kiloSkillsDir = null;
|
|
158
|
+
let kiloThemesDir = null;
|
|
159
|
+
let kiloCommandsDir = null;
|
|
160
|
+
|
|
161
|
+
if (isMultiIde) {
|
|
162
|
+
targetDir = path.join(cwd, '.qk-ai-skill-os');
|
|
163
|
+
baseFolderForPrompt = './.qk-ai-skill-os';
|
|
164
|
+
ruleFilePath = path.join(cwd, 'CLAUDE.md');
|
|
165
|
+
if (!isGlobal) {
|
|
166
|
+
kiloSkillsDir = path.join(cwd, '.kilo', 'skills');
|
|
167
|
+
kiloThemesDir = path.join(cwd, '.kilo', 'themes');
|
|
168
|
+
kiloCommandsDir = path.join(cwd, '.kilo', 'command');
|
|
169
|
+
kiloJsonPath = path.join(cwd, 'kilo.json');
|
|
170
|
+
}
|
|
171
|
+
} else if (isGemini) {
|
|
172
|
+
if (isGlobal) {
|
|
173
|
+
targetDir = path.join(homeDir, '.gemini', 'config');
|
|
174
|
+
ruleFilePath = path.join(targetDir, 'AGENTS.md');
|
|
175
|
+
baseFolderForPrompt = path.join(targetDir, 'skills').replace(/\\/g, '/');
|
|
176
|
+
} else {
|
|
177
|
+
targetDir = path.join(cwd, '.agents');
|
|
178
|
+
ruleFilePath = path.join(cwd, '.agents', 'AGENTS.md');
|
|
179
|
+
baseFolderForPrompt = '.agents/skills';
|
|
180
|
+
}
|
|
181
|
+
} else if (isKilo) {
|
|
182
|
+
if (isGlobal) {
|
|
183
|
+
targetDir = path.join(homeDir, '.qk-ai-skill-os');
|
|
184
|
+
baseFolderForPrompt = targetDir.replace(/\\/g, '/');
|
|
185
|
+
kiloSkillsDir = path.join(homeDir, '.kilo', 'skills');
|
|
186
|
+
kiloThemesDir = path.join(homeDir, '.config', 'kilo', 'themes');
|
|
187
|
+
kiloCommandsDir = path.join(homeDir, '.config', 'kilo', 'command');
|
|
188
|
+
kiloJsonPath = path.join(homeDir, '.config', 'kilo', 'kilo.json');
|
|
189
|
+
} else {
|
|
143
190
|
targetDir = path.join(cwd, '.qk-ai-skill-os');
|
|
144
191
|
baseFolderForPrompt = './.qk-ai-skill-os';
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
ruleFilePath = path.join(targetDir, 'AGENTS.md');
|
|
156
|
-
baseFolderForPrompt = path.join(targetDir, 'skills').replace(/\\/g, '/');
|
|
157
|
-
} else {
|
|
158
|
-
targetDir = path.join(cwd, '.agents');
|
|
159
|
-
ruleFilePath = path.join(cwd, '.agents', 'AGENTS.md');
|
|
160
|
-
baseFolderForPrompt = '.agents/skills';
|
|
161
|
-
}
|
|
162
|
-
} else if (isKilo) {
|
|
163
|
-
if (isGlobal) {
|
|
164
|
-
targetDir = path.join(homeDir, '.qk-ai-skill-os');
|
|
165
|
-
baseFolderForPrompt = targetDir.replace(/\\/g, '/');
|
|
166
|
-
kiloSkillsDir = path.join(homeDir, '.kilo', 'skills');
|
|
167
|
-
kiloThemesDir = path.join(homeDir, '.config', 'kilo', 'themes');
|
|
168
|
-
kiloCommandsDir = path.join(homeDir, '.config', 'kilo', 'command');
|
|
169
|
-
kiloJsonPath = path.join(homeDir, '.config', 'kilo', 'kilo.json');
|
|
170
|
-
} else {
|
|
171
|
-
targetDir = path.join(cwd, '.qk-ai-skill-os');
|
|
172
|
-
baseFolderForPrompt = './.qk-ai-skill-os';
|
|
173
|
-
kiloSkillsDir = path.join(cwd, '.kilo', 'skills');
|
|
174
|
-
kiloThemesDir = path.join(cwd, '.kilo', 'themes');
|
|
175
|
-
kiloCommandsDir = path.join(cwd, '.kilo', 'command');
|
|
176
|
-
kiloJsonPath = path.join(cwd, 'kilo.json');
|
|
177
|
-
}
|
|
178
|
-
ruleFilePath = path.join(cwd, 'CLAUDE.md');
|
|
192
|
+
kiloSkillsDir = path.join(cwd, '.kilo', 'skills');
|
|
193
|
+
kiloThemesDir = path.join(cwd, '.kilo', 'themes');
|
|
194
|
+
kiloCommandsDir = path.join(cwd, '.kilo', 'command');
|
|
195
|
+
kiloJsonPath = path.join(cwd, 'kilo.json');
|
|
196
|
+
}
|
|
197
|
+
ruleFilePath = path.join(cwd, 'CLAUDE.md');
|
|
198
|
+
} else {
|
|
199
|
+
if (isGlobal) {
|
|
200
|
+
targetDir = path.join(homeDir, '.qk-ai-skill-os');
|
|
201
|
+
baseFolderForPrompt = targetDir.replace(/\\/g, '/');
|
|
179
202
|
} else {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
baseFolderForPrompt = './.qk-ai-skill-os';
|
|
186
|
-
}
|
|
187
|
-
if (ruleFileName) {
|
|
188
|
-
ruleFilePath = path.join(cwd, ruleFileName);
|
|
189
|
-
}
|
|
203
|
+
targetDir = path.join(cwd, '.qk-ai-skill-os');
|
|
204
|
+
baseFolderForPrompt = './.qk-ai-skill-os';
|
|
205
|
+
}
|
|
206
|
+
if (ruleFileName) {
|
|
207
|
+
ruleFilePath = path.join(cwd, ruleFileName);
|
|
190
208
|
}
|
|
209
|
+
}
|
|
191
210
|
|
|
192
|
-
|
|
211
|
+
const systemPrompt = `[Role]
|
|
193
212
|
You are an elite AI Software Engineer. You must strictly follow the rules in this project.
|
|
194
213
|
Vui lòng tìm đọc danh sách kỹ năng tại file \`${baseFolderForPrompt}/skills.json\`.
|
|
195
214
|
|
|
@@ -202,7 +221,7 @@ Khi nhận được lệnh kỹ năng, bạn BẮT BUỘC phải:
|
|
|
202
221
|
2. TỰ ĐỘNG THỰC THI (End-to-End): Dùng các tools của bạn (đọc file, sửa code, chạy lệnh) để tự động hoàn thành 100% mục tiêu được giao. KHÔNG ĐƯỢC dừng lại để hỏi ý kiến trừ khi gặp lỗi chí mạng hoặc requirement quá mập mờ.
|
|
203
222
|
3. BÁO CÁO KẾT QUẢ: Sau khi hoàn tất sửa code, LUÔN trả về báo cáo theo đúng format markdown dưới đây:
|
|
204
223
|
|
|
205
|
-
|
|
224
|
+
\`\`\`markdown
|
|
206
225
|
🔧 <Tên Kỹ Năng> Summary
|
|
207
226
|
─────────────────────────────────────────────────
|
|
208
227
|
Scope: [Tóm tắt ngắn gọn phạm vi công việc]
|
|
@@ -223,114 +242,150 @@ Changes applied:
|
|
|
223
242
|
|
|
224
243
|
⚠️ Notes:
|
|
225
244
|
[Các lưu ý đặc biệt, rủi ro tiềm ẩn hoặc cách người dùng có thể test lại tính năng này]
|
|
226
|
-
|
|
245
|
+
\`\`\`
|
|
227
246
|
|
|
228
247
|
[Command Arguments]
|
|
229
|
-
Người dùng có thể truyền thêm tham số vào lệnh (ví dụ: \`./qk-ui-builder --fw=react --css=tailwind\`).
|
|
248
|
+
Người dùng có thể truyền thêm tham số vào lệnh (ví dụ: \`./qk-ui-builder --fw=react --css=tailwind\`).
|
|
230
249
|
Nếu người dùng sử dụng tham số (argument), bạn BẮT BUỘC phải tuân thủ tuyệt đối các công nghệ/yêu cầu được chỉ định trong tham số đó thay vì dùng mặc định.`;
|
|
231
250
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
251
|
+
try {
|
|
252
|
+
if (!fs.existsSync(targetDir)) {
|
|
253
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
254
|
+
}
|
|
236
255
|
|
|
237
|
-
|
|
238
|
-
|
|
256
|
+
const targetSkillsDir = path.join(targetDir, 'skills');
|
|
257
|
+
cleanOldSkills(targetSkillsDir, isGemini && isGlobal);
|
|
239
258
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
259
|
+
const filesAndFolders = [
|
|
260
|
+
'skills', '_template', 'docs', 'skills.json', 'README.md', 'CHANGELOG.md', 'LICENSE'
|
|
261
|
+
];
|
|
243
262
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
248
|
-
if (fs.existsSync(path.join(sourceDir, 'skills.json'))) {
|
|
249
|
-
fs.copyFileSync(path.join(sourceDir, 'skills.json'), path.join(targetDir, 'skills', 'skills.json'));
|
|
250
|
-
}
|
|
251
|
-
} else {
|
|
252
|
-
filesAndFolders.forEach(item => {
|
|
253
|
-
const src = path.join(sourceDir, item);
|
|
254
|
-
let dest = path.join(targetDir, item);
|
|
255
|
-
if (fs.existsSync(src)) {
|
|
256
|
-
copyRecursiveSync(src, dest);
|
|
257
|
-
}
|
|
258
|
-
});
|
|
263
|
+
if (isGemini && isGlobal) {
|
|
264
|
+
if (fs.existsSync(path.join(sourceDir, 'skills'))) {
|
|
265
|
+
copyRecursiveSync(path.join(sourceDir, 'skills'), path.join(targetDir, 'skills'));
|
|
259
266
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
267
|
+
if (fs.existsSync(path.join(sourceDir, 'skills.json'))) {
|
|
268
|
+
fs.copyFileSync(path.join(sourceDir, 'skills.json'), path.join(targetDir, 'skills', 'skills.json'));
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
filesAndFolders.forEach(item => {
|
|
272
|
+
const src = path.join(sourceDir, item);
|
|
273
|
+
let dest = path.join(targetDir, item);
|
|
274
|
+
if (fs.existsSync(src)) {
|
|
275
|
+
copyRecursiveSync(src, dest);
|
|
265
276
|
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
266
279
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
280
|
+
if (ruleFilePath) {
|
|
281
|
+
const ruleDir = path.dirname(ruleFilePath);
|
|
282
|
+
if (ruleDir !== cwd && !fs.existsSync(ruleDir)) {
|
|
283
|
+
fs.mkdirSync(ruleDir, { recursive: true });
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
let writeContent = systemPrompt;
|
|
287
|
+
if (isGemini) {
|
|
288
|
+
writeContent = `\n<RULE[ai_skill_os]>\n---\ntrigger: always_on\n---\n${systemPrompt}\n</RULE[ai_skill_os]>\n`;
|
|
289
|
+
}
|
|
271
290
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
} else {
|
|
284
|
-
fs.appendFileSync(ruleFilePath, "\n\n" + writeContent);
|
|
285
|
-
console.log(`✅ Đã GHI THÊM cấu hình tự động vào file: ${ruleFilePath}`);
|
|
286
|
-
}
|
|
291
|
+
if (fs.existsSync(ruleFilePath)) {
|
|
292
|
+
const existingContent = fs.readFileSync(ruleFilePath, 'utf8');
|
|
293
|
+
const marker = isGemini ? '<RULE[ai_skill_os]>' : '[Role]\nYou are an elite AI Software Engineer.';
|
|
294
|
+
const markerIndex = existingContent.indexOf(marker);
|
|
295
|
+
if (markerIndex !== -1) {
|
|
296
|
+
const before = existingContent.substring(0, markerIndex);
|
|
297
|
+
const after = existingContent.substring(markerIndex).split('\n').slice(isGemini ? 2 : 1).join('\n');
|
|
298
|
+
const lastMarkerEnd = after.indexOf(isGemini ? '</RULE[ai_skill_os]>' : '[Trigger Mechanism]');
|
|
299
|
+
const actualAfter = lastMarkerEnd !== -1 ? after.substring(lastMarkerEnd + (isGemini ? 19 : 18)).trimStart() : after;
|
|
300
|
+
fs.writeFileSync(ruleFilePath, before + writeContent.trimStart() + (actualAfter ? '\n' + actualAfter : '') + '\n');
|
|
301
|
+
console.log(`✅ Đã CẬP NHẬT cấu hình tự động trong file: ${ruleFilePath}`);
|
|
287
302
|
} else {
|
|
288
|
-
fs.
|
|
289
|
-
console.log(`✅ Đã
|
|
303
|
+
fs.appendFileSync(ruleFilePath, "\n\n" + writeContent);
|
|
304
|
+
console.log(`✅ Đã GHI THÊM cấu hình tự động vào file: ${ruleFilePath}`);
|
|
290
305
|
}
|
|
306
|
+
} else {
|
|
307
|
+
fs.writeFileSync(ruleFilePath, writeContent);
|
|
308
|
+
console.log(`✅ Đã TẠO MỚI file cấu hình: ${ruleFilePath}`);
|
|
291
309
|
}
|
|
310
|
+
}
|
|
292
311
|
|
|
293
|
-
|
|
312
|
+
if (isKilo) {
|
|
313
|
+
ensureKiloConfig(kiloJsonPath, kiloSkillsDir, kiloThemesDir, kiloCommandsDir);
|
|
314
|
+
console.log(`✅ Đã cấu hình Kilo Code tại: ${kiloJsonPath}`);
|
|
315
|
+
console.log(` → Skills: ${kiloSkillsDir}`);
|
|
316
|
+
console.log(` → Themes: ${kiloThemesDir}`);
|
|
317
|
+
console.log(` → Commands: ${kiloCommandsDir}`);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (isMultiIde) {
|
|
321
|
+
if (kiloJsonPath && kiloSkillsDir) {
|
|
294
322
|
ensureKiloConfig(kiloJsonPath, kiloSkillsDir, kiloThemesDir, kiloCommandsDir);
|
|
295
|
-
console.log(`✅ Đã cấu hình Kilo Code tại: ${kiloJsonPath}`);
|
|
323
|
+
console.log(`✅ Đã cấu hình Kilo Code (Multi-IDE) tại: ${kiloJsonPath}`);
|
|
296
324
|
console.log(` → Skills: ${kiloSkillsDir}`);
|
|
297
325
|
console.log(` → Themes: ${kiloThemesDir}`);
|
|
298
326
|
console.log(` → Commands: ${kiloCommandsDir}`);
|
|
327
|
+
} else if (ruleFilePath) {
|
|
328
|
+
console.log(`✅ Đã tạo file cấu hình Multi-IDE: ${ruleFilePath}`);
|
|
299
329
|
}
|
|
330
|
+
}
|
|
300
331
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}
|
|
311
|
-
}
|
|
332
|
+
console.log(`\n🎉 HOÀN TẤT! Dữ liệu kỹ năng đã được lưu tại: ${targetDir}`);
|
|
333
|
+
if (isGlobal && !isGemini) {
|
|
334
|
+
const name = ruleFilePath ? path.basename(ruleFilePath) : 'CLAUDE.md';
|
|
335
|
+
console.log(`💡 Lưu ý: Kỹ năng đã được cài ở cấp độ máy tính (Global). File cấu hình cục bộ (${name}) ở dự án này đang trỏ thẳng về thư mục Global đó.`);
|
|
336
|
+
} else if (isGlobal && isGemini) {
|
|
337
|
+
console.log(`💡 Lưu ý: Antigravity đã được cài Global. Từ nay bạn mở BẤT KỲ DỰ ÁN NÀO trên máy tính này, Antigravity cũng sẽ tự động có đủ 22 kỹ năng mà không cần cài lại!`);
|
|
338
|
+
} else if (isKilo) {
|
|
339
|
+
console.log(`💡 Lưu ý: Kilo Code đã sẵn sàng. Dùng \`<leader>t\` hoặc \`/themes\` để xem, và \`/skills\` để xem danh sách skill đã cài.`);
|
|
340
|
+
}
|
|
312
341
|
|
|
313
|
-
|
|
314
|
-
if (
|
|
315
|
-
|
|
316
|
-
console.log(
|
|
317
|
-
} else if (isGlobal && isGemini) {
|
|
318
|
-
console.log(`💡 Lưu ý: Antigravity đã được cài Global. Từ nay bạn mở BẤT KỲ DỰ ÁN NÀO trên máy tính này, Antigravity cũng sẽ tự động có đủ 23 kỹ năng mà không cần cài lại!`);
|
|
319
|
-
} else if (isKilo) {
|
|
320
|
-
console.log(`💡 Lưu ý: Kilo Code đã sẵn sàng. Dùng \`<leader>t\` hoặc \`/themes\` để xem, và \`/skills\` để xem danh sách skill đã cài.`);
|
|
342
|
+
if (!isGemini && !isKilo && !isMultiIde) {
|
|
343
|
+
if (fs.existsSync(path.join(cwd, '.kilorules'))) {
|
|
344
|
+
fs.unlinkSync(path.join(cwd, '.kilorules'));
|
|
345
|
+
console.log(`🧹 Đã xoá file .kilorules cũ (không còn cần thiết).`);
|
|
321
346
|
}
|
|
347
|
+
}
|
|
322
348
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
}
|
|
349
|
+
} catch (error) {
|
|
350
|
+
console.error('❌ Có lỗi xảy ra trong quá trình cài đặt:', error.message);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
329
353
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
354
|
+
const args = parseArgs();
|
|
355
|
+
|
|
356
|
+
if (args.ide !== null && args.scope !== null) {
|
|
357
|
+
runInstall(args.ide, args.scope);
|
|
358
|
+
} else {
|
|
359
|
+
console.log('🚀 Đang chuẩn bị cài đặt AI Developer Skill OS...\n');
|
|
360
|
+
|
|
361
|
+
const questionIde = `Vui lòng chọn IDE/AI Assistant bạn đang sử dụng:
|
|
362
|
+
(1) Cursor
|
|
363
|
+
(2) Windsurf
|
|
364
|
+
(3) Cline / Roo Code
|
|
365
|
+
(4) Antigravity / Gemini
|
|
366
|
+
(5) Codex
|
|
367
|
+
(6) Kilo Code
|
|
368
|
+
(7) Tất cả các IDE (Multi-IDE)
|
|
369
|
+
(0) Bỏ qua (Không tạo config tự động)
|
|
370
|
+
|
|
371
|
+
Nhập số (0-7): `;
|
|
372
|
+
|
|
373
|
+
const questionScope = `
|
|
374
|
+
Bạn muốn cài đặt bộ kỹ năng ở đâu?
|
|
375
|
+
(1) Local (Gắn vào dự án hiện tại - Phù hợp làm việc nhóm)
|
|
376
|
+
(2) Global (Cài vào máy tính dùng chung cho mọi dự án - Dành cho cá nhân)
|
|
377
|
+
|
|
378
|
+
Nhập số (1-2): `;
|
|
379
|
+
|
|
380
|
+
const rl = readline.createInterface({
|
|
381
|
+
input: process.stdin,
|
|
382
|
+
output: process.stdout
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
rl.question(questionIde, (answerIde) => {
|
|
386
|
+
rl.question(questionScope, (answerScope) => {
|
|
333
387
|
rl.close();
|
|
334
|
-
|
|
388
|
+
runInstall(answerIde.trim(), answerScope.trim());
|
|
389
|
+
});
|
|
335
390
|
});
|
|
336
|
-
}
|
|
391
|
+
}
|
package/bin/lint.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
import matter from 'gray-matter';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
const skillsDir = path.join(__dirname, '..', 'skills');
|
|
11
|
+
|
|
12
|
+
const REQUIRED_FOR_ALL = [
|
|
13
|
+
'Preconditions',
|
|
14
|
+
'Scope',
|
|
15
|
+
'Non-Goals',
|
|
16
|
+
'Exit Codes',
|
|
17
|
+
'Handoff Contract'
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const REQUIRED_FOR_ACTION = [
|
|
21
|
+
'Workflow',
|
|
22
|
+
'Confidence Model',
|
|
23
|
+
'Evidence Format',
|
|
24
|
+
'Escalation Rules'
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const REQUIRED_FOR_EXECUTION = [
|
|
28
|
+
'Priority Order',
|
|
29
|
+
'Severity',
|
|
30
|
+
'Retry Policy'
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const ACTION_SKILLS = ['qk-bug-resolution', 'qk-feature-delivery', 'qk-fe-api-integration', 'qk-api-lifecycle', 'qk-data-lifecycle', 'qk-db-optimizer', 'qk-ui-builder', 'qk-ui-system-builder', 'qk-access-policy', 'qk-ai-builder', 'qk-system-evolution', 'qk-production-release', 'qk-project-bootstrap'];
|
|
34
|
+
const EXECUTION_SKILLS = ['qk-bug-resolution', 'qk-feature-delivery', 'qk-fe-api-integration', 'qk-api-lifecycle', 'qk-data-lifecycle', 'qk-db-optimizer', 'qk-ui-builder', 'qk-ui-system-builder', 'qk-access-policy', 'qk-ai-builder', 'qk-system-evolution', 'qk-production-release', 'qk-project-bootstrap', 'qk-engineering-standard', 'qk-validation-gate', 'qk-ui-audit', 'qk-project-health'];
|
|
35
|
+
|
|
36
|
+
const SKIP_LINT = ['qk-help'];
|
|
37
|
+
|
|
38
|
+
let hasErrors = false;
|
|
39
|
+
|
|
40
|
+
function lintSkill(skillPath, skillName) {
|
|
41
|
+
if (SKIP_LINT.includes(skillName)) {
|
|
42
|
+
console.log(`⏭️ [${skillName}] Skipped (reference skill)`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const content = fs.readFileSync(skillPath, 'utf8');
|
|
47
|
+
|
|
48
|
+
let parsed;
|
|
49
|
+
try {
|
|
50
|
+
parsed = matter(content);
|
|
51
|
+
} catch (e) {
|
|
52
|
+
console.error(`❌ [${skillName}] Frontmatter parsing failed: ${e.message}`);
|
|
53
|
+
hasErrors = true;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const frontmatter = parsed.data;
|
|
58
|
+
|
|
59
|
+
const requiredFrontmatter = ['name', 'category', 'version', 'description', 'platforms', 'execution_mode', 'cost', 'latency', 'risk', 'side_effects', 'produces', 'consumes', 'token_budget', 'exit_codes', 'schema_version', 'runtime_version', 'skill_version'];
|
|
60
|
+
|
|
61
|
+
for (const field of requiredFrontmatter) {
|
|
62
|
+
if (frontmatter[field] === undefined) {
|
|
63
|
+
console.error(`❌ [${skillName}] Missing frontmatter field: ${field}`);
|
|
64
|
+
hasErrors = true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const validPlatforms = ['antigravity', 'claude-code', 'cursor', 'windsurf', 'kilo-code'];
|
|
69
|
+
if (Array.isArray(frontmatter.platforms)) {
|
|
70
|
+
for (const p of frontmatter.platforms) {
|
|
71
|
+
if (!validPlatforms.includes(p)) {
|
|
72
|
+
console.error(`❌ [${skillName}] Invalid platform: ${p}`);
|
|
73
|
+
hasErrors = true;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!content.includes('> **Language rule:**')) {
|
|
79
|
+
console.error(`❌ [${skillName}] Missing Language Rule declaration.`);
|
|
80
|
+
hasErrors = true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const body = parsed.content;
|
|
84
|
+
const required = [...REQUIRED_FOR_ALL];
|
|
85
|
+
if (ACTION_SKILLS.includes(skillName)) {
|
|
86
|
+
required.push(...REQUIRED_FOR_ACTION);
|
|
87
|
+
}
|
|
88
|
+
if (EXECUTION_SKILLS.includes(skillName)) {
|
|
89
|
+
required.push(...REQUIRED_FOR_EXECUTION);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for (const section of required) {
|
|
93
|
+
const headingRegex = new RegExp(`^##\\s+${section}\\b`, 'm');
|
|
94
|
+
if (!headingRegex.test(body)) {
|
|
95
|
+
console.error(`❌ [${skillName}] Missing section: ## ${section}`);
|
|
96
|
+
hasErrors = true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
console.log('🔍 Running V7.5 Skill Schema Linting...');
|
|
102
|
+
|
|
103
|
+
const items = fs.readdirSync(skillsDir);
|
|
104
|
+
for (const item of items) {
|
|
105
|
+
if (item === '_template' || item === 'qk-policy-engine') continue;
|
|
106
|
+
|
|
107
|
+
const skillDir = path.join(skillsDir, item);
|
|
108
|
+
if (fs.statSync(skillDir).isDirectory() && item.startsWith('qk-')) {
|
|
109
|
+
const skillMdPath = path.join(skillDir, 'SKILL.md');
|
|
110
|
+
if (fs.existsSync(skillMdPath)) {
|
|
111
|
+
lintSkill(skillMdPath, item);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (hasErrors) {
|
|
117
|
+
console.error('\n💥 Linting failed. One or more skills do not comply with the V7.5 Runtime Standard.');
|
|
118
|
+
process.exit(1);
|
|
119
|
+
} else {
|
|
120
|
+
console.log('\n✅ All skills comply with V7.5 Runtime Standard!');
|
|
121
|
+
process.exit(0);
|
|
122
|
+
}
|
|
123
|
+
|