#!/usr/bin/env node /** * patch-x11-x13-crlf-fix.js * 修复 X11 路径校验 + X13 handoff 原子写, CRLF 规范化 */ 'use strict'; const fs = require('fs'); const path = require('path'); const HOOKS_DIR = path.join(__dirname, '..', '..', 'hooks'); let total = 0; function patchFile(filePath, label, patches) { if (!fs.existsSync(filePath)) { console.log('SKIP ' + label + ': not found'); return; } let src = fs.readFileSync(filePath, 'utf8'); const hadCRLF = src.includes('\r\n'); let norm = src.replace(/\r\n/g, '\n'); for (const p of patches) { if (norm.includes(p.sentinel)) { console.log('SKIP ' + label + '/' + p.id + ': already patched'); continue; } if (!norm.includes(p.old)) { console.error('FAIL ' + label + '/' + p.id + ': old pattern not found'); process.exit(1); } norm = norm.replace(p.old, p.new); console.log('OK ' + p.id + ' applied'); total++; } if (hadCRLF) norm = norm.replace(/\n/g, '\r\n'); const tmp = filePath + '.tmp.' + process.pid; fs.writeFileSync(tmp, norm, 'utf8'); fs.renameSync(tmp, filePath); } // === X11: context-pressure-monitor.js 路径校验 === patchFile(path.join(HOOKS_DIR, 'context-pressure-monitor.js'), 'context-pressure-monitor', [{ id: 'X11', sentinel: '[PATCH-X11-PATH-VALIDATION]', old: `function findTranscript(hookData) { if (hookData.transcript_path && fs.existsSync(hookData.transcript_path)) { return hookData.transcript_path; } const sid = hookData.session_id; if (!sid || !fs.existsSync(PROJECTS_DIR)) return null;`, new: `function findTranscript(hookData) { // [PATCH-X11-PATH-VALIDATION] if (hookData.transcript_path) { const resolved = path.resolve(hookData.transcript_path); if (resolved.startsWith(CLAUDE_ROOT) && fs.existsSync(resolved)) { return resolved; } } const sid = hookData.session_id; if (!sid || /[\\/\\\\]/.test(sid) || !fs.existsSync(PROJECTS_DIR)) return null;` }]); // === X13: pre-compact-handoff.js handoff.json 原子写 === patchFile(path.join(HOOKS_DIR, 'pre-compact-handoff.js'), 'pre-compact-handoff', [{ id: 'X13', sentinel: '[PATCH-X13-HANDOFF-ATOMIC]', old: " fs.writeFileSync(HANDOFF_PATH, JSON.stringify(handoff, null, 2), 'utf8');", new: ` const _tmpHandoff = HANDOFF_PATH + '.tmp.' + process.pid; // [PATCH-X13-HANDOFF-ATOMIC] fs.writeFileSync(_tmpHandoff, JSON.stringify(handoff, null, 2), 'utf8'); fs.renameSync(_tmpHandoff, HANDOFF_PATH);` }]); console.log('DONE: ' + total + ' patches applied');