All 11 findings were real (3 clusters):
- Failsafe ceiling could pre-empt the critic's backstop (e9c9483f, 9109317b,
d5a9bf0d, 76ad171e): CriticAbsoluteMax was 6h, but the host's backstop
(MaxRuntime × multiplier, or its own absolute max) can reach 6h+, so the
ceiling fired first and reintroduced a premature hard cap. Now CriticAbsoluteMax
is a 24h RUNAWAY guard 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
never pre-empts a healthy supervised run. Comments corrected.
- nil Monitor handle lost the MaxRuntime cap (df016a6f, 9dd42827): a critic-enabled
run whose host Monitor returned no handle had no deadline-watch and was bounded
only by the generous ceiling. Added an unsupervised-run failsafe that re-wraps
runCtx to the nominal MaxRuntime when the critic is enabled but didn't arm.
New test TestCriticOwnsDeadline_NilHandleFallsBackToMaxRuntime.
- CriticSoftTimeout vestigial / dead fallback (f7764919, 9805bebe, 6864086f,
b2b11721): the soft trigger is now always the resolved MaxRuntime (> 0), so the
CriticSoftTimeout field + its startCritic fallback were unreachable. Removed the
field entirely; the remaining 90s floor is documented as defensive-only.
- DRY (f30ce827): extracted e.criticOwnsDeadline(ra), now the single predicate used
by both Run and startCritic so they can't drift.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jo75sqmeVPgFUWZQBn179X
When a run enables the critic (Ports.Critic set + RunnableAgent.Critic.Enabled),
the kernel no longer hard-caps it at MaxRuntime. MaxRuntime becomes the SOFT
trigger (passed to startCritic, used by the host critic as its wake + the base
for its extendable backstop); the critic's deadline-watch is the real hard
cancel. This restores mort's old agentexec two-tier timeout semantics — a
slow-but-progressing run (e.g. a parent agent blocked on a 30-min animate render)
is given room up to the critic's backstop instead of being killed at the nominal
MaxRuntime.
Specifics:
- run/executor.go: the WithTimeout(MaxRuntime) is now conditional. Non-critic
runs keep the literal MaxRuntime kill (→ "timeout"). Critic-owned runs get a
GENEROUS WithTimeout at the new Defaults.CriticAbsoluteMax (default 6h) as a
failsafe ceiling only — it never fires before the critic's backstop, and it
guarantees a broken/nil host handle can't run unbounded.
- run/critic.go: startCritic takes the resolved MaxRuntime as the soft trigger
(falling back to Defaults.CriticSoftTimeout, then 90s), instead of always using
the global CriticSoftTimeout.
- Defaults.CriticAbsoluteMax added (withFallbacks default 6h).
- Tests: non-critic dies at MaxRuntime; critic-owned survives past it; soft
trigger == MaxRuntime.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jo75sqmeVPgFUWZQBn179X