9c8dbfde35
- buildStepLine: кратко «спросил -> ответил» (служебные строки экономия/coverage/вердикт отброшены) - protocol.steps: хук ведёт по строке на КАЖДЫЙ ход; рендер — список + одна ссылка raw в конце - reconcile (stampProvenance) сохраняет steps (модель их не трогает) - stop-хук добавляет шаг текущего хода 41 тест green, exit=0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
70 lines
3.8 KiB
JavaScript
70 lines
3.8 KiB
JavaScript
import { describe, it, expect } from 'vitest';
|
|
import { renderProtocol, EMPTY_PROTOCOL } from './secretary-protocol.mjs';
|
|
|
|
describe('EMPTY_PROTOCOL', () => {
|
|
it('пустой протокол со всеми 9 разделами', () => {
|
|
expect(EMPTY_PROTOCOL()).toEqual({
|
|
subject: '', status: 'открыто',
|
|
decisions: [], alternatives: [], consequences: [],
|
|
will: [], open: [], doneNext: [], history: [], steps: [],
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('renderProtocol — 9 категорий + шаги', () => {
|
|
const proto = {
|
|
subject: 'фоновый секретарь', status: 'открыто',
|
|
decisions: [{ text: 'D', why: 'w', turns: [7], session: '69992620-x' }],
|
|
alternatives: [{ text: 'ALT', turns: [8], session: '69992620-x' }],
|
|
consequences: [{ text: 'CONS', turns: [9], session: '69992620-x' }],
|
|
will: [{ text: 'W', turns: [10], session: '69992620-x' }],
|
|
open: [{ text: 'Q', turns: [11], session: '69992620-x' }],
|
|
doneNext: [{ text: 'N', done: false, turns: [12], session: '69992620-x' }],
|
|
history: [],
|
|
};
|
|
it('шапка «Дело» со статусом/хозяином/целью (по opts)', () => {
|
|
const md = renderProtocol(proto, { work: 'создание-секретаря', date: '2026-06-22 11:00' });
|
|
expect(md).toContain('**Дело:** создание-секретаря');
|
|
expect(md).toContain('**Статус:** открыто');
|
|
expect(md).toContain('**Хозяин:** владелец');
|
|
expect(md).toContain('**Цель:** фоновый секретарь');
|
|
});
|
|
it('разделы Альтернативы и Последствия / цена', () => {
|
|
const md = renderProtocol(proto);
|
|
expect(md).toContain('## Альтернативы');
|
|
expect(md).toContain('- ALT');
|
|
expect(md).toContain('## Последствия / цена');
|
|
expect(md).toContain('- CONS');
|
|
});
|
|
it('старые разделы целы (решения с провенансом и @сессией)', () => {
|
|
const md = renderProtocol(proto);
|
|
expect(md).toContain('- D — w [→7] @69992620');
|
|
expect(md).toContain('## Твоя воля / запреты');
|
|
expect(md).toContain('## Открытые вопросы');
|
|
});
|
|
it('зачёркивание во всех корзинах', () => {
|
|
const md = renderProtocol({
|
|
subject: '', status: 'открыто', history: [],
|
|
decisions: [{ text: 'D', struck: true }], alternatives: [{ text: 'A', struck: true }],
|
|
consequences: [{ text: 'C', struck: true }], will: [{ text: 'W', struck: true }],
|
|
open: [{ text: 'Q', struck: true }], doneNext: [{ text: 'N', struck: true, done: false }],
|
|
});
|
|
for (const t of ['~~D~~', '~~A~~', '~~C~~', '~~W~~', '~~Q~~', '~~N~~']) expect(md).toContain(t);
|
|
});
|
|
it('раздел Шаги (Слой 1): человекочитаемые строки на КАЖДЫЙ ход + ссылка на сырьё в конце', () => {
|
|
const md = renderProtocol({
|
|
subject: '', status: 'открыто', history: [],
|
|
decisions: [], alternatives: [], consequences: [], will: [], open: [], doneNext: [],
|
|
steps: [
|
|
{ turn: 1, session: '69992620-x', text: 'Спросил про оглавление → ответил: тема + время' },
|
|
{ turn: 2, session: '69992620-x', text: 'Попросил флажок по сессии → сделал' },
|
|
],
|
|
});
|
|
expect(md).toContain('## Шаги (Слой 1)');
|
|
expect(md).toContain('Спросил про оглавление → ответил: тема + время');
|
|
expect(md).toContain('Попросил флажок по сессии → сделал');
|
|
expect(md).toContain('Подробно (дословно): raw/69992620-x.log');
|
|
expect(md).not.toContain('[→1] raw/'); // не ссылка в каждой строке
|
|
});
|
|
});
|