c7e02eeac9
router-prehook, router-stop-gate, router-tool-gate теперь читают stdin через readStdinAsUtf8 (StringDecoder). Русский в промпте корректно доходит до Anthropic API и в state-файл — никаких mojibake типа 'посмотри'. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
58 lines
2.5 KiB
JavaScript
58 lines
2.5 KiB
JavaScript
import { describe, it, expect } from 'vitest';
|
|
import { buildStateFromClassification, isEnforcementRequired } from './router-prehook.mjs';
|
|
|
|
describe('buildStateFromClassification', () => {
|
|
it('builds full state object', () => {
|
|
const cls = { taskType: 'feature', micro: false, recommendedNode: '#19', confidence: 0.9, source: 'regex', recommendedChain: 'L1' };
|
|
const s = buildStateFromClassification(cls, { sessionId: 'abc', promptHash: '12345' });
|
|
expect(s.sessionId).toBe('abc');
|
|
expect(s.promptHash).toBe('12345');
|
|
expect(s.classification).toEqual(cls);
|
|
expect(s.skillInvokedThisTurn).toBe(false);
|
|
expect(s.chainProgress).toEqual([]);
|
|
expect(s.enforcementRequired).toBe(true);
|
|
expect(s.timestamp).toBeDefined();
|
|
});
|
|
|
|
it('enforcementRequired false on micro', () => {
|
|
const s = buildStateFromClassification({ taskType: 'bugfix', micro: true, recommendedNode: null }, { sessionId: 'a', promptHash: 'b' });
|
|
expect(s.enforcementRequired).toBe(false);
|
|
});
|
|
|
|
it('enforcementRequired false when no recommendedNode', () => {
|
|
const s = buildStateFromClassification({ taskType: 'question', micro: false, recommendedNode: null }, { sessionId: 'a', promptHash: 'b' });
|
|
expect(s.enforcementRequired).toBe(false);
|
|
});
|
|
|
|
it('enforcementRequired false on excluded taskType', () => {
|
|
const s = buildStateFromClassification({ taskType: 'question', micro: false, recommendedNode: '#60' }, { sessionId: 'a', promptHash: 'b' });
|
|
expect(s.enforcementRequired).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('isEnforcementRequired', () => {
|
|
it('true on feature with node', () => {
|
|
expect(isEnforcementRequired({ taskType: 'feature', micro: false, recommendedNode: '#19' })).toBe(true);
|
|
});
|
|
|
|
it('false on micro', () => {
|
|
expect(isEnforcementRequired({ taskType: 'feature', micro: true, recommendedNode: '#19' })).toBe(false);
|
|
});
|
|
|
|
it('false when no node', () => {
|
|
expect(isEnforcementRequired({ taskType: 'feature', micro: false, recommendedNode: null })).toBe(false);
|
|
});
|
|
|
|
it('false on question/memory-sync (excluded)', () => {
|
|
expect(isEnforcementRequired({ taskType: 'question', micro: false, recommendedNode: '#60' })).toBe(false);
|
|
expect(isEnforcementRequired({ taskType: 'memory-sync', micro: false, recommendedNode: '#33' })).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('UTF-8 cyrillic stdin (regression — Stage 3 fix 1)', () => {
|
|
it('module loads with UTF-8 helper wired (smoke)', async () => {
|
|
const mod = await import('./router-prehook.mjs');
|
|
expect(typeof mod.buildStateFromClassification).toBe('function');
|
|
});
|
|
});
|