bookworm-smart-assistant/scripts/patches/patch-evo-log-dedup.js

96 lines
2.9 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
/**
* patch-evo-log-dedup.js
* P2 去噪: evolution-log.jsonl 去重 + seq 重编号
* 规则:
* - consistency-sentinel 同日同内容只保留首条
* - sig-drift(auto) fix_count>0 的保留
* - 所有条目按时间排序后重编号 seq
* Idempotent: sentinel 防重复
*/
'use strict';
const fs = require('fs');
const path = require('path');
const CLAUDE_ROOT = path.join(process.env.USERPROFILE || process.env.HOME, '.claude');
const EVO_LOG = path.join(CLAUDE_ROOT, 'evolution-log.jsonl');
const STATE_DIR = path.join(CLAUDE_ROOT, 'session-state');
const SENTINEL = path.join(STATE_DIR, 'patch-evo-log-dedup.done');
if (fs.existsSync(SENTINEL)) {
console.log('[SKIP] patch-evo-log-dedup already applied');
process.exit(0);
}
if (!fs.existsSync(EVO_LOG)) {
console.error('[FAIL] evolution-log.jsonl not found');
process.exit(1);
}
try {
const bak = EVO_LOG + '.bak-dedup-' + Date.now();
fs.copyFileSync(EVO_LOG, bak);
console.log('[OK] Backup: ' + path.basename(bak));
const raw = fs.readFileSync(EVO_LOG, 'utf8').trim();
const lines = raw.split('\n').map(l => { try { return JSON.parse(l); } catch { return null; } }).filter(Boolean);
const before = lines.length;
const kept = [];
const sentinelSeen = new Map();
for (const entry of lines) {
if (entry.scope === 'consistency-sentinel' && entry.trigger === 'stop-dispatcher') {
const key = entry.ts + '::' + entry.summary;
if (sentinelSeen.has(key)) continue;
const dayKey = entry.ts;
const dayEntries = lines.filter(e =>
e.scope === 'consistency-sentinel' && e.trigger === 'stop-dispatcher' && e.ts === dayKey
);
const hasSameDay = kept.some(e =>
e.scope === 'consistency-sentinel' && e.trigger === 'stop-dispatcher' && e.ts === dayKey
);
if (hasSameDay && (!entry.fix_count || entry.fix_count === 0)) {
sentinelSeen.set(key, true);
continue;
}
sentinelSeen.set(key, true);
}
kept.push(entry);
}
let seq = 1;
for (const entry of kept) {
entry.seq = seq++;
}
const output = kept.map(e => JSON.stringify(e)).join('\n') + '\n';
const tmp = EVO_LOG + '.tmp.' + process.pid;
fs.writeFileSync(tmp, output, 'utf8');
fs.renameSync(tmp, EVO_LOG);
const after = kept.length;
const removed = before - after;
console.log('[OK] evolution-log: ' + before + ' → ' + after + ' entries (removed ' + removed + ' duplicates)');
console.log('[OK] seq renumbered 1..' + after);
if (!fs.existsSync(STATE_DIR)) fs.mkdirSync(STATE_DIR, { recursive: true });
fs.writeFileSync(SENTINEL, JSON.stringify({
applied: new Date().toISOString(),
before: before,
after: after,
removed: removed,
backup: path.basename(bak)
}, null, 2), 'utf8');
console.log('[DONE] patch-evo-log-dedup applied');
} catch (err) {
console.error('[FAIL] ' + err.message);
process.exit(1);
}