bookworm-smart-assistant/scripts/patches/patch-p2-handoff-mechanism.js
Bookworm Admin b7a8e29d21 release: v6.7.0 - OTA E2E test release
- VERSION file as authoritative version source
- export.mjs reads VERSION with package.json fallback
- bw-ota.ps1 DryRun mode for safe testing
- auto-setup.ps1 bumped to v3.2.0 (Phase 8 OTA)
2026-04-27 17:59:44 +08:00

133 lines
4.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* patch-p2-handoff-mechanism.js
*
* P2 /handoff 机制改造 patch:
* 1. context-pressure-monitor.js: CRITICAL 消息改为建议 /handoff
* 2. pre-compact-handoff.js: 添加过期 handoff 文件清理 (保留最新 5 个)
* 3. CLAUDE.md: 上下文管理节添加 /handoff 说明
* 4. SKILL-REGISTRY.md: 添加 handoff 技能条目 + 更新统计
*
* 幂等: 每处修改前检查 sentinel已 patch 则跳过
*/
'use strict';
const fs = require('fs');
const path = require('path');
const CLAUDE_ROOT = path.join(require('os').homedir(), '.claude');
const HOOKS_DIR = path.join(CLAUDE_ROOT, 'hooks');
const results = [];
function patchFile(filePath, label, patches) {
if (!fs.existsSync(filePath)) {
results.push(`[SKIP] ${label}: 文件不存在 ${filePath}`);
return false;
}
const bak = filePath + '.bak';
let content = fs.readFileSync(filePath, 'utf8');
let changed = false;
for (const p of patches) {
if (p.sentinel && content.includes(p.sentinel)) {
results.push(`[SKIP] ${label}/${p.name}: sentinel 已存在`);
continue;
}
if (p.find && !content.includes(p.find)) {
results.push(`[SKIP] ${label}/${p.name}: 未找到目标文本`);
continue;
}
if (p.find) {
content = content.replace(p.find, p.replace);
} else if (p.insertAfter) {
const idx = content.indexOf(p.insertAfter);
if (idx === -1) {
results.push(`[SKIP] ${label}/${p.name}: 未找到插入锚点`);
continue;
}
const insertAt = idx + p.insertAfter.length;
content = content.slice(0, insertAt) + p.insert + content.slice(insertAt);
}
changed = true;
results.push(`[OK] ${label}/${p.name}`);
}
if (changed) {
if (!fs.existsSync(bak)) fs.copyFileSync(filePath, bak);
fs.writeFileSync(filePath, content, 'utf8');
}
return changed;
}
// === 1. context-pressure-monitor.js: CRITICAL 消息 ===
patchFile(
path.join(HOOKS_DIR, 'context-pressure-monitor.js'),
'context-pressure-monitor',
[{
name: 'critical-msg-handoff',
sentinel: '/handoff',
find: 'dump 当前关键决策到 .bookworm-progress.md, 然后请用户 /clear',
replace: '调用 /handoff 保存当前进度到 .bookworm-progress.md, 然后请用户 /clear'
}]
);
// === 2. pre-compact-handoff.js: 添加过期 handoff 清理 ===
patchFile(
path.join(HOOKS_DIR, 'pre-compact-handoff.js'),
'pre-compact-handoff',
[{
name: 'cleanup-old-handoffs',
sentinel: 'PATCH-P2-HANDOFF-CLEANUP',
insertAfter: 'fs.renameSync(_tmpHandoff, HANDOFF_PATH);',
insert: `
// [PATCH-P2-HANDOFF-CLEANUP] 清理过期 handoff 时间戳文件, 保留最新 5 个
try {
const files = fs.readdirSync(SESSION_STATE_DIR)
.filter(f => /^handoff-\\d+\\.json$/.test(f))
.map(f => ({ name: f, time: parseInt(f.match(/\\d+/)[0], 10) }))
.sort((a, b) => b.time - a.time);
const toDelete = files.slice(5);
for (const f of toDelete) {
try { fs.unlinkSync(path.join(SESSION_STATE_DIR, f.name)); } catch {}
}
} catch {}
`
}]
);
// === 3. CLAUDE.md: 上下文管理节添加 /handoff ===
patchFile(
path.join(CLAUDE_ROOT, 'CLAUDE.md'),
'CLAUDE.md',
[{
name: 'handoff-doc',
sentinel: '/handoff',
insertAfter: '- 长会话(>20 轮工具调用)时主动建议 `/clear` 重置上下文',
insert: '\n- **主动交接** (P2): 上下文压力 CRITICAL 时自动建议 `/handoff`; 手动 `/handoff` 可随时调用, 将进度写入 `.bookworm-progress.md` + 生成继续提示词 + 清理过期 handoff JSON'
}]
);
// === 4. SKILL-REGISTRY.md: 添加 handoff 条目 ===
const registryPath = path.join(CLAUDE_ROOT, 'SKILL-REGISTRY.md');
patchFile(registryPath, 'SKILL-REGISTRY', [
{
name: 'add-handoff-entry',
sentinel: '| 102 | handoff',
insertAfter: '| 101 | mcp-prune | stable | MCP 剪枝分析工具 (Phase 1 · T1.4)。基于使用率识别低频 MCP 候选,生成剪枝 plan。永不自动修改 .claude.json。 |',
insert: '\n| 102 | handoff | stable | 上下文交接/进度保存/.bookworm-progress.md 生成/继续提示词 |'
},
{
name: 'update-skill-count',
sentinel: '95 (',
find: '- **总计**: 94 (',
replace: '- **总计**: 95 ('
}
]);
// === 输出摘要 ===
console.log('=== patch-p2-handoff-mechanism ===');
for (const r of results) console.log(r);
console.log('=== done ===');