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

+8 -4
View File
@@ -101,9 +101,10 @@ type DecisionInput struct {
// 需要区分「周期性心跳(含启动轮,享长期静默豁免)」与「她自己排起的一轮
// (要求她说得出理由)」,其余类别按事件处理。
//
// ⚠️ TriggerKind 的零值是 TriggerHeartbeat:生产调用方**必须**显式传 tr.Kind
// (backthink.go 的 think 是唯一调用点,已显式传)。省略 Kind 等于按心跳豁免,
// 那是最宽的一档,别让「漏填」静默变成「免检」。
// ⚠️ TriggerKind 的**零值是 TriggerUnknown**(G-A 修法):它是**最紧**的一档,
// 不享任何豁免(activityHeld 让它落在扣下上)。生产调用方仍**必须**显式传
// tr.Kind(backthink.go 的 think 是唯一调用点,已显式传)—— 零值安全只是最后一道
// 兜底,不是「可以不填」的许可。
Kind TriggerKind
}
@@ -178,6 +179,9 @@ func (b *Backthink) baseDecide(in DecisionInput) Decision {
// ——要求她说得出理由(Import ≥ High,即声明 ≥ warning),否则扣下;
// - 其间与活动状态未知 → 不软化,照硬门结论通过。
//
// 未知触发(TriggerUnknown,即漏填 Kind 的零值)同样**不享**豁免:它掉到最后那条
// 扣下上(G-A 修法要的就是这个方向——未知 ≠ 最宽)。
//
// 活动是软信号:硬门(baseDecide)独立生效,频率门(PushGate)在推送器内部生效。
func (b *Backthink) activityHeld(in DecisionInput) (bool, string) {
if !in.HasActivity {
@@ -200,7 +204,7 @@ func (b *Backthink) activityHeld(in DecisionInput) (bool, string) {
if in.Kind == TriggerSelfWake {
return true, "self-initiated wake held: owner away and no declared urgency"
}
return true, "owner away a long while"
return true, "owner away a long while" // 其余(含 TriggerUnknown)一并扣下
}
return false, ""
}