- route-interceptor-bundle.js: 硬 require 改为 try-catch fail-open (旧版部署缺 scripts/route-engine.js 等文件时不再崩溃, 降级为 BWR:skip) - package.json 6.5.0 → 6.6.0 对齐 VERSION 文件 - INTEGRITY + 签名更新 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
69 lines
2.9 KiB
JavaScript
69 lines
2.9 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Skill Cleanup: Remove 22 low-value skills
|
|
* - 14 delete (irrelevant/niche/overlapping)
|
|
* - 8 merge-remove (redundant groups)
|
|
* Moves skill dirs to skills/_archived/, removes from skills-index.json
|
|
*/
|
|
'use strict';
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const CLAUDE_ROOT = path.resolve(__dirname, '..', '..');
|
|
const INDEX = path.join(CLAUDE_ROOT, 'skills-index.json');
|
|
const SKILLS_DIR = path.join(CLAUDE_ROOT, 'skills');
|
|
const ARCHIVE_DIR = path.join(SKILLS_DIR, '_archived');
|
|
|
|
const TO_REMOVE = [
|
|
// Cat 1: language/framework mismatch (6)
|
|
'angular-architect', 'flutter-expert', 'golang-pro',
|
|
'rust-engineer', 'swift-expert', 'vue-expert',
|
|
// Cat 1: extremely niche (4)
|
|
'ai-philosophy-expert', 'edge-computing-expert', 'graphql-architect', 'evolution-tracker',
|
|
// Cat 1: overlapping with T1 (4)
|
|
'ultimate-code-expert', 'frontend-design', 'design-consultation', 'design-review',
|
|
// Cat 2: plan variants → planning-with-files covers (3)
|
|
'plan-ceo-review', 'plan-design-review', 'plan-eng-review',
|
|
// Cat 2: design duplicates → frontend-expert T1 covers (3)
|
|
'designer-expert', 'ui-ux-pro-max', 'ux-researcher',
|
|
// Cat 2: setup tools → devops-expert covers (2)
|
|
'setup-browser-cookies', 'setup-deploy',
|
|
];
|
|
|
|
if (!fs.existsSync(INDEX)) { process.stderr.write('[FAIL] skills-index.json not found\n'); process.exit(1); }
|
|
const src = fs.readFileSync(INDEX, 'utf8');
|
|
let index;
|
|
try { index = JSON.parse(src); } catch { process.stderr.write('[FAIL] parse\n'); process.exit(1); }
|
|
|
|
fs.writeFileSync(INDEX + '.bak-cleanup.' + Date.now(), src);
|
|
|
|
const removeSet = new Set(TO_REMOVE);
|
|
const before = index.skills.length;
|
|
index.skills = index.skills.filter(s => !removeSet.has(s.name));
|
|
const removed = before - index.skills.length;
|
|
|
|
// Write updated index
|
|
const tmp = INDEX + '.tmp.' + process.pid;
|
|
fs.writeFileSync(tmp, JSON.stringify(index, null, 2), 'utf8');
|
|
fs.renameSync(tmp, INDEX);
|
|
process.stderr.write('[INDEX] Removed ' + removed + '/' + TO_REMOVE.length + ' from skills-index.json (' + before + ' -> ' + index.skills.length + ')\n');
|
|
|
|
// Move skill directories to _archived
|
|
if (!fs.existsSync(ARCHIVE_DIR)) fs.mkdirSync(ARCHIVE_DIR, { recursive: true });
|
|
let moved = 0;
|
|
for (const name of TO_REMOVE) {
|
|
const src = path.join(SKILLS_DIR, name);
|
|
const dst = path.join(ARCHIVE_DIR, name);
|
|
if (fs.existsSync(src) && !fs.existsSync(dst)) {
|
|
try { fs.renameSync(src, dst); moved++; } catch (e) {
|
|
process.stderr.write('[WARN] Failed to move ' + name + ': ' + e.message + '\n');
|
|
}
|
|
}
|
|
}
|
|
process.stderr.write('[FILES] Moved ' + moved + ' skill dirs to _archived/\n');
|
|
|
|
// Summary
|
|
const tiers = {};
|
|
for (const s of index.skills) tiers[s.tier_class] = (tiers[s.tier_class] || 0) + 1;
|
|
process.stderr.write('[DONE] Final: ' + index.skills.length + ' skills (T1=' + (tiers.T1||0) + ' T2=' + (tiers.T2||0) + ' T3=' + (tiers.T3||0) + ')\n');
|