Files
brain/tools/registry-load.test.mjs
T
Дмитрий e98ba1e527 feat: разворачивание комка claude-md-management — пилот реестра роутера
Эпик роутер-реестр, спека v2 §2. Развёрнут самый маленький комок-зонтик
в 2 отдельные карточки-навыка ради точного подбора роутером. Пилот выверил
конвенцию для остальных 11 комков.

- 2 карточки: claude-md-management__claude-md-improver + __revise-claude-md;
  поле skill = плагин:навык, kind external, zero-hash source
- nodes.yaml: узел #33 развёрнут в дочерние #33a/#33b; ссылка L12 обновлена
- schema.json: паттерн id расширен на дочерний суффикс #NNa
- registry-load.test: счётчики узлов 89 в 90, active 81 в 82
- splitting-inventory.md: инвентаризация 12 комков + выверенная конвенция
- тест-сторож split-pilot-claude-md + план пилота

Регрессия свода: 4361 passed, 0 failed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 22:35:59 +03:00

82 lines
2.9 KiB
JavaScript

// tools/registry-load.test.mjs
import { describe, it, expect, beforeEach } from 'vitest';
import { loadRegistry, clearCache, findByClassification, findByKeyword, findActiveNodes, findChainsByNode } from './registry-load.mjs';
describe('registry-load', () => {
beforeEach(() => clearCache());
it('loads registry (90 nodes: 89 + разворачивание #33 → #33a/#33b 18.06.2026)', () => {
const r = loadRegistry();
expect(r.nodes).toHaveLength(90);
expect(r.version).toBe('0.1.0');
});
it('indexes by classification', () => {
const r = loadRegistry();
const features = findByClassification(r, 'feature');
expect(features).toHaveLength(1);
expect(features[0].node.id).toBe('#19');
expect(features[0].weight).toBe(1.0);
});
it('returns empty array for unknown classification', () => {
const r = loadRegistry();
expect(findByClassification(r, 'nonexistent')).toEqual([]);
});
it('indexes by keyword case-insensitive', () => {
const r = loadRegistry();
expect(findByKeyword(r, 'tdd')).toHaveLength(1);
expect(findByKeyword(r, 'TDD')).toHaveLength(1);
});
it('excludes historic/dormant from trigger index', () => {
const r = loadRegistry();
// #1 PostgreSQL MCP — historic, не должен попасть в индексы
for (const entries of r.indexByTrigger.values()) {
expect(entries.find(e => e.node.id === '#1')).toBeUndefined();
}
});
it('includes historic in nodes array (full reference)', () => {
const r = loadRegistry();
expect(r.indexById.get('#1').status).toBe('historic');
});
it('findActiveNodes excludes non-active (nodes.yaml registry)', () => {
const r = loadRegistry();
const active = findActiveNodes(r);
// 90 nodes total; #1 historic, #17 dormant, #44/#50/#54/#67/#82/#83 deferred,
// #84/#85/#86 + #87/#88/#89 active; #33 (1 active) развёрнут в #33a/#33b (2 active) → +1 → 82 active
expect(active).toHaveLength(82);
expect(active.map(n => n.id)).toContain('#18');
expect(active.map(n => n.id)).toContain('#19');
expect(active.map(n => n.id)).not.toContain('#1');
expect(active.map(n => n.id)).not.toContain('#17');
});
it('findChainsByNode returns chain membership', () => {
const r = loadRegistry();
// L8 = runtime debug chain: systematic-debugging + Sentry (#34) + Redis (#35)
const sentryChains = findChainsByNode(r, '#34');
expect(sentryChains.map(c => c.chainId)).toContain('L8');
});
it('caches across calls in same process', () => {
const r1 = loadRegistry();
const r2 = loadRegistry();
expect(r1).toBe(r2); // same reference
});
it('clearCache forces reload', () => {
const r1 = loadRegistry();
clearCache();
const r2 = loadRegistry();
expect(r1).not.toBe(r2);
});
it('throws on schema violation', () => {
expect(() => loadRegistry({ registryPath: '/nonexistent/path.yaml', useCache: false })).toThrow();
});
});