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:
1 parent
d6ed9cfa2b
commit
236b202fda
13 files changed
+633
-54
No files matched your search
@@ -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)
|
||||
}
|
||||
}
|
||||
+19
-11
@@ -216,18 +216,26 @@ type VoiceConfig struct {
|
||||
// single source shared by the backthink service and the channel bridge's
|
||||
// minimal-disturbance quiet-hours gate (design/12 §6 策略五). Equal non-zero hours
|
||||
// disable the window. The Push*/Kind fields tune the proactive-push frequency of
|
||||
// design/11 §6 + design/12 §6 and are mapped into backthink.Config.
|
||||
// design/11 §6 + design/12 §6 and are mapped into backthink.Config. QuietIntervalSec
|
||||
// 是安静窗口内的心跳周期(design/12 §N A1):窗口只降低**周期性心跳**的频率,
|
||||
// 事件驱动通路完全不受影响(§N A2)。
|
||||
type BackgroundConfig struct {
|
||||
Enabled bool `env:"ENABLE_BACKGROUND_THINKING" default:"true"`
|
||||
IntervalSec int `env:"THINK_INTERVAL_SEC" default:"900"`
|
||||
SilenceTimeout int `env:"THINK_SILENCE_TIMEOUT_SEC" default:"120"`
|
||||
QuietStartHour int `env:"QUIET_START_HOUR" default:"23"`
|
||||
QuietEndHour int `env:"QUIET_END_HOUR" default:"7"`
|
||||
PushLimit int `env:"THINK_PUSH_LIMIT" default:"1"`
|
||||
PushWindowSec int `env:"THINK_PUSH_WINDOW_SEC" default:"3600"`
|
||||
PushCooldownSec int `env:"THINK_PUSH_COOLDOWN_SEC" default:"1800"`
|
||||
RecentChatCooldownSec int `env:"THINK_RECENT_CHAT_COOLDOWN_SEC" default:"600"`
|
||||
KindWindowSec int `env:"THINK_KIND_WINDOW_SEC" default:"7200"`
|
||||
Enabled bool `env:"ENABLE_BACKGROUND_THINKING" default:"true"`
|
||||
IntervalSec int `env:"THINK_INTERVAL_SEC" default:"900"`
|
||||
// QuietIntervalSec 是**安静窗口内**的心跳周期(秒),默认 3600(1 小时):
|
||||
// 当前时刻落在安静时段(QuietStartHour–QuietEndHour)内时,心跳改用该间隔降频,
|
||||
// 窗外仍用 IntervalSec(design/12 §N A1)。**≤0 = 关闭降频**(回落 IntervalSec,
|
||||
// 语义唯一真源 = internal/services/backthink/heartbeat.go 的 heartbeatInterval);
|
||||
// 它不是「半夜完全不思考」的开关,见 design/12 §N A3。
|
||||
QuietIntervalSec int `env:"THINK_QUIET_INTERVAL_SEC" default:"3600"`
|
||||
SilenceTimeout int `env:"THINK_SILENCE_TIMEOUT_SEC" default:"120"`
|
||||
QuietStartHour int `env:"QUIET_START_HOUR" default:"23"`
|
||||
QuietEndHour int `env:"QUIET_END_HOUR" default:"7"`
|
||||
PushLimit int `env:"THINK_PUSH_LIMIT" default:"1"`
|
||||
PushWindowSec int `env:"THINK_PUSH_WINDOW_SEC" default:"3600"`
|
||||
PushCooldownSec int `env:"THINK_PUSH_COOLDOWN_SEC" default:"1800"`
|
||||
RecentChatCooldownSec int `env:"THINK_RECENT_CHAT_COOLDOWN_SEC" default:"600"`
|
||||
KindWindowSec int `env:"THINK_KIND_WINDOW_SEC" default:"7200"`
|
||||
}
|
||||
|
||||
// MemoryTidyConfig 是记忆整理(design/23-记忆整理与去重)的开关与配额旋钮。
|
||||
|
||||
Reference in new issue
Block a user