#!/usr/bin/env node /** * patch-x08-heartbeat-atomic-write.js * 修复 session-heartbeat.js 第80行 writeFileSync → tmp+rename 原子写 * 同步修复 pre-compact-handoff.js 第50行 heartbeat 写入 * * 幂等: SENTINEL 标记 */ 'use strict'; const fs = require('fs'); const path = require('path'); const SENTINEL = '[PATCH-X08-ATOMIC-WRITE]'; const HOOKS_DIR = path.join(__dirname, '..', '..', 'hooks'); let patchCount = 0; // === 1. session-heartbeat.js === const HB_PATH = path.join(HOOKS_DIR, 'session-heartbeat.js'); if (fs.existsSync(HB_PATH)) { let src = fs.readFileSync(HB_PATH, 'utf8'); if (src.includes(SENTINEL)) { console.log('SKIP: session-heartbeat already patched'); } else { const old = " fs.writeFileSync(STATE_FILE, JSON.stringify(allState), 'utf8');"; const replacement = [ " const _tmpHb = STATE_FILE + '.tmp.' + process.pid; // " + SENTINEL, " fs.writeFileSync(_tmpHb, JSON.stringify(allState), 'utf8');", " fs.renameSync(_tmpHb, STATE_FILE);" ].join('\n'); if (!src.includes(old)) { console.error('FAIL: session-heartbeat old pattern not found'); process.exit(1); } src = src.replace(old, replacement); const tmp = HB_PATH + '.tmp.' + process.pid; fs.writeFileSync(tmp, src, 'utf8'); fs.renameSync(tmp, HB_PATH); patchCount++; console.log('OK: session-heartbeat atomic write patched'); } } // === 2. pre-compact-handoff.js heartbeat 写入 === const PCH_PATH = path.join(HOOKS_DIR, 'pre-compact-handoff.js'); if (fs.existsSync(PCH_PATH)) { let src = fs.readFileSync(PCH_PATH, 'utf8'); // 查找 heartbeat 区域的非原子写 (不含 X13 的 handoff.json 那个) const oldHb = " fs.writeFileSync(heartbeatPath, JSON.stringify(hbAll), 'utf8');"; if (src.includes(SENTINEL)) { console.log('SKIP: pre-compact-handoff heartbeat already patched'); } else if (src.includes(oldHb)) { const newHb = [ " const _tmpPch = heartbeatPath + '.tmp.' + process.pid; // " + SENTINEL, " fs.writeFileSync(_tmpPch, JSON.stringify(hbAll), 'utf8');", " fs.renameSync(_tmpPch, heartbeatPath);" ].join('\n'); src = src.replace(oldHb, newHb); const tmp = PCH_PATH + '.tmp.' + process.pid; fs.writeFileSync(tmp, src, 'utf8'); fs.renameSync(tmp, PCH_PATH); patchCount++; console.log('OK: pre-compact-handoff heartbeat atomic write patched'); } else { console.log('SKIP: pre-compact-handoff heartbeat pattern not found (may already be patched)'); } } console.log('DONE: ' + patchCount + ' files patched');