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>
17 lines
1.0 KiB
JavaScript
17 lines
1.0 KiB
JavaScript
// Учёт «какие сессии вели дело» — для догона недоразобранного хвоста умершей сессии после краха.
|
|
// Хранится в папке дела (docs/secretary/<work>/_sessions.json), НЕ коммитится.
|
|
|
|
/** Добавить/обновить указатель сессии {session, cursor}. cursor — последний разобранный spanCursor. */
|
|
export function upsertSessionPointer(list, { session, cursor }) {
|
|
const out = (Array.isArray(list) ? list : []).map((e) => ({ ...e }));
|
|
const i = out.findIndex((e) => e.session === session);
|
|
if (i >= 0) out[i].cursor = cursor;
|
|
else out.push({ session, cursor });
|
|
return out;
|
|
}
|
|
|
|
/** Прошлые сессии дела (кроме текущей) — кандидаты на догон хвоста. */
|
|
export function prevSessionsForCatchUp(list, currentSession) {
|
|
return (Array.isArray(list) ? list : []).filter((e) => e && e.session && e.session !== currentSession);
|
|
}
|