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
@@ -6,7 +6,10 @@
|
||||
// - 周期性心跳(config.Background.IntervalSec),请求注入的运行时
|
||||
// 反思,并允许调用工具(与主人对话**同一套**工具面:同一个
|
||||
// loop / dispatcher / 能力注册表,见 thinker.go 的 LoopThinker),
|
||||
// 但默认不得发出 chat 风格的消息。
|
||||
// 但默认不得发出 chat 风格的消息。心跳周期**按当前时刻选**:
|
||||
// 落在安静窗口内降频到 config.Background.QuietIntervalSec,
|
||||
// 窗外回落 IntervalSec(design/12 §N A1/A3,见 heartbeat.go)。
|
||||
// 降频**只作用于周期性心跳**,事件驱动通路照旧立刻触发(§N A2)。
|
||||
// - 进程内总线上的异步事件(iot.device_update、
|
||||
// reminder.trigger、system.event),它们唤醒一轮思考。
|
||||
//
|
||||
@@ -211,6 +214,8 @@ func (b *Backthink) Start(ctx context.Context) {
|
||||
|
||||
b.log.Info("backthink started",
|
||||
"interval", b.cfg.Interval.String(),
|
||||
"quiet_interval", b.cfg.QuietInterval.String(),
|
||||
"quiet_interval_enabled", b.quietIntervalEnabled(),
|
||||
"quiet_hours", quietHoursLabel(b.cfg.QuietStartHour, b.cfg.QuietEndHour),
|
||||
"event_triggers", b.deps.Bus != nil,
|
||||
"session_id", b.sessionID)
|
||||
@@ -324,33 +329,6 @@ func (b *Backthink) shouldThink(tr Trigger) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// tickLoop 是心跳 goroutine。按裁决 07.4.4(design/12 §1),它在进程
|
||||
// 启动时立即思考一次——产出一句拟人化的启动问候——
|
||||
// 随后稳定为每 tick 一轮思考;ctx 被取消时
|
||||
// 退出。可接受的副作用是每次进程重启都会唤醒
|
||||
// 一轮即时思考。
|
||||
func (b *Backthink) tickLoop(ctx context.Context) {
|
||||
defer b.wg.Done()
|
||||
// 启动即思考:不等满一个心跳周期。已取消的上下文直接退出,不落一条失败的
|
||||
// 启动记录。
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
}
|
||||
b.think(ctx, startupTrigger())
|
||||
ticker := time.NewTicker(b.cfg.Interval)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-ticker.C:
|
||||
b.think(ctx, heartbeatTrigger())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// think 跑一轮无人值守的思考:调用运行时、读取用户
|
||||
// 状态、判断是否打扰、值得时推送并持久化记录。
|
||||
// 只要注入的 Thinker、StateProvider 与 Pusher
|
||||
|
||||
Reference in new issue
Block a user