71 lines
2.8 KiB
JavaScript
71 lines
2.8 KiB
JavaScript
|
|
#!/usr/bin/env node
|
||
|
|
/**
|
||
|
|
* check-gray-expiry.js · 2026-04-25
|
||
|
|
* UserPromptSubmit hook. Scans state/gray-observations/*.json, if any expired
|
||
|
|
* emits prominent banner via additionalContext so user & AI see it on session start.
|
||
|
|
*/
|
||
|
|
'use strict';
|
||
|
|
const fs = require('fs');
|
||
|
|
const path = require('path');
|
||
|
|
|
||
|
|
const ROOT = path.resolve(__dirname, '..');
|
||
|
|
const DIR = path.join(ROOT, 'state', 'gray-observations');
|
||
|
|
|
||
|
|
function loadObservations() {
|
||
|
|
if (!fs.existsSync(DIR)) return [];
|
||
|
|
const out = [];
|
||
|
|
for (const name of fs.readdirSync(DIR)) {
|
||
|
|
if (!name.endsWith('.json')) continue;
|
||
|
|
try {
|
||
|
|
const j = JSON.parse(fs.readFileSync(path.join(DIR, name), 'utf8'));
|
||
|
|
j._file = name;
|
||
|
|
out.push(j);
|
||
|
|
} catch (_) {}
|
||
|
|
}
|
||
|
|
return out;
|
||
|
|
}
|
||
|
|
|
||
|
|
function main() {
|
||
|
|
const now = Date.now();
|
||
|
|
const obs = loadObservations();
|
||
|
|
const expired = obs.filter(o => {
|
||
|
|
if (o.resolved) return false;
|
||
|
|
const exp = new Date(o.expires_at).getTime();
|
||
|
|
return Number.isFinite(exp) && exp <= now;
|
||
|
|
});
|
||
|
|
if (expired.length === 0) process.exit(0);
|
||
|
|
|
||
|
|
const lines = [];
|
||
|
|
lines.push('');
|
||
|
|
lines.push('╔══════════════════════════════════════════════════════════════╗');
|
||
|
|
lines.push('║ ⚠️ 灰度观察到期提醒 · GRAY OBSERVATION EXPIRED ║');
|
||
|
|
lines.push('╠══════════════════════════════════════════════════════════════╣');
|
||
|
|
for (const o of expired) {
|
||
|
|
lines.push('║ ID: ' + (o.observation_id || o._file).padEnd(56) + '║');
|
||
|
|
lines.push('║ 到期: ' + (o.expires_at || '').slice(0, 19).padEnd(54) + '║');
|
||
|
|
if (o.watched_flag) lines.push('║ 关注 flag: ' + String(o.watched_flag).padEnd(50) + '║');
|
||
|
|
if (o.on_expiry_action) {
|
||
|
|
const act = String(o.on_expiry_action);
|
||
|
|
for (let i = 0; i < act.length; i += 58) {
|
||
|
|
lines.push('║ → ' + act.slice(i, i + 58).padEnd(58) + '║');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
lines.push('║' + ' '.repeat(62) + '║');
|
||
|
|
}
|
||
|
|
lines.push('║ 建议: 查看 manifest.jsonl 统计 → 决定 warn→enforce 升级 ║');
|
||
|
|
lines.push('║ 解决后: resolved:true 写入对应 .json 停止提醒 ║');
|
||
|
|
lines.push('╚══════════════════════════════════════════════════════════════╝');
|
||
|
|
lines.push('');
|
||
|
|
|
||
|
|
const output = {
|
||
|
|
hookSpecificOutput: {
|
||
|
|
hookEventName: 'UserPromptSubmit',
|
||
|
|
additionalContext: lines.join('\n'),
|
||
|
|
},
|
||
|
|
};
|
||
|
|
process.stdout.write(JSON.stringify(output));
|
||
|
|
process.exit(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
try { main(); } catch (_) { process.exit(0); }
|