feat(backthink): 静默时段心跳降频(A)—— THINK_QUIET_INTERVAL_SEC 默认 3600

主人裁定「先做 A(静默降频)再转向 C」;背景实测:静默期**思考频率不变**(恒定 900s 心跳),只拦打扰 ⇒ 成本照付。
- 新键 THINK_QUIET_INTERVAL_SEC(默认 3600):窗口内用该间隔、窗外仍用 THINK_INTERVAL_SEC;**≤0 = 关闭降频**(不许出现「半夜完全不思考」暗坑);窗口关闭/钟点非法 ⇒ 不降频
- 心跳**每拍按时刻选间隔**(放到循环外就永远不生效——变异实测能打红)
- 🔴 不变量:**事件驱动不被降频影响**(TestBackthink_EventTrigger_NotSlowedByQuietInterval 钉住)
- 事实卡 9→12 条(+思考总开关/普通间隔/静默间隔,标「改需重启」);契约形状未变、未升版
- ⚠️ 如实登记:ENABLE_BACKGROUND_THINKING 是**死配置**(全仓无消费者),已在 env/面板标签/契约三处标注,**是否接线待主人拍**
- 变异 5 条全红;C 的缺口清单(唤醒面 7 处)已回给主会话排期
This commit is contained in:
AskaEth committed 2026-10-05 22:38:17 +08:00
1 parent d6ed9cfa2b
commit 236b202fda
13 files changed
+633 -54

No files matched your search

+53
View File
@@ -0,0 +1,53 @@
package config
import (
"strings"
"testing"
)
// TestLoad_BackgroundThinkingDefaults 锁定后台思考心跳(design/12 §N A1)的 env
// 契约默认值:普通心跳 900s、安静窗口内心跳 3600s。后者必须与设计稿一致(1 小时),
// 否则「没配这个键」与「配了但解析失败」会走向不同的行为。
func TestLoad_BackgroundThinkingDefaults(t *testing.T) {
t.Setenv("JWT_SECRET", strings.Repeat("s", 40))
cfg, err := Load("")
if err != nil {
t.Fatalf("Load() error: %v", err)
}
got := cfg.Background
if !got.Enabled {
t.Error("ENABLE_BACKGROUND_THINKING 默认应为 true")
}
if got.IntervalSec != 900 {
t.Errorf("THINK_INTERVAL_SEC = %d, want 900", got.IntervalSec)
}
if got.QuietIntervalSec != 3600 {
t.Errorf("THINK_QUIET_INTERVAL_SEC = %d, want 3600(design/12 §N A1)", got.QuietIntervalSec)
}
if got.QuietStartHour != 23 || got.QuietEndHour != 7 {
t.Errorf("安静时段 = %d-%d, want 23-7", got.QuietStartHour, got.QuietEndHour)
}
}
// TestLoad_BackgroundThinkingEnvOverrides 锁定键名与类型:写进 .env 的旋钮真的生效
// (键名写错会静默沿用默认值,这类错误只能靠这条用例抓住)。
// `THINK_QUIET_INTERVAL_SEC=0` 是**合法值**(关闭降频,design/12 §N A3),因此它必须
// 原样解析成 0,不能被默认值覆盖。
func TestLoad_BackgroundThinkingEnvOverrides(t *testing.T) {
t.Setenv("JWT_SECRET", strings.Repeat("s", 40))
t.Setenv("THINK_INTERVAL_SEC", "1200")
t.Setenv("THINK_QUIET_INTERVAL_SEC", "0")
cfg, err := Load("")
if err != nil {
t.Fatalf("Load() error: %v", err)
}
if cfg.Background.IntervalSec != 1200 {
t.Fatalf("THINK_INTERVAL_SEC 未生效:%d", cfg.Background.IntervalSec)
}
if cfg.Background.QuietIntervalSec != 0 {
t.Fatalf("THINK_QUIET_INTERVAL_SEC=0 必须原样解析成 0(关闭降频),得到 %d",
cfg.Background.QuietIntervalSec)
}
}