91 lines
3.6 KiB
JavaScript
91 lines
3.6 KiB
JavaScript
|
|
#!/usr/bin/env node
|
||
|
|
/**
|
||
|
|
* P0-3 Precise Re-tiering
|
||
|
|
* Uses maturity field + route frequency + domain relevance for accurate T1/T2/T3
|
||
|
|
* Replaces previous coarse tiering (T3 only matched 2/34)
|
||
|
|
* Idempotent: overwrites existing tier_class/criticality values
|
||
|
|
*/
|
||
|
|
'use strict';
|
||
|
|
const fs = require('fs');
|
||
|
|
const path = require('path');
|
||
|
|
|
||
|
|
const TARGET = path.resolve(__dirname, '..', '..', 'skills-index.json');
|
||
|
|
if (!fs.existsSync(TARGET)) { process.stderr.write('[SKIP] not found\n'); process.exit(0); }
|
||
|
|
|
||
|
|
const src = fs.readFileSync(TARGET, 'utf8');
|
||
|
|
let index;
|
||
|
|
try { index = JSON.parse(src); } catch { process.stderr.write('[FAIL] parse\n'); process.exit(1); }
|
||
|
|
if (!index.skills) { process.stderr.write('[FAIL] no skills\n'); process.exit(1); }
|
||
|
|
|
||
|
|
fs.writeFileSync(TARGET + '.bak-p03-precise.' + Date.now(), src);
|
||
|
|
|
||
|
|
// T1: 21 high-frequency / high-criticality core skills
|
||
|
|
const T1 = new Set([
|
||
|
|
'ai-ml-expert', 'architect-expert', 'backend-builder', 'debugger-expert',
|
||
|
|
'developer-expert', 'devops-expert', 'frontend-expert', 'git-operation-master',
|
||
|
|
'guardian', 'mobile-expert', 'performance-expert', 'project-audit-expert',
|
||
|
|
'prompt-optimizer', 'qa', 'review', 'reviewer-expert', 'security-expert',
|
||
|
|
'technical-seo-expert', 'tester-expert', 'workflow-automation-expert',
|
||
|
|
'zero-defect-guardian',
|
||
|
|
]);
|
||
|
|
|
||
|
|
// T2: 28 on-demand skills (proven useful or domain-relevant)
|
||
|
|
const T2 = new Set([
|
||
|
|
// Stable T2 (13): actively routed or clearly relevant
|
||
|
|
'api-integration-specialist', 'browser-automation-expert', 'cloud-native-expert',
|
||
|
|
'data-engineer-expert', 'database-tuning-expert', 'devsecops-expert',
|
||
|
|
'diagram-as-code-expert', 'handoff', 'mcp-probe', 'mcp-prune',
|
||
|
|
'miniprogram-expert', 'product-manager-expert', 'regex-shell-wizard',
|
||
|
|
// Unknown T2 (10): infra/ops/dev tools
|
||
|
|
'api-designer', 'cloud-architect', 'data-analyst-expert', 'gstack',
|
||
|
|
'kubernetes-specialist', 'project-coordinator', 'ship', 'sre-expert',
|
||
|
|
'tech-writer-expert', 'terraform-engineer',
|
||
|
|
// Imported T2 (5): actively routed or language skills
|
||
|
|
'codex', 'investigate', 'nextjs-developer', 'python-pro', 'typescript-pro',
|
||
|
|
]);
|
||
|
|
|
||
|
|
// HIGH criticality: security/audit/guardian types
|
||
|
|
const HIGH_CRIT = new Set([
|
||
|
|
'security-expert', 'guardian', 'zero-defect-guardian', 'review',
|
||
|
|
'debugger-expert', 'developer-expert', 'project-audit-expert',
|
||
|
|
]);
|
||
|
|
|
||
|
|
// Load route frequency from available data
|
||
|
|
const routeFreq = {};
|
||
|
|
const dataFiles = [
|
||
|
|
path.join(__dirname, '..', '..', 'debug', 'shadow-route-log.jsonl'),
|
||
|
|
path.join(__dirname, '..', '..', 'debug', 'metrics-route.jsonl'),
|
||
|
|
];
|
||
|
|
for (const f of dataFiles) {
|
||
|
|
try {
|
||
|
|
if (!fs.existsSync(f)) continue;
|
||
|
|
for (const line of fs.readFileSync(f, 'utf8').split('\n').filter(Boolean)) {
|
||
|
|
try {
|
||
|
|
const e = JSON.parse(line);
|
||
|
|
const name = e.p || e.skill;
|
||
|
|
if (name && name !== 'none') routeFreq[name] = (routeFreq[name] || 0) + 1;
|
||
|
|
} catch {}
|
||
|
|
}
|
||
|
|
} catch {}
|
||
|
|
}
|
||
|
|
|
||
|
|
let t1 = 0, t2 = 0, t3 = 0;
|
||
|
|
for (const skill of index.skills) {
|
||
|
|
const name = skill.name || '';
|
||
|
|
if (T1.has(name)) {
|
||
|
|
skill.tier_class = 'T1'; t1++;
|
||
|
|
} else if (T2.has(name)) {
|
||
|
|
skill.tier_class = 'T2'; t2++;
|
||
|
|
} else {
|
||
|
|
skill.tier_class = 'T3'; t3++;
|
||
|
|
}
|
||
|
|
skill.criticality = HIGH_CRIT.has(name) ? 'HIGH' : T1.has(name) ? 'MEDIUM' : 'LOW';
|
||
|
|
skill.callCount30d = routeFreq[name] || 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
const tmp = TARGET + '.tmp.' + process.pid;
|
||
|
|
fs.writeFileSync(tmp, JSON.stringify(index, null, 2), 'utf8');
|
||
|
|
fs.renameSync(tmp, TARGET);
|
||
|
|
process.stderr.write('[DONE] Precise tiering: T1=' + t1 + ' T2=' + t2 + ' T3=' + t3 + '\n');
|
||
|
|
process.stderr.write('[DATA] Route frequency populated for ' + Object.keys(routeFreq).length + ' skills\n');
|