90f1360065
Секретарь перестал терять промпт владельца при обрыве (сбой API / ручной стоп / жёсткий крах). Источник правды — транскрипт на диске: сырьё (Слой 1) пересобирается из всего транскрипта на каждом завершении, а не дописывается по последнему обмену. - classifyEntry/assembleExchanges: распознавание машинных меток (isApiErrorMessage, [Request interrupted by user] обе формы, isCompactSummary, isMeta) — метка не считается настоящим промптом; промпт после обрыва помечается продолжением (cont=1), хвост — tail=1. - realBoundariesFromRaw: продолжение не открывает новый спан (одна работа не дробится). - честные пометки спана: «(связь прерывалась — продолжено)» / «(прервана, не завершена)». - stop-хук: пересборка сырья из транскрипта + догон недоразобранного хвоста прошлых (умерших) сессий дела при «включи секретаря <дело>» (_sessions.json, secretary-sessions). - parseLastExchange → тонкая обёртка над assembleExchanges (без дубля логики). Свод секретаря зелёный: 172 теста / 12 файлов. Спека: docs/superpowers/specs/2026-06-23-secretary-interruption-resilience-spec.md План: docs/superpowers/plans/2026-06-23-secretary-interruption-resilience.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
21 lines
1.1 KiB
JavaScript
21 lines
1.1 KiB
JavaScript
import { describe, it, expect } from 'vitest';
|
|
import { upsertSessionPointer, prevSessionsForCatchUp } from './secretary-sessions.mjs';
|
|
|
|
describe('secretary-sessions — учёт сессий дела', () => {
|
|
it('upsertSessionPointer добавляет новую сессию с курсором', () => {
|
|
const out = upsertSessionPointer([], { session: 's1', cursor: 2 });
|
|
expect(out).toEqual([{ session: 's1', cursor: 2 }]);
|
|
});
|
|
it('upsertSessionPointer обновляет курсор существующей', () => {
|
|
const out = upsertSessionPointer([{ session: 's1', cursor: 1 }], { session: 's1', cursor: 5 });
|
|
expect(out).toEqual([{ session: 's1', cursor: 5 }]);
|
|
});
|
|
it('prevSessionsForCatchUp — все сессии дела кроме текущей', () => {
|
|
const list = [{ session: 's1', cursor: 3 }, { session: 's2', cursor: 0 }];
|
|
expect(prevSessionsForCatchUp(list, 's2')).toEqual([{ session: 's1', cursor: 3 }]);
|
|
});
|
|
it('prevSessionsForCatchUp — пустой список → пусто', () => {
|
|
expect(prevSessionsForCatchUp([], 's2')).toEqual([]);
|
|
});
|
|
});
|