#!/usr/bin/env node /** * P0-2 Patch: Hook Session-Once * - session-start-mcp-probe.js: 追加 session-once early-exit + markRun * - session-start-memory-audit.js: 追加 session-once early-exit + markRun * 幂等: sentinel [P0-2] SESSION_ONCE_v1 */ 'use strict'; const fs = require('fs'); const path = require('path'); const HOOKS = path.resolve(__dirname, '..', '..', 'hooks'); const SENTINEL = '[P0-2] SESSION_ONCE_v1'; function patchFile(name, fn) { const fp = path.join(HOOKS, name); if (!fs.existsSync(fp)) { process.stderr.write('[SKIP] ' + name + ' not found\n'); return false; } const src = fs.readFileSync(fp, 'utf8'); if (src.includes(SENTINEL)) { process.stderr.write('[SKIP] ' + name + ' already patched\n'); return false; } fs.writeFileSync(fp + '.bak-p02.' + Date.now(), src); const out = fn(src); const tmp = fp + '.tmp.' + process.pid; fs.writeFileSync(tmp, out, 'utf8'); fs.renameSync(tmp, fp); process.stderr.write('[DONE] ' + name + '\n'); return true; } // --- session-start-mcp-probe.js --- function patchMcpProbe(src) { // early-exit 插在 feature flag 检查之前 (main 函数第一行) const marker = ' // Feature flag 检查'; if (!src.includes(marker)) throw new Error('marker not found in mcp-probe'); const earlyExit = [ ' // ' + SENTINEL + ' — 会话级去重 (<1ms)', ' try { if (require(\'./lib/session-once.js\').hasRun(\'mcp-probe\')) return safeExit(); } catch {}', '', marker, ].join('\n'); let result = src.replace(marker, earlyExit); // markRun 插在原子写成功之后 const writeMarker = " fs.renameSync(tmp, HEALTH_FILE);"; if (!result.includes(writeMarker)) throw new Error('write marker not found'); result = result.replace( writeMarker, writeMarker + '\n // ' + SENTINEL + '\n try { require(\'./lib/session-once.js\').markRun(\'mcp-probe\'); } catch {}' ); return result; } // --- session-start-memory-audit.js --- function patchMemoryAudit(src) { // early-exit 插在 feature flag 之前 const marker = ' // Feature flag'; if (!src.includes(marker)) throw new Error('marker not found in memory-audit'); const earlyExit = [ ' // ' + SENTINEL + ' — 会话级去重 (<1ms)', ' try { if (require(\'./lib/session-once.js\').hasRun(\'memory-audit\')) return safeExit(); } catch {}', '', marker, ].join('\n'); let result = src.replace(marker, earlyExit); // markRun 插在 stamp 更新之后 const stampMarker = " fs.writeFileSync(STAMP_FILE, TODAY);"; if (!result.includes(stampMarker)) throw new Error('stamp marker not found'); result = result.replace( stampMarker, stampMarker + '\n // ' + SENTINEL + '\n try { require(\'./lib/session-once.js\').markRun(\'memory-audit\'); } catch {}' ); return result; } // --- Execute --- let count = 0; if (patchFile('session-start-mcp-probe.js', patchMcpProbe)) count++; if (patchFile('session-start-memory-audit.js', patchMemoryAudit)) count++; process.stderr.write('\nP0-2 Session-Once: ' + count + '/2 files patched\n');