bookworm-smart-assistant/scripts/patches/patch-x07-x08-x09-crlf-fix.js

92 lines
3.6 KiB
JavaScript
Raw Permalink Normal View History

#!/usr/bin/env node
/**
* patch-x07-x08-x09-crlf-fix.js
* 统一修复 X07/X08/X09使用 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);
}
// === X07: agent-isolation-gate.js seq 步长 ===
patchFile(path.join(HOOKS_DIR, 'agent-isolation-gate.js'), 'agent-isolation-gate', [{
id: 'X07',
sentinel: '[PATCH-X07-SEQ-STEP]',
old: ` const seqMatch = c.match(/\\bseq\\s+(\\d+)(?:\\s+(\\d+))?(?:\\s+(\\d+))?/);
if (seqMatch) {
const a = parseInt(seqMatch[1], 10);
const b = seqMatch[2] ? parseInt(seqMatch[2], 10) : null;
const z = seqMatch[3] ? parseInt(seqMatch[3], 10) : (b !== null ? b : a);
const n = b !== null && z !== null ? Math.max(0, z - a + 1) : a;
if (n >= 6) return { rule: 'B2', detail: 'seq ' + n };
}`,
new: ` const seqMatch = c.match(/\\bseq\\s+(\\d+)(?:\\s+(\\d+))?(?:\\s+(\\d+))?/); // [PATCH-X07-SEQ-STEP]
if (seqMatch) {
let n;
const g1 = parseInt(seqMatch[1], 10);
const g2 = seqMatch[2] ? parseInt(seqMatch[2], 10) : null;
const g3 = seqMatch[3] ? parseInt(seqMatch[3], 10) : null;
if (g3 !== null) {
const step = Math.max(1, g2);
n = Math.max(0, Math.floor((g3 - g1) / step) + 1);
} else if (g2 !== null) {
n = Math.max(0, g2 - g1 + 1);
} else {
n = g1;
}
if (n >= 6) return { rule: 'B2', detail: 'seq ' + n };
}`
}]);
// === X08: session-heartbeat.js 原子写 ===
patchFile(path.join(HOOKS_DIR, 'session-heartbeat.js'), 'session-heartbeat', [{
id: 'X08-hb',
sentinel: '[PATCH-X08-ATOMIC-WRITE]',
old: " fs.writeFileSync(STATE_FILE, JSON.stringify(allState), 'utf8');",
new: ` const _tmpHb = STATE_FILE + '.tmp.' + process.pid; // [PATCH-X08-ATOMIC-WRITE]
fs.writeFileSync(_tmpHb, JSON.stringify(allState), 'utf8');
fs.renameSync(_tmpHb, STATE_FILE);`
}]);
// === X08b: pre-compact-handoff.js heartbeat 原子写 ===
patchFile(path.join(HOOKS_DIR, 'pre-compact-handoff.js'), 'pre-compact-handoff', [{
id: 'X08-pch',
sentinel: '[PATCH-X08-ATOMIC-WRITE]',
old: " fs.writeFileSync(heartbeatPath, JSON.stringify(hbAll), 'utf8');",
new: ` const _tmpPch = heartbeatPath + '.tmp.' + process.pid; // [PATCH-X08-ATOMIC-WRITE]
fs.writeFileSync(_tmpPch, JSON.stringify(hbAll), 'utf8');
fs.renameSync(_tmpPch, heartbeatPath);`
}]);
// === X09: context-pressure-monitor.js CJK 范围 ===
patchFile(path.join(HOOKS_DIR, 'context-pressure-monitor.js'), 'context-pressure-monitor', [{
id: 'X09',
sentinel: '[PATCH-X09-CJK-KOREAN]',
old: " if (b >= 0xE3 && b <= 0xE9) cjk += 3;",
new: " if (b >= 0xE4 && b <= 0xED) cjk += 3; // [PATCH-X09-CJK-KOREAN]"
}]);
console.log('DONE: ' + total + ' patches applied');