test(secretary): gravity / reopen / history-compression mechanics (decision #8)
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { applyTend } from './secretary-gardener.mjs';
|
||||
import { applyResults } from './secretary-apply.mjs';
|
||||
|
||||
// Механика, которую на 2-спановых прогонах не проверяли (НАХОДКИ, решение №8). Тесты бьют по реальным
|
||||
// функциям конвейера A (applyTend/applyResults), а не по воркеру — это поведение разбора, не оркестрации.
|
||||
|
||||
describe('mechanics: reopen / обратный каскад', () => {
|
||||
it('закрытая ветка снова открывается и снимается зачёркивание (несущее решение изменилось)', () => {
|
||||
const proto = { hidden: [{ id: 'СВ-1', lens: 'Л4', status: 'закрыт', struck: true, text: 'дыра', born: 3, lastTouch: 5 }] };
|
||||
applyTend(proto, [{ id: 'СВ-1', action: 'reopen', why: 'несущее решение изменилось' }], 8);
|
||||
const sv = proto.hidden[0];
|
||||
expect(sv.status).toBe('открыт');
|
||||
expect(sv.struck).toBe(false);
|
||||
expect(sv.lastTouch).toBe(8);
|
||||
expect(sv.born).toBe(3); // корень сохранён — не потеряли историю
|
||||
});
|
||||
});
|
||||
|
||||
describe('mechanics: сжатие длинной истории (сворачивание ≠ удаление)', () => {
|
||||
it('на масштабе: закрытые ветки сворачиваются (struck), но остаются с источником (born)', () => {
|
||||
// 12 живых веток; закрываем половину с пруфом.
|
||||
const hidden = Array.from({ length: 12 }, (_, i) => ({
|
||||
id: `СВ-${i + 1}`, lens: 'Л1', status: 'открыт', struck: false,
|
||||
text: `нет выдержек кода ${i}`, born: i + 1, lastTouch: i + 1,
|
||||
}));
|
||||
const proto = { hidden };
|
||||
const tend = hidden.filter((_, i) => i % 2 === 0).map((h) => ({ id: h.id, action: 'close', proof: `код:${h.born}` }));
|
||||
applyTend(proto, tend, 20);
|
||||
// Ни одна ветка не удалена — сворачивание прячет видность, не корень («потом не восстановим»).
|
||||
expect(proto.hidden).toHaveLength(12);
|
||||
const closed = proto.hidden.filter((h) => h.status === 'закрыт');
|
||||
expect(closed).toHaveLength(6);
|
||||
for (const h of closed) {
|
||||
expect(h.struck).toBe(true);
|
||||
expect(Number.isFinite(h.born)).toBe(true); // источник на месте
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('mechanics: гравитация (кандидат → ствол)', () => {
|
||||
// ПРОБЕЛ (follow-up): в A механика НЕ реализована. applyResults накапливает кандидатов (p.candidates,
|
||||
// дедуп по branch), но НЕТ пути продвижения кандидата в ствол (decisions/will), когда владелец заговорил
|
||||
// об идее. Это суждение РЕДАКТОРА (сопоставить кандидата с движением ствола), не детерминированное
|
||||
// правило — строить спекулятивно нельзя (решение владельца; реализация = доработка редактор-промпта).
|
||||
// Документируем как незакрытый хвост, не выдаём отсутствующее за готовое.
|
||||
it.todo('кандидат поднимается в ствол, когда владелец заговорил об его идее');
|
||||
|
||||
it('сейчас: кандидат лишь накапливается в candidates, в ствол сам не уходит (фиксируем текущее поведение)', () => {
|
||||
const proto = { hidden: [], candidates: [], nextSvId: 1, decisions: [] };
|
||||
const d13 = { forks: [{ branch: 'вынести очередь в SQLite', trigger: 'цитата', why: 'масштаб', опора: 'догадка', релевантность: 'medium' }] };
|
||||
const out = applyResults(proto, 5, null, null, d13, null);
|
||||
expect(out.candidates).toHaveLength(1);
|
||||
expect(out.candidates[0].branch).toBe('вынести очередь в SQLite');
|
||||
expect(out.decisions || []).toHaveLength(0); // в ствол не просочился — подтверждает, что гравитации нет
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user