fix(run): address round-2 gadfly nits (max(), drop dead soft fallback, decouple doc)
executus CI / test (pull_request) Successful in 49s

All low-severity follow-ups on the critic-deadline change:
- hardCap uses max(CriticAbsoluteMax, maxRuntime) instead of a nested if (723193a7).
- Drop the now-dead 90s soft-trigger fallback + its bare literal: the sole caller
  passes the resolved MaxRuntime (>0), and Run's unsupervised-run failsafe bounds
  even an impossible 0 (8d377051, 2f86bf58).
- Decouple the kernel doc from a named downstream convar ("a 6h host convar")
  (730c67fc).

Graded false-positive: agent.go BackstopMultiplier validation (handled in the host;
not in this diff), the 24h default "magic number" (matches every withFallbacks
default), and the defer-in-conditional pattern (idiomatic). Kept: the thorough
two-tier comment (this logic regressed once) and the rare-path nested timer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jo75sqmeVPgFUWZQBn179X
This commit is contained in:
2026-06-30 11:54:38 -04:00
parent cb4c612461
commit 79ce833dd7
2 changed files with 12 additions and 19 deletions
+4 -7
View File
@@ -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 // 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). // run exceeds its nominal budget, and its backstop = softTrigger × multiplier).
// The caller (Run) always passes the resolved MaxRuntime, which withFallbacks // The caller (Run) always passes the resolved MaxRuntime, which withFallbacks
// guarantees is > 0; the 90s floor below is purely a defensive guard for a // guarantees is > 0, so no fallback is needed here. (A non-positive soft would make
// hypothetical caller that passes a non-positive value. // 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()) { func (e *Executor) startCritic(runCtx context.Context, cancelCause context.CancelCauseFunc, ra RunnableAgent, info RunInfo, softTrigger time.Duration) (*criticBinding, func()) {
noop := func() {} noop := func() {}
if !e.criticOwnsDeadline(ra) { if !e.criticOwnsDeadline(ra) {
return nil, noop return nil, noop
} }
soft := softTrigger h := e.cfg.Ports.Critic.Monitor(runCtx, info, 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)
if h == nil { if h == nil {
return nil, noop return nil, noop
} }
+8 -12
View File
@@ -35,11 +35,10 @@ type Defaults struct {
// deadline. This ceiling exists ONLY to stop a critic that never advances its // 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 // 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 // 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. // backstop to a much smaller absolute max (e.g. a 6h host convar), so the ceiling
// absolute_max_seconds = 6h), so the ceiling never pre-empts a healthy // never pre-empts a healthy supervised run. Keep it well above the host's
// supervised run. Keep it well above the host's absolute max. Never shorter than // absolute max. Never shorter than the run's MaxRuntime. Non-critic runs ignore
// the run's MaxRuntime. Non-critic runs ignore it (they keep the literal // it (they keep the literal MaxRuntime kill).
// MaxRuntime kill).
CriticAbsoluteMax time.Duration 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 // 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 // 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 // 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 // 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. // unsupervised and we tighten the cap back down to MaxRuntime below.
// A NESTED cause-carrying layer (cancelCause) lets a critic kill surface as a // 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 hardCap := maxRuntime
if criticOwns { if criticOwns {
// Runaway guard only — the critic's own (extendable) deadline-watch is the // Runaway guard only — the critic's own (extendable) deadline-watch is the
// normal cap. Never shorter than the nominal budget, in case an operator // normal cap. max() keeps it from being shorter than the nominal budget if an
// sets MaxRuntime above the runaway ceiling (a degenerate config). // operator sets MaxRuntime above the runaway ceiling (a degenerate config).
hardCap = e.cfg.Defaults.CriticAbsoluteMax hardCap = max(e.cfg.Defaults.CriticAbsoluteMax, maxRuntime)
if hardCap < maxRuntime {
hardCap = maxRuntime
}
} }
timeoutCtx, cancelTimeout := context.WithTimeout(context.WithoutCancel(ctx), hardCap) timeoutCtx, cancelTimeout := context.WithTimeout(context.WithoutCancel(ctx), hardCap)
defer cancelTimeout() defer cancelTimeout()