mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 21:53:28 +08:00
feat: architecture improvements — test discovery, hooks schema, catalog, command map, coverage, cross-harness docs
- AGENTS.md: sync skills count to 65+ - tests/run-all.js: glob-based test discovery for *.test.js - scripts/ci/validate-hooks.js: validate hooks.json with ajv + schemas/hooks.schema.json - schemas/hooks.schema.json: hookItem.type enum command|notification - scripts/ci/catalog.js: catalog agents, commands, skills (--json | --md) - docs/COMMAND-AGENT-MAP.md: command → agent/skill map - docs/ARCHITECTURE-IMPROVEMENTS.md: improvement recommendations - package.json: ajv, c8 devDeps; npm run coverage - CONTRIBUTING.md: Cross-Harness and Translations section - .gitignore: coverage/ Made-with: Cursor
This commit is contained in:
committed by
Affaan Mustafa
parent
c883289abb
commit
a50349181a
71
scripts/ci/catalog.js
Normal file
71
scripts/ci/catalog.js
Normal file
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Catalog agents, commands, and skills from the repo.
|
||||
* Outputs JSON with counts and lists for CI/docs sync.
|
||||
*
|
||||
* Usage: node scripts/ci/catalog.js [--json|--md]
|
||||
* Default: --json to stdout
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const ROOT = path.join(__dirname, '../..');
|
||||
const AGENTS_DIR = path.join(ROOT, 'agents');
|
||||
const COMMANDS_DIR = path.join(ROOT, 'commands');
|
||||
const SKILLS_DIR = path.join(ROOT, 'skills');
|
||||
|
||||
function listAgents() {
|
||||
if (!fs.existsSync(AGENTS_DIR)) return [];
|
||||
return fs.readdirSync(AGENTS_DIR)
|
||||
.filter(f => f.endsWith('.md'))
|
||||
.map(f => f.slice(0, -3))
|
||||
.sort();
|
||||
}
|
||||
|
||||
function listCommands() {
|
||||
if (!fs.existsSync(COMMANDS_DIR)) return [];
|
||||
return fs.readdirSync(COMMANDS_DIR)
|
||||
.filter(f => f.endsWith('.md'))
|
||||
.map(f => f.slice(0, -3))
|
||||
.sort();
|
||||
}
|
||||
|
||||
function listSkills() {
|
||||
if (!fs.existsSync(SKILLS_DIR)) return [];
|
||||
const entries = fs.readdirSync(SKILLS_DIR, { withFileTypes: true });
|
||||
return entries
|
||||
.filter(e => e.isDirectory() && fs.existsSync(path.join(SKILLS_DIR, e.name, 'SKILL.md')))
|
||||
.map(e => e.name)
|
||||
.sort();
|
||||
}
|
||||
|
||||
function run() {
|
||||
const agents = listAgents();
|
||||
const commands = listCommands();
|
||||
const skills = listSkills();
|
||||
|
||||
const catalog = {
|
||||
agents: { count: agents.length, list: agents },
|
||||
commands: { count: commands.length, list: commands },
|
||||
skills: { count: skills.length, list: skills }
|
||||
};
|
||||
|
||||
const format = process.argv[2] === '--md' ? 'md' : 'json';
|
||||
if (format === 'md') {
|
||||
console.log('# ECC Catalog (generated)\n');
|
||||
console.log(`- **Agents:** ${catalog.agents.count}`);
|
||||
console.log(`- **Commands:** ${catalog.commands.count}`);
|
||||
console.log(`- **Skills:** ${catalog.skills.count}\n`);
|
||||
console.log('## Agents\n');
|
||||
catalog.agents.list.forEach(a => console.log(`- ${a}`));
|
||||
console.log('\n## Commands\n');
|
||||
catalog.commands.list.forEach(c => console.log(`- ${c}`));
|
||||
console.log('\n## Skills\n');
|
||||
catalog.skills.list.forEach(s => console.log(`- ${s}`));
|
||||
} else {
|
||||
console.log(JSON.stringify(catalog, null, 2));
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
@@ -1,13 +1,15 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Validate hooks.json schema
|
||||
* Validate hooks.json schema and hook entry rules.
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const vm = require('vm');
|
||||
const Ajv = require('ajv');
|
||||
|
||||
const HOOKS_FILE = path.join(__dirname, '../../hooks/hooks.json');
|
||||
const HOOKS_SCHEMA_PATH = path.join(__dirname, '../../schemas/hooks.schema.json');
|
||||
const VALID_EVENTS = ['PreToolUse', 'PostToolUse', 'PreCompact', 'SessionStart', 'SessionEnd', 'Stop', 'Notification', 'SubagentStop'];
|
||||
|
||||
/**
|
||||
@@ -67,6 +69,20 @@ function validateHooks() {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Validate against JSON schema
|
||||
if (fs.existsSync(HOOKS_SCHEMA_PATH)) {
|
||||
const schema = JSON.parse(fs.readFileSync(HOOKS_SCHEMA_PATH, 'utf-8'));
|
||||
const ajv = new Ajv({ allErrors: true });
|
||||
const validate = ajv.compile(schema);
|
||||
const valid = validate(data);
|
||||
if (!valid) {
|
||||
for (const err of validate.errors) {
|
||||
console.error(`ERROR: hooks.json schema: ${err.instancePath || '/'} ${err.message}`);
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Support both object format { hooks: {...} } and array format
|
||||
const hooks = data.hooks || data;
|
||||
let hasErrors = false;
|
||||
|
||||
Reference in New Issue
Block a user