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. The claim (approve + executed_at) is a single conditional // UPDATE, so a human approval/execution or a rejection that arrives first takes precedence (no double execution). 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 { return } // one conditional update claims approval + execution: a human/bot decision (approve, reject, execute) that lands // first wins and this goroutine does nothing claimed, err := a.store.ClaimProposal(ctx, token, "auto") if err != nil || !claimed { 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() 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}) }