/** * 记忆固化触发决策测试(v0.7.3 P1-5) * * 锁定 shouldConsolidate 的四类判定:总开关 / 内容门控(回答长度 ∨ 成功工具调用)/ * 频率窗口(含首次不限)/ 配置兜底(非法数值回退安全下限)。 */ import { describe, it, expect } from 'vitest'; import { shouldConsolidate, MIN_CONSOLIDATION_INTERVAL_MS, MIN_CONSOLIDATION_MIN_CHARS, } from '../consolidation-policy'; const BASE = { enabled: true, answerChars: 500, minChars: 200, hadSuccessfulToolCall: false, lastConsolidationAt: 0, now: 1_000_000, intervalMs: 600_000, }; describe('shouldConsolidate', () => { it('总开关显式关闭 → disabled', () => { expect(shouldConsolidate({ ...BASE, enabled: false })).toEqual({ consolidate: false, reason: 'disabled', }); }); it('回答够长且首次固化 → 允许(lastConsolidationAt=0 不受频率限制)', () => { expect(shouldConsolidate(BASE)).toEqual({ consolidate: true, reason: 'content-and-frequency-pass', }); }); it('回答过短且无成功工具调用 → below-threshold(短寒暄不触发固化)', () => { expect(shouldConsolidate({ ...BASE, answerChars: 50, hadSuccessfulToolCall: false })).toEqual({ consolidate: false, reason: 'below-threshold', }); }); it('回答过短但存在成功工具调用 → 允许(事实性上下文可沉淀)', () => { expect(shouldConsolidate({ ...BASE, answerChars: 50, hadSuccessfulToolCall: true })).toEqual({ consolidate: true, reason: 'content-and-frequency-pass', }); }); it('频率窗口内重复触发 → throttled', () => { expect( shouldConsolidate({ ...BASE, lastConsolidationAt: BASE.now - 60_000, // 1 分钟前刚固化过 }), ).toEqual({ consolidate: false, reason: 'throttled' }); }); it('频率窗口已过 → 允许', () => { expect( shouldConsolidate({ ...BASE, lastConsolidationAt: BASE.now - 600_001, }), ).toEqual({ consolidate: true, reason: 'content-and-frequency-pass' }); }); it('配置兜底:minChars=0 不会让纯寒暄触发(安全下限生效)', () => { expect(shouldConsolidate({ ...BASE, minChars: 0, answerChars: 10 })).toEqual({ consolidate: false, reason: 'below-threshold', }); expect(MIN_CONSOLIDATION_MIN_CHARS).toBeGreaterThan(0); }); it('配置兜底:intervalMs=0 不会退化为每条消息固化(安全下限生效)', () => { expect( shouldConsolidate({ ...BASE, intervalMs: 0, lastConsolidationAt: BASE.now - 30_000, // 30 秒前刚固化 }), ).toEqual({ consolidate: false, reason: 'throttled' }); expect(MIN_CONSOLIDATION_INTERVAL_MS).toBeGreaterThanOrEqual(60_000); }); it('配置兜底:minChars/intervalMs 为 NaN 时按默认值处理', () => { expect(shouldConsolidate({ ...BASE, minChars: Number.NaN, intervalMs: Number.NaN })).toEqual({ consolidate: true, reason: 'content-and-frequency-pass', }); }); });