diff --git a/run/critic.go b/run/critic.go index d5eafdd..49c1a05 100644 --- a/run/critic.go +++ b/run/critic.go @@ -44,18 +44,15 @@ func (e *Executor) criticOwnsDeadline(ra RunnableAgent) bool { // is the soft wake (mort's two-tier semantics — the critic first reviews once the // run exceeds its nominal budget, and its backstop = softTrigger × multiplier). // The caller (Run) always passes the resolved MaxRuntime, which withFallbacks -// guarantees is > 0; the 90s floor below is purely a defensive guard for a -// hypothetical caller that passes a non-positive value. +// guarantees is > 0, so no fallback is needed here. (A non-positive soft would make +// the host Monitor return no handle, and Run's unsupervised-run failsafe then bounds +// the run at MaxRuntime — so even that impossible case stays bounded.) func (e *Executor) startCritic(runCtx context.Context, cancelCause context.CancelCauseFunc, ra RunnableAgent, info RunInfo, softTrigger time.Duration) (*criticBinding, func()) { noop := func() {} if !e.criticOwnsDeadline(ra) { return nil, noop } - soft := softTrigger - if soft <= 0 { - soft = 90 * time.Second // defensive only; the sole caller passes MaxRuntime (>0) - } - h := e.cfg.Ports.Critic.Monitor(runCtx, info, soft) + h := e.cfg.Ports.Critic.Monitor(runCtx, info, softTrigger) if h == nil { return nil, noop } diff --git a/run/executor.go b/run/executor.go index 4b75010..7a3ffb3 100644 --- a/run/executor.go +++ b/run/executor.go @@ -35,11 +35,10 @@ type Defaults struct { // deadline. This ceiling exists ONLY to stop a critic that never advances its // deadline (a broken host handle) from running forever, so it is deliberately // set FAR beyond any realistic backstop (default 24h): the host clamps its own - // backstop to a much smaller absolute max (e.g. mort's agents.critic. - // absolute_max_seconds = 6h), so the ceiling never pre-empts a healthy - // supervised run. Keep it well above the host's absolute max. Never shorter than - // the run's MaxRuntime. Non-critic runs ignore it (they keep the literal - // MaxRuntime kill). + // backstop to a much smaller absolute max (e.g. a 6h host convar), so the ceiling + // never pre-empts a healthy supervised run. Keep it well above the host's + // absolute max. Never shorter than the run's MaxRuntime. Non-critic runs ignore + // it (they keep the literal MaxRuntime kill). CriticAbsoluteMax time.Duration } @@ -294,7 +293,7 @@ func (e *Executor) Run(ctx context.Context, ra RunnableAgent, inv tool.Invocatio // gets a WithTimeout at CriticAbsoluteMax (default 24h) purely as a RUNAWAY // guard for a critic that never advances its deadline: it is set FAR beyond // any realistic backstop (the host clamps its own backstop to a much smaller - // absolute max, e.g. mort's 6h convar), so it does NOT pre-empt a healthy + // absolute max, e.g. a 6h host convar), so it does NOT pre-empt a healthy // supervised run. If the host critic fails to ARM (nil handle), the run is // unsupervised and we tighten the cap back down to MaxRuntime below. // A NESTED cause-carrying layer (cancelCause) lets a critic kill surface as a @@ -305,12 +304,9 @@ func (e *Executor) Run(ctx context.Context, ra RunnableAgent, inv tool.Invocatio hardCap := maxRuntime if criticOwns { // Runaway guard only — the critic's own (extendable) deadline-watch is the - // normal cap. Never shorter than the nominal budget, in case an operator - // sets MaxRuntime above the runaway ceiling (a degenerate config). - hardCap = e.cfg.Defaults.CriticAbsoluteMax - if hardCap < maxRuntime { - hardCap = maxRuntime - } + // normal cap. max() keeps it from being shorter than the nominal budget if an + // operator sets MaxRuntime above the runaway ceiling (a degenerate config). + hardCap = max(e.cfg.Defaults.CriticAbsoluteMax, maxRuntime) } timeoutCtx, cancelTimeout := context.WithTimeout(context.WithoutCancel(ctx), hardCap) defer cancelTimeout()