Files
portal/tools/router-exploration.mjs
T

35 lines
2.2 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
/**
* router-exploration — ручка «% разведки» (#3 крит-разбор). По умолчанию ВЫКЛючена
* (rate=0) — анти-самоослепление петли обучения предусмотрено СЛОТОМ, но включается
* позже. Проба нового узла = ВОПРОС владельцу с обоснованием+риском (никогда авто;
* наполняется только по «да», как 3.4/3.5). Высокорисковые узлы к пробе не предлагаются.
*/
export const DEFAULT_EXPLORATION = Object.freeze({ rate: 0 });
/** Счётчик использования узлов (для выбора наименее пробованного). */
export function tallyUsage(counts, nodeId) {
const c = { ...(counts || {}) };
c[nodeId] = (c[nodeId] || 0) + 1;
return c;
}
/**
* Предложить пробу наименее использованного узла. rate<=0 → null (выкл). Иначе среди
* кандидатов, НЕ высокорисковых (riskOf инъектируется), берём с минимальным счётчиком →
* вопрос владельцу (requiresOwnerApproval=true) с обоснованием+риском. Не применяет сам.
*/
export function proposeProbe({ rate = 0, usageCounts = {}, candidates = [], riskOf = () => false } = {}) {
if (!(rate > 0)) return null;
const eligible = candidates.filter((c) => !riskOf(c.id));
if (eligible.length === 0) return null;
const least = eligible.reduce((best, c) =>
(usageCounts[c.id] || 0) < (usageCounts[best.id] || 0) ? c : best, eligible[0]);
return {
probe: least.id,
requiresOwnerApproval: true,
justification: `узел ${least.id} почти не пробован (использований: ${usageCounts[least.id] || 0}) — разведка может найти лучший инструмент`,
risk: 'непроверенный узел может сработать хуже привычного; включается только по твоему «да»',
};
}