feat(router): пининг совета роутера по goalHash (переписка шагов не зовёт LLM заново)
Новый router-pin-store: пин совета роутера по (task_id, goalHash) пер-сессионно. on-plan-write пин-aware: пин-попадание по неизменной цели → совет переиспользуется, classifyImpl НЕ зовётся; промах/смена цели → classify + сохранение пина. Проводка в активный наставник-хук инъекцией реального стора с sessionId (инъекция-выкл по умолчанию, старое поведение/тесты целы). Хвост спеки роутера §4 (пининг по goalHash), эпик роутер-реестр этап 3, item 2. Граница не тронута (recommended_chain, цепочки, observer-stop-hook, owner-seal). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+17
-5
@@ -48,6 +48,8 @@ export async function onPlanWrite({
|
||||
registry = null,
|
||||
declaredSkills = [],
|
||||
planGoal = '',
|
||||
pinLoadImpl = null,
|
||||
pinSaveImpl = null,
|
||||
roundMemory = {},
|
||||
} = {}) {
|
||||
const planHash = planId(planSteps);
|
||||
@@ -59,14 +61,24 @@ export async function onPlanWrite({
|
||||
}
|
||||
// Мерж роутер↔наставник: зовём classify() как функцию (мозг роутера цел). Сбой/недоступен →
|
||||
// recommendedChain=null → наставник судит план БЕЗ скил-сверки (fail-safe §5, не ложный NO-GO).
|
||||
// Пининг (спека роутер-реестр §4): пин-попадание по (taskId, goalHash) → совет переиспользуется,
|
||||
// classifyImpl НЕ зовётся; промах → classifyImpl + сохранение пина. Без пин-имплов — прежнее поведение.
|
||||
let recommendedChain = null;
|
||||
let routerClassification = null; // видимость: сырой результат classify наружу для снимка/баннера
|
||||
if (typeof classifyImpl === 'function') {
|
||||
try {
|
||||
const c = await classifyImpl(planGoal, registry);
|
||||
routerClassification = c ?? null;
|
||||
recommendedChain = recommendedChainOf(c);
|
||||
} catch { recommendedChain = null; routerClassification = { unavailable: true }; }
|
||||
let pinned = null;
|
||||
try { pinned = typeof pinLoadImpl === 'function' ? pinLoadImpl({ taskId, planGoal }) : null; } catch { pinned = null; }
|
||||
if (pinned) {
|
||||
routerClassification = pinned;
|
||||
recommendedChain = recommendedChainOf(pinned);
|
||||
} else {
|
||||
try {
|
||||
const c = await classifyImpl(planGoal, registry);
|
||||
routerClassification = c ?? null;
|
||||
recommendedChain = recommendedChainOf(c);
|
||||
if (c && typeof pinSaveImpl === 'function') { try { pinSaveImpl({ taskId, planGoal, classification: c }); } catch { /* best-effort */ } }
|
||||
} catch { recommendedChain = null; routerClassification = { unavailable: true }; }
|
||||
}
|
||||
}
|
||||
const skillContext = renderSkillContext({ declared: declaredSkills, recommendedChain, registry });
|
||||
// Производитель вердикта (C T5b): сбой → ok:false/wired:false (SE-R6-6, не суд).
|
||||
|
||||
Reference in New Issue
Block a user