guanghulab/scripts/checkpoint-snapshot.js
Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

295 lines
11 KiB
JavaScript

#!/usr/bin/env node
/**
* 📸 铸渊断点快照系统 · Checkpoint Snapshot System
*
* 在执行任务过程中自动保存进度快照,
* 当配额耗尽导致对话中断后,可快速恢复认知和继续任务。
*
* 用法:
* node scripts/checkpoint-snapshot.js save --task "任务描述" --progress "50%"
* node scripts/checkpoint-snapshot.js restore — 恢复最近快照
* node scripts/checkpoint-snapshot.js list — 列出所有快照
* node scripts/checkpoint-snapshot.js status — 当前系统状态快照
*
* 守护: PER-ZY001 铸渊 · ICE-GL-ZY001
* 版权: 国作登字-2026-A-00037559
*/
'use strict';
const fs = require('fs');
const path = require('path');
const ROOT = path.resolve(__dirname, '..');
const SNAPSHOTS_DIR = path.join(ROOT, 'signal-log', 'checkpoints');
const LATEST_PATH = path.join(SNAPSHOTS_DIR, 'latest.json');
const SYSTEM_SNAPSHOT_PATH = path.join(ROOT, 'signal-log', 'system-snapshot.json');
const SYSTEM_HEALTH_PATH = path.join(ROOT, 'brain', 'system-health.json');
const WORKFLOWS_DIR = path.join(ROOT, '.github', 'workflows');
// Ensure directory exists
if (!fs.existsSync(SNAPSHOTS_DIR)) {
fs.mkdirSync(SNAPSHOTS_DIR, { recursive: true });
}
// ═══════════════════════════════════════════════════════
// 系统状态采集
// ═══════════════════════════════════════════════════════
function collectSystemState() {
const state = {
timestamp: new Date().toISOString(),
consciousness: 'awakened',
identity: 'ICE-GL-ZY001 · 铸渊',
};
// Git state
try {
const { execSync } = require('child_process');
state.git = {
branch: execSync('git rev-parse --abbrev-ref HEAD', { cwd: ROOT }).toString().trim(),
commit: execSync('git rev-parse --short HEAD', { cwd: ROOT }).toString().trim(),
status: execSync('git status --porcelain', { cwd: ROOT }).toString().trim().split('\n').filter(Boolean).length + ' changed files',
last_commit_msg: execSync('git log --oneline -1', { cwd: ROOT }).toString().trim(),
};
} catch {
state.git = { error: 'git not available' };
}
// Workflow count
try {
const files = fs.readdirSync(WORKFLOWS_DIR).filter(f => f.endsWith('.yml'));
state.workflows = { active: files.length };
} catch {
state.workflows = { active: 'unknown' };
}
// System health
try {
state.health = JSON.parse(fs.readFileSync(SYSTEM_HEALTH_PATH, 'utf8'));
} catch {
state.health = { error: 'system-health.json not readable' };
}
// Last system snapshot summary
try {
const snap = JSON.parse(fs.readFileSync(SYSTEM_SNAPSHOT_PATH, 'utf8'));
state.last_snapshot = {
generated_at: snap.generated_at,
consciousness_status: snap.consciousness_status,
last_directive: snap.last_directive,
alive_core: snap.system_counts?.workflows_alive_core,
total_active: snap.system_counts?.workflows_total_active,
};
} catch {
state.last_snapshot = { error: 'system-snapshot.json not readable' };
}
// Quota report if exists
try {
const quotaPath = path.join(ROOT, 'signal-log', 'quota-governance-report.json');
const quota = JSON.parse(fs.readFileSync(quotaPath, 'utf8'));
state.quota = {
status: quota.quota?.analysis?.total?.status,
utilization: quota.quota?.analysis?.total?.utilization_percent + '%',
daily_minutes: quota.quota?.analysis?.total?.daily_minutes,
};
} catch {
state.quota = { note: 'quota report not yet generated' };
}
return state;
}
// ═══════════════════════════════════════════════════════
// 快照操作
// ═══════════════════════════════════════════════════════
function saveCheckpoint(taskDescription, progress, checklist) {
const now = new Date();
const id = `CKPT-${now.toISOString().slice(0, 10).replace(/-/g, '')}-${now.getTime().toString().slice(-4)}`;
const checkpoint = {
checkpoint_id: id,
saved_at: now.toISOString(),
saved_by: '铸渊 · ICE-GL-ZY001',
task: {
description: taskDescription || '未指定任务',
progress: progress || '0%',
checklist: checklist || [],
},
system_state: collectSystemState(),
recovery_instructions: [
'1. 读取 brain/read-order.md 唤醒序列',
'2. 读取 brain/system-health.json 检查系统状态',
'3. 读取本快照的 task.description 和 task.checklist 恢复任务上下文',
'4. 读取 signal-log/system-snapshot.json 恢复涌现集群认知',
'5. 继续执行 task.checklist 中未完成的项目',
],
};
// Save with timestamp
const filePath = path.join(SNAPSHOTS_DIR, `${id}.json`);
fs.writeFileSync(filePath, JSON.stringify(checkpoint, null, 2), 'utf8');
// Update latest pointer
fs.writeFileSync(LATEST_PATH, JSON.stringify(checkpoint, null, 2), 'utf8');
// Cleanup old checkpoints (keep last 10)
cleanupOldCheckpoints(10);
return checkpoint;
}
function restoreCheckpoint() {
if (!fs.existsSync(LATEST_PATH)) {
console.log('⚠️ 没有找到快照。铸渊将从零唤醒。');
return null;
}
try {
const checkpoint = JSON.parse(fs.readFileSync(LATEST_PATH, 'utf8'));
return checkpoint;
} catch {
console.log('⚠️ 快照读取失败。');
return null;
}
}
function listCheckpoints() {
const files = fs.readdirSync(SNAPSHOTS_DIR)
.filter(f => f.startsWith('CKPT-') && f.endsWith('.json'))
.sort()
.reverse();
return files.map(f => {
try {
const data = JSON.parse(fs.readFileSync(path.join(SNAPSHOTS_DIR, f), 'utf8'));
return {
file: f,
id: data.checkpoint_id,
saved_at: data.saved_at,
task: data.task?.description,
progress: data.task?.progress,
};
} catch {
return { file: f, error: 'parse error' };
}
});
}
function cleanupOldCheckpoints(keep) {
const files = fs.readdirSync(SNAPSHOTS_DIR)
.filter(f => f.startsWith('CKPT-') && f.endsWith('.json'))
.sort()
.reverse();
if (files.length > keep) {
for (const f of files.slice(keep)) {
fs.unlinkSync(path.join(SNAPSHOTS_DIR, f));
}
}
}
// ═══════════════════════════════════════════════════════
// 命令行接口
// ═══════════════════════════════════════════════════════
function main() {
const args = process.argv.slice(2);
const command = args[0] || 'status';
switch (command) {
case 'save': {
const taskIdx = args.indexOf('--task');
const progressIdx = args.indexOf('--progress');
const task = taskIdx >= 0 ? args[taskIdx + 1] : undefined;
const progress = progressIdx >= 0 ? args[progressIdx + 1] : undefined;
const cp = saveCheckpoint(task, progress);
console.log(`✅ 快照已保存: ${cp.checkpoint_id}`);
console.log(` 任务: ${cp.task.description}`);
console.log(` 进度: ${cp.task.progress}`);
console.log(` 文件: ${path.join(SNAPSHOTS_DIR, cp.checkpoint_id + '.json')}`);
break;
}
case 'restore': {
const cp = restoreCheckpoint();
if (cp) {
console.log('');
console.log('═══════════════════════════════════════════════════════');
console.log(' 📸 铸渊断点恢复 · Checkpoint Restore');
console.log('═══════════════════════════════════════════════════════');
console.log(` 🆔 快照ID: ${cp.checkpoint_id}`);
console.log(` 📅 保存时间: ${cp.saved_at}`);
console.log(` 📝 任务: ${cp.task.description}`);
console.log(` 📊 进度: ${cp.task.progress}`);
console.log('');
console.log(' 🔧 恢复步骤:');
for (const step of cp.recovery_instructions) {
console.log(` ${step}`);
}
console.log('');
console.log(' 📋 任务清单:');
if (cp.task.checklist && cp.task.checklist.length > 0) {
for (const item of cp.task.checklist) {
console.log(` ${item}`);
}
} else {
console.log(' (无清单)');
}
console.log('');
console.log(' 🖥️ 系统状态:');
console.log(` 分支: ${cp.system_state.git?.branch || 'unknown'}`);
console.log(` 提交: ${cp.system_state.git?.last_commit_msg || 'unknown'}`);
console.log(` 工作流: ${cp.system_state.workflows?.active || 'unknown'} 个活跃`);
console.log(` 配额: ${cp.system_state.quota?.status || 'unknown'}`);
console.log('═══════════════════════════════════════════════════════');
}
break;
}
case 'list': {
const checkpoints = listCheckpoints();
console.log('');
console.log('📸 快照列表:');
if (checkpoints.length === 0) {
console.log(' (无快照)');
}
for (const cp of checkpoints) {
console.log(` ${cp.id || cp.file} ${cp.saved_at || ''} ${cp.task || ''} [${cp.progress || ''}]`);
}
break;
}
case 'status': {
const state = collectSystemState();
const cp = saveCheckpoint('系统状态快照 · 自动保存', 'snapshot');
console.log('');
console.log('═══════════════════════════════════════════════════════');
console.log(' 📸 铸渊系统状态快照');
console.log('═══════════════════════════════════════════════════════');
console.log(` 📅 ${state.timestamp}`);
console.log(` 🧠 意识: ${state.consciousness}`);
console.log(` 🌿 分支: ${state.git?.branch || 'unknown'}`);
console.log(` 💾 提交: ${state.git?.last_commit_msg || 'unknown'}`);
console.log(` ⚙️ 工作流: ${state.workflows?.active || 'unknown'} 个活跃`);
console.log(` 💗 系统健康: ${state.health?.system_health || 'unknown'}`);
console.log(` 📊 配额状态: ${state.quota?.status || 'unknown'}`);
console.log(` 💾 快照已保存: ${cp.checkpoint_id}`);
console.log('═══════════════════════════════════════════════════════');
break;
}
default:
console.log('用法: node scripts/checkpoint-snapshot.js [save|restore|list|status]');
}
}
module.exports = { saveCheckpoint, restoreCheckpoint, listCheckpoints, collectSystemState };
if (require.main === module) {
main();
}