feat(ai): redesign the Jev triage state and add JEV_MODE=enforce review rules

第 2 回キャンペーンの突き合わせ結果を反映した。triage の state にコードで計算した
最新値の要約(now: プローブ、1 分 p95、1 分エラー率、再起動数、slo_now_ok)と
直近 5 分のエラーログ抜粋を加え、recovering は slo_now_ok を読むだけにした。
layer の choice を irreversible_needed の noul に置き換え、target_valid は
カタログ action のときだけ尋ねる。JEV_MODE=enforce では review の 2 ルール
(best_action 不一致かつ確信度 0.9 以上、target_valid 0.5 未満)で提案を
escalate に格下げし、判断を res.jev.enforced に記録する。既定は shadow のまま。
This commit is contained in:
seon committed 2026-10-08 17:45:28 +09:00
1 parent 795be156d9
commit 13797e5741
5 files changed
+178 -30

No files matched your search

+50
View File
@@ -0,0 +1,50 @@
package agent
import (
"testing"
"github.com/selfheal-lab/selfheal-lab-apps/ai/internal/jev"
)
func f(v float64) *float64 { return &v }
func TestEnforceRules(t *testing.T) {
a := &Agent{jevEnforce: true}
// rule A: best_action disagrees with high confidence -> escalate
res := &Result{}
res.ProposedAction, res.Target = "net.route_change", ""
rev := &ShadowRecord{Gate: "review", Answers: map[string]any{"best_action": jev.Answer{Type: "choice", Choice: "escalate", Confidence: f(0.95)}}}
a.Enforce(res, rev)
if res.ProposedAction != "escalate" || res.Jev["enforced"].(map[string]any)["rule"] != "best_action_disagrees" {
t.Fatalf("rule A: %+v %v", res.Diagnosis, res.Jev)
}
// rule B: target invalid -> escalate
res = &Result{}
res.ProposedAction, res.Target = "k8s.rollout_restart", ""
rev = &ShadowRecord{Gate: "review", Answers: map[string]any{"best_action": jev.Answer{Type: "choice", Choice: "k8s.rollout_restart", Confidence: f(0.9)}, "target_valid": jev.Answer{Type: "noul", Noul: f(0.2)}}}
a.Enforce(res, rev)
if res.ProposedAction != "escalate" || res.Jev["enforced"].(map[string]any)["rule"] != "target_invalid" {
t.Fatalf("rule B: %+v %v", res.Diagnosis, res.Jev)
}
// agreement with valid target -> unchanged; none/escalate -> untouched; shadow mode -> untouched
res = &Result{}
res.ProposedAction, res.Target = "k8s.rollout_restart", "api"
rev = &ShadowRecord{Gate: "review", Answers: map[string]any{"best_action": jev.Answer{Choice: "k8s.rollout_restart", Confidence: f(0.99)}, "target_valid": jev.Answer{Noul: f(0.9)}}}
a.Enforce(res, rev)
if res.ProposedAction != "k8s.rollout_restart" || res.Jev != nil {
t.Fatalf("agreement: %+v", res.Diagnosis)
}
res = &Result{}
res.ProposedAction = "none"
a.Enforce(res, &ShadowRecord{Answers: map[string]any{"best_action": jev.Answer{Choice: "escalate", Confidence: f(0.99)}}})
if res.ProposedAction != "none" {
t.Fatalf("none must not change")
}
s := &Agent{jevEnforce: false}
res = &Result{}
res.ProposedAction = "k8s.scale"
s.Enforce(res, &ShadowRecord{Answers: map[string]any{"best_action": jev.Answer{Choice: "escalate", Confidence: f(0.99)}}})
if res.ProposedAction != "k8s.scale" {
t.Fatalf("shadow must not change")
}
}