#!/usr/bin/env node 'use strict'; /** * SessionStart Memory Audit Hook * sentinel: SESSION_START_MEMORY_AUDIT_2026_04_25 * * 事件: UserPromptSubmit (Bookworm 无 SessionStart, 用 UserPromptSubmit + 日守卫) * 目的: 每日首次会话自动体检记忆文件健康度, 异常时作为 additionalContext 提醒 * * 预算: * - 今日已跑: <5ms (stamp 快速返回) * - 首次: <1000ms (memory-audit.js --json, execFileSync 3s timeout) * * 告警门槛 (静默默认, 命中才输出): * - orphan >= 3 目录有文件未索引 * - ghost >= 1 索引指向已删文件 * - health.score < 80 * * Feature flag: .bookworm-features.json.memory_audit=false 可关闭 * Fail-open: 任何异常 exit 0, 永不阻断用户输入 */ const fs = require('fs'); const path = require('path'); const os = require('os'); const HOME = process.env.USERPROFILE || process.env.HOME || os.homedir(); const CLAUDE_ROOT = process.env.CLAUDE_HOME || (fs.existsSync(path.join(HOME, '.claude')) ? path.join(HOME, '.claude') : HOME); const DEBUG_DIR = path.join(CLAUDE_ROOT, 'debug'); const STAMP_FILE = path.join(DEBUG_DIR, '.last-memory-audit'); const FEATURE_FLAGS_FILE = path.join(CLAUDE_ROOT, '.bookworm-features.json'); const AUDIT_TOOL = path.join( CLAUDE_ROOT, 'projects', 'C--Users-leesu', 'memory', '_tools', 'memory-audit.js' ); const TODAY = new Date().toISOString().slice(0, 10); function safeExit() { process.exit(0); } function main() { try { // [P0-2] SESSION_ONCE_v1 — 会话级去重 (<1ms) try { if (require('./lib/session-once.js').hasRun('memory-audit')) return safeExit(); } catch {} // Feature flag try { if (fs.existsSync(FEATURE_FLAGS_FILE)) { const flags = JSON.parse(fs.readFileSync(FEATURE_FLAGS_FILE, 'utf8')); if (flags && flags.memory_audit === false) return safeExit(); } } catch {} // 日级守卫 if (fs.existsSync(STAMP_FILE)) { try { const last = fs.readFileSync(STAMP_FILE, 'utf8').trim(); if (last === TODAY) return safeExit(); } catch {} } // 工具存在性 if (!fs.existsSync(AUDIT_TOOL)) return safeExit(); // 运行审计 const { execFileSync } = require('child_process'); let report; try { const result = execFileSync(process.execPath, [AUDIT_TOOL, '--json'], { timeout: 3000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], }); report = JSON.parse(result); } catch { return safeExit(); } // 更新 stamp (不管结果, 避免失败时每次会话都重试) try { fs.mkdirSync(DEBUG_DIR, { recursive: true }); fs.writeFileSync(STAMP_FILE, TODAY); // [P0-2] SESSION_ONCE_v1 try { require('./lib/session-once.js').markRun('memory-audit'); } catch {} } catch {} // 判断是否需要告警 const h = (report && report.health) || {}; const orphan = h.orphanCount || 0; const ghost = h.ghostCount || 0; const oversize = h.oversizeCount || 0; const score = typeof h.score === 'number' ? h.score : 100; const needs = (orphan >= 3) || (ghost >= 1) || (score < 80); if (!needs) return safeExit(); // 输出为 UserPromptSubmit 的 additionalContext const lines = [ '[memory-audit] 记忆系统需要关注:', ' score=' + score + '/100 | orphan=' + orphan + ' ghost=' + ghost + ' oversize=' + oversize, ' 运行: node projects/C--Users-leesu/memory/_tools/memory-audit.js', ' 一键归档 orphan: ... --fix', ]; console.log(lines.join('\n')); } catch { // fail-open } safeExit(); } if (require.main === module) main(); module.exports = { main };