feat(secretary): разделитель сессий в разделе «Шаги»

В сквозной тетради дела между ходами разных сессий рендер вставляет строку
«—— сессия <id> ——» (граница рабочего захода) — навигация по длинному делу.
Не перед первой сессией; только на смене session между соседними шагами. TDD, свод зелёный.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-06-22 18:46:57 +03:00
parent 229b9c443e
commit b527f26a37
2 changed files with 26 additions and 4 deletions
+12 -4
View File
@@ -22,11 +22,19 @@ const line = (e) => `${e.struck ? `~~${e.text}~~` : e.text}${prov(e.turns)}`;
function stepsSection(p) {
const steps = (p.steps || []).slice().sort((a, b) => (a.turn || 0) - (b.turn || 0));
// Ссылка на отдельный файл хода (file=«ходы/turn-N.log»), проставленный при остановке;
// до нарезки — запасной вариант на общий лог сессии.
return steps.map((s) => {
// до нарезки — запасной вариант на общий лог сессии. Между ходами разных сессий —
// строка-разделитель «—— сессия X ——» (граница рабочего захода в сквозной тетради).
const out = [];
let prevSession = null;
for (const s of steps) {
if (s.session && prevSession !== null && s.session !== prevSession) {
out.push(`—— сессия ${s.session} ——`);
}
const ref = s.file || (s.session ? `${s.session}.log` : '');
return `- ${s.text}${ref ? ` · ${ref}` : ''}`;
});
out.push(`- ${s.text}${ref ? ` · ${ref}` : ''}`);
if (s.session) prevSession = s.session;
}
return out;
}
// Полная форма протокола (§D7): шапка «Дело» + 8 корзин (2–9) + навигация Шаги→Слой 1.
+14
View File
@@ -85,4 +85,18 @@ describe('renderProtocol — 9 категорий + шаги', () => {
expect(md).toContain('## Шаги (Слой 1)');
expect(md).toContain('Ход 1 — я: про оглавление · ты: тема+время · делал: читал хук · 69992620-x.log');
});
it('Шаги: разделитель «—— сессия X ——» при смене сессии (не перед первой)', () => {
const md = renderProtocol({
subject: '', status: 'открыто', history: [],
decisions: [], alternatives: [], consequences: [], will: [], open: [], doneNext: [],
steps: [
{ turn: 1, session: 'sА', text: 'Ход 1 — я: a · ты: b · делал: —' },
{ turn: 2, session: 'sА', text: 'Ход 2 — я: c · ты: d · делал: —' },
{ turn: 3, session: 'sБ', text: 'Ход 3 — я: e · ты: f · делал: —' },
],
});
expect(md).toContain('—— сессия sБ ——');
expect(md).not.toContain('—— сессия sА ——'); // перед первой сессией разделителя нет
expect(md.indexOf('—— сессия sБ ——')).toBeLessThan(md.indexOf('Ход 3'));
});
});