134 lines
3.8 KiB
JavaScript
134 lines
3.8 KiB
JavaScript
#!/usr/bin/env node
|
||
/**
|
||
* Stop Hook 追加: 宪法违规会话摘要
|
||
* 读取 debug/detection-stats.json 中当天的违规统计
|
||
* 输出到 debug/constitution-report.jsonl
|
||
*
|
||
* Fail-open: 异常 → exit(0)
|
||
*/
|
||
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
const { safeAppendJsonl } = require('./lib/safe-append.js');
|
||
|
||
|
||
function main() {
|
||
try {
|
||
const root = require('./lib/root.js');
|
||
const debugDir = path.join(root, 'debug');
|
||
const statsFile = path.join(debugDir, 'detection-stats.json');
|
||
const reportFile = path.join(debugDir, 'constitution-report.jsonl');
|
||
const reminderFile = path.join(debugDir, 'constitution-reminder-session.json');
|
||
|
||
const today = new Date().toISOString().slice(0, 10);
|
||
let todayViolations = 0;
|
||
let ruleBreakdown = {};
|
||
|
||
// 从 detection-stats.json 读取当日统计
|
||
if (fs.existsSync(statsFile)) {
|
||
try {
|
||
const stats = JSON.parse(fs.readFileSync(statsFile, 'utf8'));
|
||
todayViolations = (stats.dailyTotals || {})[today] || 0;
|
||
for (const [ruleId, ruleData] of Object.entries(stats.rules || {})) {
|
||
const todayCount = (ruleData.last7days || {})[today] || 0;
|
||
if (todayCount > 0) {
|
||
ruleBreakdown[ruleId] = todayCount;
|
||
}
|
||
}
|
||
} catch {}
|
||
}
|
||
|
||
// 从 constitution-reminder-session.json 读取提醒统计
|
||
let filesReminded = 0;
|
||
if (fs.existsSync(reminderFile)) {
|
||
try {
|
||
const session = JSON.parse(fs.readFileSync(reminderFile, 'utf8'));
|
||
filesReminded = (session.reminded || []).length;
|
||
} catch {}
|
||
}
|
||
|
||
// 如果今天有违规或提醒,记录到报告
|
||
if (todayViolations > 0 || filesReminded > 0) {
|
||
const entry = {
|
||
ts: new Date().toISOString(),
|
||
date: today,
|
||
violations: todayViolations,
|
||
ruleBreakdown,
|
||
filesReminded,
|
||
};
|
||
|
||
safeAppendJsonl(reportFile, entry);
|
||
}
|
||
|
||
// 清理提醒会话文件 (Stop 时重置)
|
||
if (fs.existsSync(reminderFile)) {
|
||
try { fs.unlinkSync(reminderFile); } catch {}
|
||
}
|
||
} catch {}
|
||
|
||
process.exit(0);
|
||
}
|
||
|
||
/**
|
||
* 可导出的会话报告生成函数 (供 dispatcher 调用)
|
||
* 不调用 process.exit,直接执行逻辑
|
||
*/
|
||
function runReport() {
|
||
try {
|
||
const root = require('./lib/root.js');
|
||
const debugDir = path.join(root, 'debug');
|
||
const statsFile = path.join(debugDir, 'detection-stats.json');
|
||
const reportFile = path.join(debugDir, 'constitution-report.jsonl');
|
||
const reminderFile = path.join(debugDir, 'constitution-reminder-session.json');
|
||
|
||
const today = new Date().toISOString().slice(0, 10);
|
||
let todayViolations = 0;
|
||
let ruleBreakdown = {};
|
||
|
||
if (fs.existsSync(statsFile)) {
|
||
try {
|
||
const stats = JSON.parse(fs.readFileSync(statsFile, 'utf8'));
|
||
todayViolations = (stats.dailyTotals || {})[today] || 0;
|
||
for (const [ruleId, ruleData] of Object.entries(stats.rules || {})) {
|
||
const todayCount = (ruleData.last7days || {})[today] || 0;
|
||
if (todayCount > 0) {
|
||
ruleBreakdown[ruleId] = todayCount;
|
||
}
|
||
}
|
||
} catch {}
|
||
}
|
||
|
||
let filesReminded = 0;
|
||
if (fs.existsSync(reminderFile)) {
|
||
try {
|
||
const session = JSON.parse(fs.readFileSync(reminderFile, 'utf8'));
|
||
filesReminded = (session.reminded || []).length;
|
||
} catch {}
|
||
}
|
||
|
||
if (todayViolations > 0 || filesReminded > 0) {
|
||
const entry = {
|
||
ts: new Date().toISOString(),
|
||
date: today,
|
||
violations: todayViolations,
|
||
ruleBreakdown,
|
||
filesReminded,
|
||
};
|
||
safeAppendJsonl(reportFile, entry);
|
||
}
|
||
|
||
if (fs.existsSync(reminderFile)) {
|
||
try { fs.unlinkSync(reminderFile); } catch {}
|
||
}
|
||
} catch {}
|
||
}
|
||
|
||
// 模块导出 (供 dispatcher 和测试使用)
|
||
if (typeof module !== 'undefined') {
|
||
module.exports = { runReport };
|
||
}
|
||
|
||
if (require.main === module) {
|
||
main();
|
||
}
|