refactor(router): Этап B1 сноса цепочек L — node-graph без chains/hintLinksOf

Этап 3 эпика «роутер-реестр» (B1): из tools/node-graph.mjs убрана поддержка chains
(в buildNodeGraph) и функция hintLinksOf (живого импортёра нет); тест приведён в
соответствие (без hintLinksOf-блока и литералов chains). twinsOf/conflictsOf/resolveNode/
checkGraphFreshness сохранены. Полный свод зелёный (263 файла, 4414 тестов — прогон в чистом
терминале владельца; под Bash сессии воркеры коллапсируют от контеншна).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-06-20 16:15:10 +03:00
parent 0103388bc0
commit 4249535eea
2 changed files with 9 additions and 39 deletions
+3 -15
View File
@@ -1,6 +1,6 @@
import { describe, it, expect } from 'vitest';
import {
buildNodeGraph, resolveNode, twinsOf, hintLinksOf, conflictsOf, checkGraphFreshness,
buildNodeGraph, resolveNode, twinsOf, conflictsOf, checkGraphFreshness,
} from './node-graph.mjs';
const REG = {
@@ -11,9 +11,6 @@ const REG = {
{ id: '#38', name: 'architecture-patterns', slug: 'architecture-patterns', subcategory: 'architecture-tooling', status: 'active' },
{ id: '#17', name: 'pg_partman', slug: 'pg-partman', subcategory: null, status: 'dormant' },
],
chains: {
L4: { name: 'diagram', sequence: ['#36', '#37'] },
},
};
describe('buildNodeGraph', () => {
@@ -24,7 +21,7 @@ describe('buildNodeGraph', () => {
expect(g.bySlug.get('mermaid').id).toBe('#37');
});
it('accepts a plain registry literal (not loadRegistry-bound)', () => {
const g = buildNodeGraph({ nodes: [{ id: '#1', slug: 'x', name: 'X' }], chains: {} });
const g = buildNodeGraph({ nodes: [{ id: '#1', slug: 'x', name: 'X' }] });
expect(g.bySlug.get('x').id).toBe('#1');
});
});
@@ -64,21 +61,12 @@ describe('twinsOf (близнецы = общий subcategory, активные)'
it('несуществующий ref → []', () => { expect(twinsOf(g, 'nope')).toEqual([]); });
});
describe('hintLinksOf (связи = со-членство в цепочке)', () => {
const g = buildNodeGraph(REG);
it('соседи по chains, без себя', () => {
expect(hintLinksOf(g, '#36').map((n) => n.id)).toEqual(['#37']);
expect(hintLinksOf(g, '#37').map((n) => n.id)).toEqual(['#36']);
});
it('узел вне цепочек → []', () => { expect(hintLinksOf(g, '#19')).toEqual([]); });
});
describe('conflictsOf (явные attributes.conflicts_with)', () => {
it('резолвит явные конфликт-рёбра', () => {
const reg = { nodes: [
{ id: '#a', slug: 'a', status: 'active', attributes: { conflicts_with: ['#b'] } },
{ id: '#b', slug: 'b', status: 'active' },
], chains: {} };
] };
const g = buildNodeGraph(reg);
expect(conflictsOf(g, '#a').map((n) => n.id)).toEqual(['#b']);
});