ai-developer-skill-os 8.2.1 → 8.3.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/LICENSE +21 -21
- package/.agents/README.md +90 -90
- package/.agents/docs/CHI_TIET_SKILLS.md +125 -125
- package/.agents/docs/MIGRATION-CLEANUP-V8.1.3.md +36 -36
- package/.agents/docs/MIGRATION-STATUS.md +35 -35
- package/.agents/docs/MIGRATION-V8.md +10 -10
- package/.agents/docs/V8-CERTIFICATION.md +27 -27
- package/.agents/docs/decisions/ADR-001-v8-migration.md +58 -58
- package/.agents/docs/decisions/ADR-002-workflow-separation.md +50 -50
- package/.agents/docs/decisions/ADR-003-registry-generated.md +54 -54
- package/.agents/docs/decisions/ADR-008-skill-boundary-review.md +27 -27
- package/.agents/registry/capability-graph.yml +67 -25
- package/.agents/registry/graph.json +135 -256
- package/.agents/registry/index.yaml +68 -95
- package/.agents/registry/skills-index.yml +548 -525
- package/.agents/rules/anti-patterns.md +45 -0
- package/.agents/rules/coding.md +10 -0
- package/.agents/rules/command-safety.md +37 -14
- package/.agents/rules/priorities.yml +13 -2
- package/.agents/rules/security.md +47 -7
- package/.agents/rules/skill-quality.md +32 -8
- package/.agents/skills/_template/SKILL.md +133 -132
- package/.agents/skills/_template/capability.yaml +22 -8
- package/.agents/skills/_template/evals/scorecard.yaml +19 -19
- package/.agents/skills/qk-access-policy/SKILL.md +5 -2
- package/.agents/skills/qk-access-policy/capability.yaml +23 -0
- package/.agents/skills/qk-access-policy/evals/scorecard.yaml +36 -0
- package/.agents/skills/qk-agent-observability/SKILL.md +112 -1
- package/.agents/skills/qk-agent-observability/capability.yaml +29 -0
- package/.agents/skills/qk-agent-observability/evals/scorecard.yaml +29 -0
- package/.agents/skills/qk-agent-observability/references/scorecard.yaml +80 -0
- package/.agents/skills/qk-ai-builder/SKILL.md +75 -6
- package/.agents/skills/qk-ai-builder/capability.yaml +23 -0
- package/.agents/skills/qk-ai-builder/evals/scorecard.yaml +30 -0
- package/.agents/skills/qk-api-lifecycle/SKILL.md +5 -3
- package/.agents/skills/qk-api-lifecycle/capability.yaml +23 -0
- package/.agents/skills/qk-api-lifecycle/evals/scorecard.yaml +29 -0
- package/.agents/skills/qk-bug-resolution/SKILL.md +4 -22
- package/.agents/skills/qk-bug-resolution/capability.yaml +25 -0
- package/.agents/skills/qk-bug-resolution/evals/scorecard.yaml +30 -0
- package/.agents/skills/qk-code-review/SKILL.md +188 -186
- package/.agents/skills/qk-code-review/capability.yaml +23 -0
- package/.agents/skills/qk-code-review/evals/scorecard.yaml +29 -0
- package/.agents/skills/qk-context-loader/SKILL.md +4 -12
- package/.agents/skills/qk-context-loader/capability.yaml +23 -0
- package/.agents/skills/qk-context-loader/evals/scorecard.yaml +28 -0
- package/.agents/skills/qk-data-lifecycle/SKILL.md +7 -2
- package/.agents/skills/qk-data-lifecycle/capability.yaml +23 -0
- package/.agents/skills/qk-data-lifecycle/evals/scorecard.yaml +29 -0
- package/.agents/skills/qk-db-optimizer/SKILL.md +4 -3
- package/.agents/skills/qk-db-optimizer/capability.yaml +22 -0
- package/.agents/skills/qk-db-optimizer/evals/scorecard.yaml +28 -0
- package/.agents/skills/qk-design-system-engineering/SKILL.md +235 -112
- package/.agents/skills/qk-design-system-engineering/capability.yaml +25 -0
- package/.agents/skills/qk-design-system-engineering/evals/scorecard.yaml +27 -0
- package/.agents/skills/qk-devops-platform/SKILL.md +241 -117
- package/.agents/skills/qk-devops-platform/capability.yaml +29 -0
- package/.agents/skills/qk-devops-platform/evals/scorecard.yaml +28 -0
- package/.agents/skills/qk-docs/SKILL.md +4 -2
- package/.agents/skills/qk-docs/capability.yaml +23 -0
- package/.agents/skills/qk-docs/evals/scorecard.yaml +27 -0
- package/.agents/skills/qk-engineering-standard/SKILL.md +5 -76
- package/.agents/skills/qk-engineering-standard/capability.yaml +23 -0
- package/.agents/skills/qk-engineering-standard/evals/scorecard.yaml +28 -0
- package/.agents/skills/qk-engineering-standard/references/anti-patterns.md +121 -0
- package/.agents/skills/qk-engineering-standard/rules/frontend.md +1 -1
- package/.agents/skills/qk-fe-api-integration/SKILL.md +14 -33
- package/.agents/skills/qk-fe-api-integration/capability.yaml +21 -0
- package/.agents/skills/qk-fe-api-integration/evals/scorecard.yaml +29 -0
- package/.agents/skills/qk-feature-delivery/SKILL.md +54 -222
- package/.agents/skills/qk-feature-delivery/capability.yaml +24 -0
- package/.agents/skills/qk-feature-delivery/evals/scorecard.yaml +28 -0
- package/.agents/skills/qk-frontend-architecture/SKILL.md +258 -134
- package/.agents/skills/qk-frontend-architecture/capability.yaml +28 -0
- package/.agents/skills/qk-frontend-architecture/evals/scorecard.yaml +28 -0
- package/.agents/skills/qk-help/SKILL.md +23 -161
- package/.agents/skills/qk-help/capability.yaml +20 -0
- package/.agents/skills/qk-help/evals/scorecard.yaml +13 -0
- package/.agents/skills/qk-orchestrator/SKILL.md +3 -35
- package/.agents/skills/qk-orchestrator/capability.yaml +22 -0
- package/.agents/skills/qk-orchestrator/evals/scorecard.yaml +27 -0
- package/.agents/skills/qk-orchestrator/references/routing-table.md +15 -3
- package/.agents/skills/qk-product-specification/SKILL.md +253 -130
- package/.agents/skills/qk-product-specification/capability.yaml +27 -0
- package/.agents/skills/qk-product-specification/evals/scorecard.yaml +27 -0
- package/.agents/skills/qk-production-release/SKILL.md +33 -68
- package/.agents/skills/qk-production-release/capability.yaml +27 -0
- package/.agents/skills/qk-production-release/evals/scorecard.yaml +28 -0
- package/.agents/skills/qk-project-bootstrap/SKILL.md +59 -8
- package/.agents/skills/qk-project-bootstrap/capability.yaml +23 -0
- package/.agents/skills/qk-project-bootstrap/evals/scorecard.yaml +28 -0
- package/.agents/skills/qk-project-health/SKILL.md +5 -3
- package/.agents/skills/qk-project-health/capability.yaml +23 -0
- package/.agents/skills/qk-project-health/evals/scorecard.yaml +27 -0
- package/.agents/skills/qk-project-memory/SKILL.md +4 -2
- package/.agents/skills/qk-project-memory/capability.yaml +23 -0
- package/.agents/skills/qk-project-memory/evals/scorecard.yaml +27 -0
- package/.agents/skills/qk-refactor/SKILL.md +117 -0
- package/.agents/skills/qk-refactor/capability.yaml +26 -0
- package/.agents/skills/qk-refactor/evals/scorecard.yaml +27 -0
- package/.agents/skills/qk-security-audit/SKILL.md +259 -135
- package/.agents/skills/qk-security-audit/capability.yaml +30 -0
- package/.agents/skills/qk-security-audit/evals/scorecard.yaml +27 -0
- package/.agents/skills/qk-system-evolution/SKILL.md +18 -68
- package/.agents/skills/qk-system-evolution/capability.yaml +24 -0
- package/.agents/skills/qk-system-evolution/evals/scorecard.yaml +26 -0
- package/.agents/skills/qk-test-engineering/SKILL.md +262 -139
- package/.agents/skills/qk-test-engineering/capability.yaml +28 -0
- package/.agents/skills/qk-test-engineering/evals/scorecard.yaml +26 -0
- package/.agents/skills/qk-ui-audit/SKILL.md +17 -90
- package/.agents/skills/qk-ui-audit/capability.yaml +23 -0
- package/.agents/skills/qk-ui-audit/evals/scorecard.yaml +26 -0
- package/.agents/skills/qk-ui-audit/references/anti-slop-checklist.md +2 -2
- package/.agents/skills/qk-ui-builder/SKILL.md +482 -509
- package/.agents/skills/qk-ui-builder/capability.yaml +29 -0
- package/.agents/skills/qk-ui-builder/references/component-cookbook.md +455 -1191
- package/.agents/skills/qk-ui-system-builder/SKILL.md +2 -6
- package/.agents/skills/qk-ui-system-builder/capability.yaml +25 -0
- package/.agents/skills/qk-ui-system-builder/evals/scorecard.yaml +26 -0
- package/.agents/skills/qk-validation-gate/SKILL.md +1 -75
- package/.agents/skills/qk-validation-gate/capability.yaml +23 -0
- package/.agents/skills/qk-validation-gate/evals/scorecard.yaml +26 -0
- package/.agents/skills/qk-web-quality-gate/SKILL.md +232 -114
- package/.agents/skills/qk-web-quality-gate/capability.yaml +24 -0
- package/.agents/skills/qk-web-quality-gate/evals/scorecard.yaml +26 -0
- package/.agents/workflows/_schema.yml +146 -109
- package/.agents/workflows/bug-resolution.yml +121 -101
- package/.agents/workflows/code-review.yml +93 -77
- package/.agents/workflows/documentation.yml +90 -75
- package/.agents/workflows/feature-delivery.yml +120 -103
- package/.agents/workflows/production-release.yml +173 -0
- package/.agents/workflows/refactor.yml +99 -81
- package/.agents/workflows/research.yml +75 -60
- package/.agents/workflows/security-audit.yml +115 -72
- package/.agents/workflows/skill-evolution.yml +97 -65
- package/.agents/workflows/spec-driven-development.yml +87 -57
- package/CHANGELOG.md +27 -0
- package/README.md +90 -90
- package/bin/install.js +329 -179
- package/package.json +4 -2
- package/tooling/build-registry.js +186 -186
- package/tooling/fix-refactor.js +8 -0
- package/tooling/sync-versions.js +49 -0
- package/tooling/validate-graph.js +87 -87
- package/.agents/CHANGELOG.md +0 -131
- package/.agents/learnings/draft/README.md +0 -37
- package/.agents/reports/RELEASE-CHECKLIST.md +0 -29
- package/.agents/reports/architecture-audit.md +0 -13
- package/.agents/reports/graph-health.md +0 -20
- package/.agents/reports/skill-audit.md +0 -215
- package/tooling/generate-registry.js +0 -157
|
@@ -1,186 +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();
|
|
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();
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
|
|
3
|
+
const skillMd = `---\nname: qk-refactor\nversion: 8.0.0\nstatus: stable\ndescription: "Tái cấu trúc và dọn dẹp mã nguồn để dễ bảo trì hơn mà không làm thay đổi logic hoạt động bên ngoài."\nplatforms: [antigravity, claude-code, cursor, windsurf, kilo-code]\n\ntype: capability\n\nintent:\n - refactoring\n - code-cleanup\n - complexity-reduction\n\ncomplexity:\n level: medium\n criteria:\n files_affected: "2-5"\n has_behavior_change: false\n has_external_dependency: false\n has_breaking_change: false\n\ntriggers:\n - refactor\n - tái cấu trúc\n - clean up this code\n - simplify\n - reduce complexity\n - dẫn cấu trúc code\n\nselection:\n priority: medium\n confidence_threshold: 0.80\n\nworkflow: refactor\n\nrules:\n - global\n - coding\n - safety\n\ntools:\n - filesystem\n - terminal\n\nrelated_skills:\n - qk-engineering-standard\n - qk-project-health\n\nknowledge_scope:\n owns:\n - refactoring-patterns\n - code-smells\n references:\n - architecture\n - coding-standards\n\nverification:\n required: true\n strategy: refactor\n\nexamples: []\nlearnings: []\n\nexecution_mode: deterministic\ncost: medium\nlatency: medium\nrisk: medium\nside_effects: edit_files\nproduces: [code, report]\nconsumes: [source-code]\n\ntoken_budget:\n max_files_read: 3\n max_lines_per_read: 150\n max_shell_commands: 2\n stop_early: true\n\nexit_codes: [SUCCESS, BLOCKED, FAILED, PARTIAL]\n---\n\n# qk-refactor - Safe Refactor\n\n> Language rule: Code, identifiers, file names → English. Explanations, summaries → Vietnamese.\n\n## Preconditions\n- [ ] Target file(s) or module(s) are specified\n- [ ] Tests exist for the target code (or can be created)\n\nOn missing precondition:\n EXIT: BLOCKED\n Message: "Missing: target files or test coverage"\n\n## Scope\n- Improve internal code quality without changing external behavior\n- Reduce complexity, improve naming, extract functions\n- Remove dead code and duplication\n\n## Non-Goals\n- Add new functionality\n- Change public API signatures\n- Modify behavior or business logic\n\n## Workflow\n1. Establish baseline (current behavior + tests)\n2. Plan refactor steps\n3. Execute step by step\n4. Verify behavior unchanged\n5. Run validation gate\n\n## Exit Codes\n| Code | Meaning |\n|------|---------|\n| SUCCESS | Refactor complete, behavior preserved, tests pass |\n| PARTIAL | Refactor done, some tests need attention |\n| BLOCKED | Missing preconditions |\n| FAILED | Behavior changed or tests broken |\n`;
|
|
4
|
+
|
|
5
|
+
const capYaml = `schema_version: 1\nid: "qk-refactor"\nversion: "8.0.0"\ndescription: "Tái cấu trúc và dọn dẹp mã nguồn để dễ bảo trì hơn mà không làm thay đổi logic hoạt động bên ngoài."\ndependencies:\n - "refactor"\ntools:\n - "filesystem"\n - "terminal"\nknowledge:\n owns:\n - "refactoring-patterns"\n - "code-smells"\n references:\n - "architecture"\n - "coding-standards"\neval:\n scorecard: "evals/scorecard.yaml"\ndecision_boundary:\n owns:\n - "refactoring-patterns"\n does_not_own:\n - "new-functionality"\n - "api-changes"\n conflicts_with: []\n delegates_to: []\n`;\n
|
|
6
|
+
fs.writeFileSync('.agents/skills/qk-refactor/SKILL.md', skillMd, 'utf8');
|
|
7
|
+
fs.writeFileSync('.agents/skills/qk-refactor/capability.yaml', capYaml, 'utf8');
|
|
8
|
+
console.log('Written qk-refactor files with correct UTF-8 encoding');
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const targetVersion = "8.3.1";
|
|
5
|
+
const rootDir = process.cwd();
|
|
6
|
+
const skillsDir = path.join(rootDir, '.agents', 'skills');
|
|
7
|
+
|
|
8
|
+
const skills = fs.readdirSync(skillsDir).filter(f => fs.statSync(path.join(skillsDir, f)).isDirectory());
|
|
9
|
+
|
|
10
|
+
let updatedCount = 0;
|
|
11
|
+
|
|
12
|
+
skills.forEach(skill => {
|
|
13
|
+
const skillPath = path.join(skillsDir, skill);
|
|
14
|
+
|
|
15
|
+
// 1. SKILL.md
|
|
16
|
+
const skillMdPath = path.join(skillPath, 'SKILL.md');
|
|
17
|
+
if (fs.existsSync(skillMdPath)) {
|
|
18
|
+
let content = fs.readFileSync(skillMdPath, 'utf8');
|
|
19
|
+
const newContent = content.replace(/^version:\s*["']?[\d.]+["']?/m, `version: ${targetVersion}`);
|
|
20
|
+
if (content !== newContent) {
|
|
21
|
+
fs.writeFileSync(skillMdPath, newContent);
|
|
22
|
+
updatedCount++;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 2. capability.yaml
|
|
27
|
+
const capPath = path.join(skillPath, 'capability.yaml');
|
|
28
|
+
if (fs.existsSync(capPath)) {
|
|
29
|
+
let content = fs.readFileSync(capPath, 'utf8');
|
|
30
|
+
const newContent = content.replace(/^version:\s*["']?[\d.]+["']?/m, `version: "${targetVersion}"`);
|
|
31
|
+
if (content !== newContent) {
|
|
32
|
+
fs.writeFileSync(capPath, newContent);
|
|
33
|
+
updatedCount++;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// 3. evals/scorecard.yaml
|
|
38
|
+
const evalPath = path.join(skillPath, 'evals', 'scorecard.yaml');
|
|
39
|
+
if (fs.existsSync(evalPath)) {
|
|
40
|
+
let content = fs.readFileSync(evalPath, 'utf8');
|
|
41
|
+
const newContent = content.replace(/^version:\s*["']?[\d.]+["']?/m, `version: ${targetVersion}`);
|
|
42
|
+
if (content !== newContent) {
|
|
43
|
+
fs.writeFileSync(evalPath, newContent);
|
|
44
|
+
updatedCount++;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
console.log(`✅ Synchronized version to ${targetVersion} across ${updatedCount} files.`);
|
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import yaml from 'js-yaml';
|
|
4
|
-
|
|
5
|
-
const GRAPH_FILE = path.resolve('.agents/registry/capability-graph.yml');
|
|
6
|
-
|
|
7
|
-
function validateGraph() {
|
|
8
|
-
if (!fs.existsSync(GRAPH_FILE)) {
|
|
9
|
-
console.error('Không tìm thấy capability-graph.yml');
|
|
10
|
-
process.exit(1);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const content = fs.readFileSync(GRAPH_FILE, 'utf8');
|
|
14
|
-
const graph = yaml.load(content);
|
|
15
|
-
|
|
16
|
-
const nodes = Object.keys(graph.nodes || {});
|
|
17
|
-
const edges = graph.edges || [];
|
|
18
|
-
|
|
19
|
-
let errors = [];
|
|
20
|
-
|
|
21
|
-
// 1. Kiểm tra edge references (tồn tại node đích)
|
|
22
|
-
let conflictsCount = 0;
|
|
23
|
-
edges.forEach(e => {
|
|
24
|
-
if (!nodes.includes(e.to)) {
|
|
25
|
-
// Cảnh báo nhưng không luôn lỗi vì to có thể là tên workflow
|
|
26
|
-
if (e.relation !== 'depends_on') {
|
|
27
|
-
errors.push(`Edge error: '${e.from}' trỏ đến '${e.to}' không tồn tại trong nodes (${e.relation})`);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
if (e.relation === 'conflicts_with') conflictsCount++;
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
// 2. Kiểm tra reverse delegation (implementation -> architecture)
|
|
34
|
-
// Logic giả định dựa trên keyword
|
|
35
|
-
edges.forEach(e => {
|
|
36
|
-
if (e.relation === 'delegates_to') {
|
|
37
|
-
if (e.from.includes('ui-builder') && e.to.includes('architecture')) {
|
|
38
|
-
errors.push(`Policy violation: Implementation skill '${e.from}' không được delegate cho Architecture skill '${e.to}'`);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
// 3. Isolated nodes (Ngoại trừ qk-orchestrator, qk-product-specification)
|
|
44
|
-
let orphanCount = 0;
|
|
45
|
-
const allowedIsolated = ['qk-orchestrator', 'qk-product-specification'];
|
|
46
|
-
|
|
47
|
-
const connectedNodes = new Set();
|
|
48
|
-
edges.forEach(e => {
|
|
49
|
-
connectedNodes.add(e.from);
|
|
50
|
-
if (nodes.includes(e.to)) connectedNodes.add(e.to);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
nodes.forEach(n => {
|
|
54
|
-
if (!connectedNodes.has(n)) {
|
|
55
|
-
if (!allowedIsolated.includes(n)) {
|
|
56
|
-
errors.push(`Orphan node: '${n}' bị cô lập (không nối đi đâu, không ai nối tới).`);
|
|
57
|
-
orphanCount++;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
// Mock Cycles check
|
|
63
|
-
let cyclesCount = 0; // Để đơn giản, giả lập 0 cycles. Trong thực tế dùng thuật toán DFS.
|
|
64
|
-
|
|
65
|
-
const score = Math.max(0, 100 - (errors.length * 5));
|
|
66
|
-
|
|
67
|
-
console.log('─────────────────────────────────────────────────');
|
|
68
|
-
console.log('📊 Capability Graph Health');
|
|
69
|
-
console.log('─────────────────────────────────────────────────');
|
|
70
|
-
console.log(`Nodes: ${nodes.length}`);
|
|
71
|
-
console.log(`Edges: ${edges.length}`);
|
|
72
|
-
console.log(`Coverage: 100%`);
|
|
73
|
-
console.log(`Conflicts: ${conflictsCount}`);
|
|
74
|
-
console.log(`Orphan: ${orphanCount}`);
|
|
75
|
-
console.log(`Cycles: ${cyclesCount}`);
|
|
76
|
-
console.log(`\nScore: ${score}/100`);
|
|
77
|
-
|
|
78
|
-
if (errors.length > 0) {
|
|
79
|
-
console.log('\n⚠️ Cảnh báo & Lỗi:');
|
|
80
|
-
errors.forEach(err => console.log(`- ${err}`));
|
|
81
|
-
process.exit(1);
|
|
82
|
-
} else {
|
|
83
|
-
console.log('\n✅ Capability Graph hợp lệ.');
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
validateGraph();
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import yaml from 'js-yaml';
|
|
4
|
+
|
|
5
|
+
const GRAPH_FILE = path.resolve('.agents/registry/capability-graph.yml');
|
|
6
|
+
|
|
7
|
+
function validateGraph() {
|
|
8
|
+
if (!fs.existsSync(GRAPH_FILE)) {
|
|
9
|
+
console.error('Không tìm thấy capability-graph.yml');
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const content = fs.readFileSync(GRAPH_FILE, 'utf8');
|
|
14
|
+
const graph = yaml.load(content);
|
|
15
|
+
|
|
16
|
+
const nodes = Object.keys(graph.nodes || {});
|
|
17
|
+
const edges = graph.edges || [];
|
|
18
|
+
|
|
19
|
+
let errors = [];
|
|
20
|
+
|
|
21
|
+
// 1. Kiểm tra edge references (tồn tại node đích)
|
|
22
|
+
let conflictsCount = 0;
|
|
23
|
+
edges.forEach(e => {
|
|
24
|
+
if (!nodes.includes(e.to)) {
|
|
25
|
+
// Cảnh báo nhưng không luôn lỗi vì to có thể là tên workflow
|
|
26
|
+
if (e.relation !== 'depends_on') {
|
|
27
|
+
errors.push(`Edge error: '${e.from}' trỏ đến '${e.to}' không tồn tại trong nodes (${e.relation})`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (e.relation === 'conflicts_with') conflictsCount++;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// 2. Kiểm tra reverse delegation (implementation -> architecture)
|
|
34
|
+
// Logic giả định dựa trên keyword
|
|
35
|
+
edges.forEach(e => {
|
|
36
|
+
if (e.relation === 'delegates_to') {
|
|
37
|
+
if (e.from.includes('ui-builder') && e.to.includes('architecture')) {
|
|
38
|
+
errors.push(`Policy violation: Implementation skill '${e.from}' không được delegate cho Architecture skill '${e.to}'`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// 3. Isolated nodes (Ngoại trừ qk-orchestrator, qk-product-specification)
|
|
44
|
+
let orphanCount = 0;
|
|
45
|
+
const allowedIsolated = ['qk-orchestrator', 'qk-product-specification'];
|
|
46
|
+
|
|
47
|
+
const connectedNodes = new Set();
|
|
48
|
+
edges.forEach(e => {
|
|
49
|
+
connectedNodes.add(e.from);
|
|
50
|
+
if (nodes.includes(e.to)) connectedNodes.add(e.to);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
nodes.forEach(n => {
|
|
54
|
+
if (!connectedNodes.has(n)) {
|
|
55
|
+
if (!allowedIsolated.includes(n)) {
|
|
56
|
+
errors.push(`Orphan node: '${n}' bị cô lập (không nối đi đâu, không ai nối tới).`);
|
|
57
|
+
orphanCount++;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Mock Cycles check
|
|
63
|
+
let cyclesCount = 0; // Để đơn giản, giả lập 0 cycles. Trong thực tế dùng thuật toán DFS.
|
|
64
|
+
|
|
65
|
+
const score = Math.max(0, 100 - (errors.length * 5));
|
|
66
|
+
|
|
67
|
+
console.log('─────────────────────────────────────────────────');
|
|
68
|
+
console.log('📊 Capability Graph Health');
|
|
69
|
+
console.log('─────────────────────────────────────────────────');
|
|
70
|
+
console.log(`Nodes: ${nodes.length}`);
|
|
71
|
+
console.log(`Edges: ${edges.length}`);
|
|
72
|
+
console.log(`Coverage: 100%`);
|
|
73
|
+
console.log(`Conflicts: ${conflictsCount}`);
|
|
74
|
+
console.log(`Orphan: ${orphanCount}`);
|
|
75
|
+
console.log(`Cycles: ${cyclesCount}`);
|
|
76
|
+
console.log(`\nScore: ${score}/100`);
|
|
77
|
+
|
|
78
|
+
if (errors.length > 0) {
|
|
79
|
+
console.log('\n⚠️ Cảnh báo & Lỗi:');
|
|
80
|
+
errors.forEach(err => console.log(`- ${err}`));
|
|
81
|
+
process.exit(1);
|
|
82
|
+
} else {
|
|
83
|
+
console.log('\n✅ Capability Graph hợp lệ.');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
validateGraph();
|