#!/usr/bin/env node /** * 逃生舱状态管理 (Phase 0) * * 管理 /force, /checks, /reset 用户覆盖。 * * 状态文件: debug/user-overrides.json * 自动过期: 1 小时(匹配 session-memory.js MAX_SESSION_AGE) * /force: 单次生效(compliance-gate 放行后自动清除) * /checks off: 会话级(手动 /checks on 或 /reset 或过期后恢复) */ const fs = require('fs'); const path = require('path'); // 路径解析 let overridesPath, debugDir; try { const { PATHS } = require('./paths.config.js'); overridesPath = PATHS.userOverridesJson; debugDir = PATHS.debugDir; } catch { const root = path.resolve(__dirname, '..'); debugDir = path.join(root, 'debug'); overridesPath = path.join(debugDir, 'user-overrides.json'); } const MAX_AGE_MS = 60 * 60 * 1000; // 1 小时 // ─── 内部辅助 ───────────────────────────────────────── function ensureDir() { try { if (!fs.existsSync(debugDir)) fs.mkdirSync(debugDir, { recursive: true }); } catch {} } /** * 读取覆盖状态(检查过期) * @returns {Object} overrides 状态 */ function readState() { try { if (!fs.existsSync(overridesPath)) return null; const raw = fs.readFileSync(overridesPath, 'utf8'); const state = JSON.parse(raw); // 检查过期 if (state.expiresAt && new Date(state.expiresAt).getTime() < Date.now()) { // 过期 → 清除文件 try { fs.unlinkSync(overridesPath); } catch {} return null; } return state; } catch { return null; } } /** * 写入覆盖状态 * @param {Object} overrides - { force, checksOff, forceSkill } */ function writeState(overrides) { ensureDir(); const now = new Date(); const state = { createdAt: now.toISOString(), expiresAt: new Date(now.getTime() + MAX_AGE_MS).toISOString(), overrides: { force: overrides.force || false, checksOff: overrides.checksOff || false, forceSkill: overrides.forceSkill || null, }, }; fs.writeFileSync(overridesPath, JSON.stringify(state, null, 2) + '\n'); } // ─── 公开 API ───────────────────────────────────────── /** * 设置 force 模式(单次生效) * @param {string} [skillName] - 可选指定技能 */ function setForce(skillName) { const current = readState(); const overrides = current ? current.overrides : { force: false, checksOff: false, forceSkill: null }; overrides.force = true; overrides.forceSkill = skillName || null; writeState(overrides); } /** * 设置 checks 开关 * @param {boolean} enabled - true=开启检查, false=关闭检查 */ function setChecks(enabled) { const current = readState(); const overrides = current ? current.overrides : { force: false, checksOff: false, forceSkill: null }; overrides.checksOff = !enabled; writeState(overrides); } /** * 重置所有覆盖 */ function resetAll() { try { if (fs.existsSync(overridesPath)) fs.unlinkSync(overridesPath); } catch {} } /** * 检查 force 是否激活 * @returns {{ active: boolean, skill?: string }} */ function isForceActive() { const state = readState(); if (!state || !state.overrides || !state.overrides.force) { return { active: false }; } return { active: true, skill: state.overrides.forceSkill || undefined }; } /** * 检查 checks 是否被关闭 * @returns {boolean} */ function isChecksDisabled() { const state = readState(); if (!state || !state.overrides) return false; return state.overrides.checksOff === true; } /** * 清除 force 标志(compliance-gate 放行后调用) */ function clearForce() { const state = readState(); if (!state || !state.overrides) return; state.overrides.force = false; state.overrides.forceSkill = null; writeState(state.overrides); } // ─── 导出 ───────────────────────────────────────────── module.exports = { setForce, setChecks, resetAll, isForceActive, isChecksDisabled, clearForce, }; // CLI: 直接运行时打印当前状态 if (require.main === module) { const state = readState(); console.log('=== User Overrides ==='); console.log(`Path: ${overridesPath}`); if (!state) { console.log('Status: No active overrides'); } else { console.log(`Created: ${state.createdAt}`); console.log(`Expires: ${state.expiresAt}`); console.log(`Force: ${state.overrides.force ? 'ON' + (state.overrides.forceSkill ? ` (${state.overrides.forceSkill})` : '') : 'OFF'}`); console.log(`Checks: ${state.overrides.checksOff ? 'DISABLED' : 'ENABLED'}`); } }