// active-days.mts —— 活跃会话日清单(供写盘桥的 /api/l1/active-days 调用) // // 为什么需要这个入口(2026-10-08 实测发现): // 查看器的质量分用"活跃会话日"时钟算衰减,而它原先只从 `l1/hit-stats.json` 侧车拿 `activeDays`。 // 侧车**只在命中统计库被打开/写入时才刷新**(无召回发生就不会重写),所以它可以比真实情况旧好几天。 // 实测差异:侧车 29 个活跃日,实际 30 个 —— 公式两边一致(parity 门禁全绿),但 `days` 差 1, // 于是 3 条记录从「冷」错标成「待观察」,且整个质量分直方图整体偏了一格。**静默偏移正是本次要根治的失效模式。** // // 所以权威来源是 `l0/conversations/` 目录本身(`loadActiveDayKeys` 的读取口径),由本入口透出, // 页面优先用它、侧车只作离线回退。规则不在这里重写 —— 只 import。 // // 输出:{ activeDays: ["YYYY-MM-DD", …], count, firstDay, lastDay, source } // 用法:node --experimental-strip-types scripts/l1-admin/active-days.mts [--profile ] import { argv, stdout } from "node:process"; import { loadActiveDayKeys } from "../../memory/l1/active-days.ts"; /** 取 `--flag value` 形式的值。 */ function flagValue(flag: string): string | undefined { const i = argv.indexOf(flag); return i >= 0 ? argv[i + 1] : undefined; } const PROFILE = flagValue("--profile") ?? "C:/Users/leaf/.pi/agent/profiles/default"; const keys = loadActiveDayKeys(PROFILE); // 一律用 process.exitCode 而非 exit():stdout 是管道时写入异步,立刻 exit 会截断 JSON。 stdout.write( `${JSON.stringify( { // undefined(l0/conversations 不存在或读不了)→ 空数组 + source="none", // 页面据此显式退化为日历天(而不是悄悄按"0 个活跃日"算出偏高的质量分) activeDays: keys ?? [], count: keys?.length ?? 0, firstDay: keys && keys.length > 0 ? keys[0] : null, lastDay: keys && keys.length > 0 ? keys[keys.length - 1] : null, source: "l0/conversations", available: Array.isArray(keys), }, null, 2, )}\n`, ); process.exitCode = 0;