refactor(observer): этап 3 сноса цепочек L — снос chain-detector + chain-map + retrofill

Снята зависимость парсера транскрипта наблюдателя от машинерии L-цепочек:
- observer-transcript-parser больше не импортирует observer-chain-detector,
  не загружает observer-chain-map.json и не пишет primary_rationale.chain_ref;
- KNOWN_NODES больше не черпает имена из карты цепочек (источники: known-nodes.txt,
  маркер direct, форменные правила #NN и плагин:навык);
- удалены observer-chain-detector.mjs(+test), observer-chain-map.json,
  observer-retrofill-chain-ref.mjs(+test).

Граница не тронута: recommended_chain/recommended_node/chain_progress/chain_completed,
observer-stop-hook, командные цепочки, verifyChain. Полный свод зелёный.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-06-21 05:50:59 +03:00
parent c5af28f529
commit 7c728917c7
7 changed files with 1 additions and 232 deletions
+1 -12
View File
@@ -22,7 +22,6 @@ import { readRouterState, extractRouterFields, extractClassifierOutput } from '.
import { CLASSIFIER_MODEL } from './router-config.mjs';
import { homedir } from 'node:os';
import { detectChoiceProvenance, detectAskUserQuestionChoice } from './observer-choice-detector.mjs';
import { loadChainMap, chainsFor } from './observer-chain-detector.mjs';
import { buildHookMap, resolveScriptCounts } from './observer-hook-resolver.mjs';
// recommendNode / buildClassificationMap / buildDormancyMap были использованы
// для слепого fallback на heuristic recommended_node — убрано 2026-05-26
@@ -33,13 +32,6 @@ import { JUDGE_PER_CALL_USD } from './cost-pricing.mjs';
const __dirname = dirname(fileURLToPath(import.meta.url));
let CHAIN_MAP = null;
try {
CHAIN_MAP = loadChainMap();
} catch {
CHAIN_MAP = new Map(); // битый/отсутствующий JSON -> chainsFor вернёт null, observer не падает
}
let HOOK_MAP = null;
function getHookMap() {
if (HOOK_MAP) return HOOK_MAP;
@@ -57,7 +49,6 @@ function getHookMap() {
* the regex on its own would happily slurp into candidates_considered.
* Sources, in order:
* - tools/observer-known-nodes.txt — bare names (brainstorming, ccpm, …)
* - tools/observer-chain-map.json keys — incl. plugin:skill form
* - sentinel "direct" (no-skill marker used by node_chosen)
* Tooling IDs (#NN) and arbitrary plugin:skill forms pass via regex below.
*/
@@ -70,9 +61,8 @@ const KNOWN_NODES = (() => {
if (t) set.add(t);
}
} catch {
// file missing in some test sandboxes — fall back to chain-map keys only
// file missing in some test sandboxes — whitelist falls back to "direct" + regex shapes
}
if (CHAIN_MAP) for (const node of CHAIN_MAP.keys()) set.add(node);
return set;
})();
@@ -960,7 +950,6 @@ export function parseTranscript(transcriptText, fallbackSessionId = null, option
return {
step: 1,
node_chosen: skills.length > 0 ? skills[0] : 'direct',
chain_ref: chainsFor(skills.length > 0 ? skills[0] : 'direct', CHAIN_MAP),
triggers_matched: merge(extractTriggers(turn), tag ? tag.triggers : []),
candidates_considered: merge(extractCandidates(turn), tag ? tag.candidates : []),
boundaries_applied: merge(extractBoundaries(turn), tag ? tag.boundaries : []),