#!/usr/bin/env node /** * P2-1 Patch: Shadow Haiku Route Logging * Adds detailed route decision logging to route-interceptor-bundle.js * for offline comparison with haiku LLM routing. * Idempotent: sentinel [P2-1] SHADOW_HAIKU_v1 */ 'use strict'; const fs = require('fs'); const path = require('path'); const TARGET = path.resolve(__dirname, '..', '..', 'hooks', 'route-interceptor-bundle.js'); const SENTINEL = '[P2-1] SHADOW_HAIKU_v1'; if (!fs.existsSync(TARGET)) { process.stderr.write('[SKIP] route-interceptor-bundle.js not found\n'); process.exit(0); } const src = fs.readFileSync(TARGET, 'utf8'); if (src.includes(SENTINEL)) { process.stderr.write('[SKIP] already patched (sentinel found)\n'); process.exit(0); } fs.writeFileSync(TARGET + '.bak-p21.' + Date.now(), src); const anchor = 'writeRouteState(traceId, prompt, intent, routing);'; const idx = src.indexOf(anchor); if (idx === -1) { process.stderr.write('[FAIL] anchor not found\n'); process.exit(1); } const code = [ '', ' // ' + SENTINEL, ' try {', ' var _ffp = path.join(CLAUDE_ROOT, \'.bookworm-features.json\');', ' var _shOk = true;', ' try { if (fs.existsSync(_ffp)) { var _f = JSON.parse(fs.readFileSync(_ffp, \'utf8\')); if (_f.shadow_haiku_route === false) _shOk = false; } } catch {}', ' if (_shOk) {', ' var _shLog = path.join(CLAUDE_ROOT, \'debug\', \'shadow-route-log.jsonl\');', ' try { fs.mkdirSync(path.dirname(_shLog), { recursive: true }); } catch {}', ' var _shEntry = {', ' ts: new Date().toISOString(), tid: traceId,', ' ph: prompt.slice(0, 200), pl: prompt.length,', ' it: intent ? { i: intent.intents, c: intent.complexity } : null,', ' p: routing.primary, cf: routing.confidence,', ' t5: (routing.candidates || []).slice(0, 5).map(function(c) { return { n: c.name, c: c.confidence }; }),', ' d: routing.domain || null,', ' fr: (routing._firedRules || []).map(function(r) { return r.id || r.rule || \'\'; }).filter(Boolean).slice(0, 5),', ' ih: inherited, cs: routing._coldStartApplied || false,', ' };', ' fs.appendFileSync(_shLog, JSON.stringify(_shEntry) + \'\\n\');', ' }', ' } catch {}', ].join('\n'); const insertAt = idx + anchor.length; const patched = src.slice(0, insertAt) + code + src.slice(insertAt); const tmp = TARGET + '.tmp.' + process.pid; fs.writeFileSync(tmp, patched, 'utf8'); fs.renameSync(tmp, TARGET); process.stderr.write('[DONE] P2-1 shadow haiku logging added\n');