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/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', '.agents');
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.1.9",
4
- "description": "Agent Engineering OS: A deterministic capability graph, governance rules, and dynamic knowledge base for AI coding agents.",
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 --config vitest.config.js",
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();