Files
brain/tools/secretary-protocol.mjs
T
Дмитрий 67fecd7149 feat(secretary): reconcile — модель-редактор правит весь протокол, хук-сторож против потерь
- secretary-reconcile.mjs: buildReconcilePrompt (весь протокол+обмен), parseReconcileResponse,
  reconcileGuard (ни одна старая строка не пропала), buildGuardRemark (обоснованный возврат),
  stampProvenance (turn+session по тексту), reconcileTurn (вызов->сторож->до 2 возвратов)
- stop-хук: вместо applyExtraction вызывает reconcileTurn; мотор инъектируется
- renderProtocol: зачёркивание во ВСЕХ разделах (закрытые вопросы видны ~~struck~~)
- ретайр: applyExtraction/buildExtractionPrompt/parseExtractionResponse (secretary-extract удалён)
- Слой 1, провенанс @session, флажок по сессии, оглавление — без изменений
- спека + план reconcile в docs/superpowers

33 теста green (мотор замокан, без сети). Модель для prod — Sonnet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 10:54:20 +03:00

33 lines
1.6 KiB
JavaScript

// Структура и сверка короткого протокола (§D5/§D7). Отменённое зачёркивается, не удаляется.
export function EMPTY_PROTOCOL() {
return { subject: '', decisions: [], will: [], open: [], doneNext: [], history: [] };
}
function prov(turns) {
return Array.isArray(turns) && turns.length ? ` [${turns.map((t) => `${t}`).join(', ')}]` : '';
}
// Навигация в Слой 1: метка сессии рядом с [→N] → искать raw/<session>.log, "=== ХОД turn=N ===".
function src(entry) {
return entry && entry.session ? ` @${String(entry.session).slice(0, 8)}` : '';
}
export function renderProtocol(protocol) {
const L = [];
L.push('## Решения');
for (const d of protocol.decisions) {
const body = d.struck ? `~~${d.text}~~` : d.text;
const why = d.why ? `${d.why}` : '';
L.push(`- ${body}${why}${prov(d.turns)}${src(d)}`);
}
L.push('', '## Твоя воля / запреты');
for (const w of protocol.will) L.push(`- ${w.struck ? `~~${w.text}~~` : w.text}${prov(w.turns)}${src(w)}`);
L.push('', '## Открытые вопросы');
for (const o of protocol.open) L.push(`- ${o.struck ? `~~${o.text}~~` : o.text}${prov(o.turns)}${src(o)}`);
L.push('', '## Сделано / дальше');
for (const s of protocol.doneNext) L.push(`- [${s.done ? 'x' : ' '}] ${s.struck ? `~~${s.text}~~` : s.text}${prov(s.turns)}${src(s)}`);
L.push('', '## История (заменено, не стёрто)');
for (const h of protocol.history) L.push(`- ~~${h.oldText}~~ → ${h.newText}${prov(h.turns)}`);
return L.join('\n');
}