- VERSION file as authoritative version source - export.mjs reads VERSION with package.json fallback - bw-ota.ps1 DryRun mode for safe testing - auto-setup.ps1 bumped to v3.2.0 (Phase 8 OTA)
58 lines
2.6 KiB
JavaScript
58 lines
2.6 KiB
JavaScript
#!/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');
|