ai-developer-skill-os 8.1.9 → 8.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.
- package/.agents/CHANGELOG.md +18 -0
- package/.agents/README.md +17 -13
- package/.agents/blueprints/coding/project.yaml.tpl +39 -0
- package/.agents/blueprints/rag/project.yaml.tpl +45 -0
- package/.agents/blueprints/workflow/project.yaml.tpl +38 -0
- package/.agents/knowledge/domain-patterns/construction/ddc-construction-ai-blueprint.md +103 -0
- package/.agents/registry/graph.json +526 -0
- package/.agents/registry/index.yaml +259 -0
- package/.agents/skills/_template/capability.yaml +20 -0
- package/.agents/skills/_template/evals/scorecard.yaml +19 -0
- package/.agents/skills/qk-agent-observability/SKILL.md +11 -0
- package/.agents/skills/qk-ai-builder/SKILL.md +13 -10
- package/.agents/skills/qk-project-bootstrap/SKILL.md +55 -51
- package/.agents/skills/qk-validation-gate/SKILL.md +15 -8
- package/CHANGELOG.md +18 -0
- package/README.md +17 -13
- package/bin/install.js +39 -1
- package/package.json +9 -4
- package/tooling/build-registry.js +186 -0
package/bin/install.js
CHANGED
|
@@ -71,7 +71,7 @@ function runInstall(ideChoice, scopeChoice) {
|
|
|
71
71
|
if (isGlobal) {
|
|
72
72
|
const homeDir = os.homedir();
|
|
73
73
|
if (ide === 'antigravity') {
|
|
74
|
-
targetDir = path.join(homeDir, '.gemini', 'config'
|
|
74
|
+
targetDir = path.join(homeDir, '.gemini', 'config');
|
|
75
75
|
} else {
|
|
76
76
|
targetDir = path.join(homeDir, '.ai-developer-skill-os', '.agents');
|
|
77
77
|
}
|
|
@@ -87,6 +87,44 @@ function runInstall(ideChoice, scopeChoice) {
|
|
|
87
87
|
if (fs.existsSync(sourceDir)) {
|
|
88
88
|
copyRecursiveSync(sourceDir, targetDir);
|
|
89
89
|
console.log(`✅ Đã copy toàn bộ kiến trúc .agents vào: ${targetDir}`);
|
|
90
|
+
|
|
91
|
+
if (isGlobal && ide === 'antigravity') {
|
|
92
|
+
const targetDirPosix = targetDir.replace(/\\/g, '/');
|
|
93
|
+
|
|
94
|
+
function walkAndReplace(dir) {
|
|
95
|
+
const files = fs.readdirSync(dir);
|
|
96
|
+
for (const file of files) {
|
|
97
|
+
const fullPath = path.join(dir, file);
|
|
98
|
+
if (fs.statSync(fullPath).isDirectory()) {
|
|
99
|
+
walkAndReplace(fullPath);
|
|
100
|
+
} else if (fullPath.endsWith('.md') || fullPath.endsWith('.yml') || fullPath.endsWith('.yaml') || fullPath.endsWith('.json')) {
|
|
101
|
+
let content = fs.readFileSync(fullPath, 'utf8');
|
|
102
|
+
let modified = false;
|
|
103
|
+
|
|
104
|
+
const dirsToRewrite = ['skills', 'registry', 'rules', 'workflows', 'knowledge', 'examples', 'docs'];
|
|
105
|
+
for (const d of dirsToRewrite) {
|
|
106
|
+
const regex = new RegExp(`\\.agents/${d}`, 'g');
|
|
107
|
+
if (regex.test(content)) {
|
|
108
|
+
content = content.replace(regex, `${targetDirPosix}/${d}`);
|
|
109
|
+
modified = true;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (content.includes('.agents/skills.json')) {
|
|
114
|
+
content = content.replace(/\.agents\/skills\.json/g, `${targetDirPosix}/skills.json`);
|
|
115
|
+
modified = true;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (modified) {
|
|
119
|
+
fs.writeFileSync(fullPath, content, 'utf8');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
walkAndReplace(targetDir);
|
|
126
|
+
console.log(`✅ Đã cập nhật đường dẫn tuyệt đối cho cấu hình Global Antigravity`);
|
|
127
|
+
}
|
|
90
128
|
} else {
|
|
91
129
|
console.error(`❌ Lỗi: Không tìm thấy thư mục nguồn ${sourceDir}`);
|
|
92
130
|
return;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-developer-skill-os",
|
|
3
|
-
"version": "8.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "8.2.0",
|
|
4
|
+
"description": "EDAOS v8.2 — Governed Capability Metadata & Eval Platform: Blueprints organize, manifests govern, registries accelerate.",
|
|
5
5
|
"main": "bin/install.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"bin",
|
|
@@ -20,9 +20,10 @@
|
|
|
20
20
|
"node": ">=18.0.0"
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
|
+
"build:registry": "node tooling/build-registry.js",
|
|
23
24
|
"test": "vitest run",
|
|
24
25
|
"test:watch": "vitest",
|
|
25
|
-
"test:registry": "vitest run
|
|
26
|
+
"test:registry": "vitest run && node tooling/build-registry.js",
|
|
26
27
|
"test:graph": "node tooling/validate-graph.js",
|
|
27
28
|
"lint": "node bin/lint.js",
|
|
28
29
|
"test:agent": "node tests/agent-evaluation/runner/evaluate-routing.js",
|
|
@@ -49,7 +50,11 @@
|
|
|
49
50
|
"developer",
|
|
50
51
|
"agent",
|
|
51
52
|
"prompts",
|
|
52
|
-
"framework"
|
|
53
|
+
"framework",
|
|
54
|
+
"edaos",
|
|
55
|
+
"manifest",
|
|
56
|
+
"registry",
|
|
57
|
+
"eval"
|
|
53
58
|
],
|
|
54
59
|
"author": "Quang Khánh",
|
|
55
60
|
"license": "MIT",
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* build-registry.js
|
|
3
|
+
* V8.2 Governed Capability Metadata & Eval Platform
|
|
4
|
+
* Generates registry/index.yaml (lightweight lookup) and registry/graph.json (O(1) graph & cycle check)
|
|
5
|
+
*
|
|
6
|
+
* Usage: node tooling/build-registry.js
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import { fileURLToPath } from 'url';
|
|
12
|
+
import yaml from 'js-yaml';
|
|
13
|
+
|
|
14
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
|
|
16
|
+
const SKILLS_DIR = path.join(__dirname, '../.agents/skills');
|
|
17
|
+
const REGISTRY_DIR = path.join(__dirname, '../.agents/registry');
|
|
18
|
+
const INDEX_YAML = path.join(REGISTRY_DIR, 'index.yaml');
|
|
19
|
+
const GRAPH_JSON = path.join(REGISTRY_DIR, 'graph.json');
|
|
20
|
+
|
|
21
|
+
function parseYamlFile(filePath) {
|
|
22
|
+
try {
|
|
23
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
24
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
25
|
+
if (match) {
|
|
26
|
+
return yaml.load(match[1]);
|
|
27
|
+
}
|
|
28
|
+
return yaml.load(content);
|
|
29
|
+
} catch (e) {
|
|
30
|
+
console.error(`[WARN] Failed to parse YAML from ${filePath}: ${e.message}`);
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function buildRegistry() {
|
|
36
|
+
console.log('🔄 Building V8.2 Governed Capability Registry & O(1) Runtime Graph...');
|
|
37
|
+
|
|
38
|
+
if (!fs.existsSync(SKILLS_DIR)) {
|
|
39
|
+
console.error('❌ Skills directory not found:', SKILLS_DIR);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
fs.mkdirSync(REGISTRY_DIR, { recursive: true });
|
|
44
|
+
|
|
45
|
+
const dirs = fs.readdirSync(SKILLS_DIR).filter(d =>
|
|
46
|
+
!d.startsWith('_') && fs.statSync(path.join(SKILLS_DIR, d)).isDirectory()
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const capabilities = {};
|
|
50
|
+
const adjacency = {};
|
|
51
|
+
const reverseAdjacency = {};
|
|
52
|
+
|
|
53
|
+
for (const dir of dirs) {
|
|
54
|
+
const capYamlPath = path.join(SKILLS_DIR, dir, 'capability.yaml');
|
|
55
|
+
const skillMdPath = path.join(SKILLS_DIR, dir, 'SKILL.md');
|
|
56
|
+
|
|
57
|
+
let meta = null;
|
|
58
|
+
let fromCapabilityYaml = false;
|
|
59
|
+
|
|
60
|
+
if (fs.existsSync(capYamlPath)) {
|
|
61
|
+
meta = parseYamlFile(capYamlPath);
|
|
62
|
+
fromCapabilityYaml = true;
|
|
63
|
+
} else if (fs.existsSync(skillMdPath)) {
|
|
64
|
+
meta = parseYamlFile(skillMdPath);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (!meta) continue;
|
|
68
|
+
|
|
69
|
+
const id = meta.id || meta.name || dir;
|
|
70
|
+
const version = meta.version || '8.2.0';
|
|
71
|
+
const description = meta.description || '';
|
|
72
|
+
|
|
73
|
+
// Normalize tags
|
|
74
|
+
let tags = meta.tags || meta.keywords || [];
|
|
75
|
+
if (!Array.isArray(tags) || tags.length === 0) {
|
|
76
|
+
// Derive simple tags from dir words
|
|
77
|
+
tags = dir.replace(/^qk-/, '').split('-');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Normalize dependencies
|
|
81
|
+
let dependencies = meta.dependencies || [];
|
|
82
|
+
if (!fromCapabilityYaml) {
|
|
83
|
+
// Derive from V8.1 skill frontmatter decision_boundary / workflow
|
|
84
|
+
const deps = new Set();
|
|
85
|
+
if (meta.workflow && typeof meta.workflow === 'string') deps.add(meta.workflow);
|
|
86
|
+
if (meta.decision_boundary?.delegates_to) {
|
|
87
|
+
meta.decision_boundary.delegates_to.forEach(d => deps.add(d));
|
|
88
|
+
}
|
|
89
|
+
dependencies = Array.from(deps);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
capabilities[id] = {
|
|
93
|
+
path: `.agents/skills/${dir}`,
|
|
94
|
+
version,
|
|
95
|
+
tags,
|
|
96
|
+
dependencies
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
adjacency[id] = dependencies;
|
|
100
|
+
if (!reverseAdjacency[id]) reverseAdjacency[id] = [];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Populate reverse adjacency for orphan detection
|
|
104
|
+
for (const [id, deps] of Object.entries(adjacency)) {
|
|
105
|
+
for (const dep of deps) {
|
|
106
|
+
if (!reverseAdjacency[dep]) reverseAdjacency[dep] = [];
|
|
107
|
+
reverseAdjacency[dep].push(id);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Detect cycles using DFS
|
|
112
|
+
let hasCycles = false;
|
|
113
|
+
const visited = {};
|
|
114
|
+
const recursionStack = {};
|
|
115
|
+
|
|
116
|
+
function detectCycle(node) {
|
|
117
|
+
visited[node] = true;
|
|
118
|
+
recursionStack[node] = true;
|
|
119
|
+
|
|
120
|
+
const deps = adjacency[node] || [];
|
|
121
|
+
for (const dep of deps) {
|
|
122
|
+
if (!visited[dep]) {
|
|
123
|
+
if (detectCycle(dep)) return true;
|
|
124
|
+
} else if (recursionStack[dep]) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
recursionStack[node] = false;
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
for (const node of Object.keys(adjacency)) {
|
|
134
|
+
if (!visited[node]) {
|
|
135
|
+
if (detectCycle(node)) {
|
|
136
|
+
hasCycles = true;
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Build Graph JSON (O(1) Runtime lookups)
|
|
143
|
+
const graphNodes = {};
|
|
144
|
+
for (const [id, data] of Object.entries(capabilities)) {
|
|
145
|
+
const dependents = reverseAdjacency[id] || [];
|
|
146
|
+
const isOrphan = data.dependencies.length === 0 && dependents.length === 0 && id !== 'qk-orchestrator' && id !== 'qk-help';
|
|
147
|
+
|
|
148
|
+
graphNodes[id] = {
|
|
149
|
+
path: data.path,
|
|
150
|
+
version: data.version,
|
|
151
|
+
tags: data.tags,
|
|
152
|
+
dependencies: data.dependencies,
|
|
153
|
+
dependents,
|
|
154
|
+
is_orphan: isOrphan
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const graphJsonData = {
|
|
159
|
+
schema_version: 1,
|
|
160
|
+
manifest_version: '8.2',
|
|
161
|
+
generated_at: new Date().toISOString(),
|
|
162
|
+
nodes: graphNodes,
|
|
163
|
+
adjacency,
|
|
164
|
+
stats: {
|
|
165
|
+
total_capabilities: Object.keys(capabilities).length,
|
|
166
|
+
has_cycles: hasCycles
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// Build Registry Index YAML (Lightweight lookup)
|
|
171
|
+
const indexYamlContent = `# AUTO-GENERATED BY registry-builder (tooling/build-registry.js)\n# DO NOT EDIT MANUALLY. THIS IS A GENERATED RUNTIME ARTIFACT.\n` +
|
|
172
|
+
yaml.dump({
|
|
173
|
+
schema_version: 1,
|
|
174
|
+
manifest_version: '8.2',
|
|
175
|
+
generated_at: new Date().toISOString(),
|
|
176
|
+
capabilities
|
|
177
|
+
}, { indent: 2 });
|
|
178
|
+
|
|
179
|
+
fs.writeFileSync(INDEX_YAML, indexYamlContent, 'utf8');
|
|
180
|
+
fs.writeFileSync(GRAPH_JSON, JSON.stringify(graphJsonData, null, 2), 'utf8');
|
|
181
|
+
|
|
182
|
+
console.log(`✅ Generated lightweight registry index at .agents/registry/index.yaml (${Object.keys(capabilities).length} capabilities)`);
|
|
183
|
+
console.log(`✅ Generated O(1) adjacency graph at .agents/registry/graph.json (has_cycles: ${hasCycles})`);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
buildRegistry();
|