feat(backthink): 自排 C1-2 本体 + TriggerUnknown 修 fail-open(V1)

- selfwake.go:WakeNow + 待跑槽容量 1(先探槽合并不过闸、槽空才过闸、同锁)+ 闸 4 轮/小时
  ($DATA_DIR/config/backthink.json,零新 env 键)+ 审计四条 what + 启动日志两键 + 组合根接线
- G-A(主人已批):TriggerUnknown 作零值、既有两值编号后移(语义不动),未知触发走**最紧分支**
- 5 个变异自检(拆闸/≤0 未回落/过闸挪到探槽前=G1 失效形态/槽无界/零值挪走)
⚠️ 服务侧已就绪但**她仍调不到**(自排工具面属 C1-3)⇒ 不得写「C 已完成」
This commit is contained in:
AskaEth committed 2026-10-06 20:25:04 +08:00
1 parent 301f8b4276
commit ed5005307a
12 files changed
+1193 -8

No files matched your search

+5
View File
@@ -159,6 +159,11 @@ func (a *app) wireFrontend() error {
if a.channelBridge != nil {
a.backthink.SetIMSink(a.channelBridge)
}
// design/12 §N C.5:自排的四个动作(queued/coalesced/capped/denied)走与渠道
// 黑名单拒绝同一条审计链(谁/什么/何时/结果),因此它们**面板可查**,不需要
// 新端点(GET /api/v1/admin/observability/audit 已存在)。同样是晚绑定:
// backthink.New 时网关还没组装。
a.backthink.SetAuditSink(gw)
}
return nil
}
+25 -1
View File
@@ -10,6 +10,7 @@ import (
"git.yeij.top/AskaEth/Cyrene_v2/internal/capability/registry"
"git.yeij.top/AskaEth/Cyrene_v2/internal/channel/session"
"git.yeij.top/AskaEth/Cyrene_v2/internal/config"
"git.yeij.top/AskaEth/Cyrene_v2/internal/config/runtimeconfig"
"git.yeij.top/AskaEth/Cyrene_v2/internal/iot"
"git.yeij.top/AskaEth/Cyrene_v2/internal/logger"
"git.yeij.top/AskaEth/Cyrene_v2/internal/platform"
@@ -66,7 +67,7 @@ func (a *app) wireAuxiliary() error {
}
a.automation = automation
bt, err := backthink.New(backthink.ConfigFromBackground(a.cfg.Background), backthink.Deps{
bt, err := backthink.New(a.backthinkTuning(), backthink.Deps{
Bus: a.bus,
Thinker: backthink.NewLoopThinker(a.loop, a.history),
Recent: a.history,
@@ -128,6 +129,29 @@ func (a *app) buildSkillFace() *loop.SkillFace {
})
}
// backthinkTuning 组装后台思考的调优配置:env 引导面(心跳周期 / 安静时段 / 推送频次)
// 由 ConfigFromBackground 映射,**自排成本闸**(design/12 §N C.5)从
// `$DATA_DIR/config/backthink.json` 读 —— 零新 env 键(主人 2026-10-06 `.env` 冻结红线)。
//
// 文件缺失/全空白 ⇒ 保持零值,由 backthink 的 normalize 回落代码默认(4 轮/小时;
// 「≤0 回落默认」在服务侧统一执行,这里不再造第二套默认值)。存在却解不开 ⇒ 记一条
// 带 source 的 WARN 并回落默认:坏配置**不许**静默变成「无上限」。
//
// 与 QUIET_* 同口径:启动期读一次,**改文件需重启**。
func (a *app) backthinkTuning() backthink.Config {
cfg := backthink.ConfigFromBackground(a.cfg.Background)
tuningPath := runtimeconfig.DefaultBackthinkPath(resolveDataDir(a.cfg))
tuning, err := runtimeconfig.LoadBackgroundTuning(tuningPath)
if err != nil {
logger.WithSource(a.log, "services/backthink").Warn(
"backthink tuning unreadable; falling back to code defaults", "path", tuningPath, "error", err)
return cfg
}
cfg.SelfWakeLimit = tuning.SelfWakePerWindow
cfg.SelfWakeWindow = time.Duration(tuning.SelfWakeWindowSec) * time.Second
return cfg
}
// pushOutletConfig 把环境变量里的推送出口配置块映射为 backthink 的导出器配置。
// 个推(Getui)凭据只被 config 读取、并不消费:备用 SDK 尚未接入,因此出口在
// 待接入该档位时记日志,而不是伪造一次推送。token 只透传,绝不写日志。