feat(harness): per-run auto-approval of layer-2 proposals for model measurement
런 옵션 auto_approve_after_s(runs 열·POST /runs)를 추가한다. 값이 양수면 하네스가 제안 등록 뒤 그 지연만큼 기다렸다가 스스로 승인(actor auto)하고 HITL 버튼 경로와 같은 방식으로 조치를 실행(actor ai-approved, MarkProposalExecuted)한다. 사람 없이 모델 비교 캠페인을 반복하기 위한 측정 모드로, MTTA는 지연값으로 고정되고 판정 로직은 그대로다(2층 판정은 ai-approved 조치에서 나온다). 이미 결정·만료된 제안과 기록 전용 조치는 API 경로와 같이 처리한다.
This commit is contained in:
1 parent
f671e2419f
commit
ca933a646e
4 files changed
+82
-26
No files matched your search
@@ -0,0 +1,45 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
// autoApprove is the measurement-mode stand-in for the Discord approver (run option auto_approve_after_s, 2026-10-15):
|
||||
// after the configured delay the harness approves the layer-2 proposal (actor "auto") and executes it exactly as the
|
||||
// HITL bot does after a button press (actor "ai-approved", MarkProposalExecuted). MTTA therefore equals the delay;
|
||||
// the verdict logic is unchanged (layer 2 from the ai-approved action). A proposal already decided, expired or
|
||||
// recorded-only is handled the same way as the API path.
|
||||
func (a *App) autoApprove(token string, req ProposalRequest, after time.Duration) {
|
||||
time.Sleep(after)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||
defer cancel()
|
||||
p, err := a.store.GetProposal(ctx, token)
|
||||
if err != nil || p.ApprovedAt != nil || time.Now().After(p.ExpiresAt) {
|
||||
return
|
||||
}
|
||||
if err := a.store.ApproveProposal(ctx, token, "auto"); err != nil {
|
||||
return
|
||||
}
|
||||
suffix := token[len(token)-6:]
|
||||
a.store.Event(ctx, p.RunID, p.ScenarioID, "approval", "auto", map[string]any{"action_id": p.ActionID, "token_suffix": suffix, "auto_approve_after_s": after.Seconds()})
|
||||
ce := catalogEntry(p.ActionID)
|
||||
if ce == nil {
|
||||
return
|
||||
}
|
||||
note := "auto-approved by the harness (measurement mode)"
|
||||
if !ce.Exec {
|
||||
a.store.Event(ctx, p.RunID, p.ScenarioID, "action", "ai-approved", map[string]any{"action_id": p.ActionID, "target": req.Target, "recorded_only": true, "note": note, "layer": ce.Layer})
|
||||
mActs.WithLabelValues(p.ActionID, "ai-approved", "recorded").Inc()
|
||||
_ = a.store.MarkProposalExecuted(ctx, token)
|
||||
return
|
||||
}
|
||||
res, err := a.executeAction(ctx, p.ActionID, req.Target, "ai-approved", p.RunID, p.ScenarioID)
|
||||
result := "ok"
|
||||
if err != nil {
|
||||
result = "error"
|
||||
}
|
||||
mActs.WithLabelValues(p.ActionID, "ai-approved", result).Inc()
|
||||
a.store.Event(ctx, p.RunID, p.ScenarioID, "action", "ai-approved", map[string]any{"action_id": p.ActionID, "target": req.Target, "result": res, "error": errStr(err), "note": note})
|
||||
_ = a.store.MarkProposalExecuted(ctx, token)
|
||||
}
|
||||
Reference in new issue
Block a user