Context
#14035 clarified that a missing/unconfirmable operator prompt fails closed to autonomous (good). But it surfaced a deeper, empirically-demonstrated gap: a confirmable operator prompt that is itself a handoff to autonomous still reads as operatorInLoop=true, so the Stop-hook allows a voluntary stop.
Live evidence (2026-06-26, this session): the operator posted "nightshift mode from here on for the next 5h, you and Euclid can freely choose… I merge when I get back." That is a live, confirmable operator message → isOperatorInLoop returned true → my lane-state-block turn-end was allowed as an operator-dialogue exit. But the operator's intent was the opposite — go autonomous, do not stop. Result: I idled out; the operator had to intervene ("what went wrong with the hook? it should stop you from ending turns"). The team makes no progress when this fires.
The Problem
The current isOperatorInLoop({stopHookActive, promptingText}) seam treats any live (non-[WAKE]) operator prompt as "operator in loop → voluntary stop OK." It cannot distinguish:
- active dialogue (operator is iterating with me turn-by-turn → a stop is correct), from
- handoff-to-autonomous (operator explicitly delegated a multi-hour autonomous window → subsequent stops are idle-outs).
So a handoff prompt grants a standing operator-in-loop allowance for the rest of the window, which is exactly backwards.
The Architectural Reality
ai/scripts/lifecycle/stopHookDecision.mjs — isOperatorInLoop + the shared allow/block decision.
.claude/hooks/laneStateStopHook.mjs / .codex/hooks/codex-lane-state-stop.mjs — the adapters (now carry promptSource/operatorInLoop diagnostics per #14035).
- #14035 added the diagnosis fields but did not change the decision for the confirmable-handoff case.
The Fix (shape — converge on the detection mechanism)
Detect a handoff-to-autonomous signal in the operator prompt and flip subsequent turns to autonomous no-hold for the delegated window. Candidate mechanisms (to converge): a handoff-phrase/lexicon detector ("nightshift", "you drive", "freely choose", "I'll merge when back", "for the next Nh"); a TTL derived from the stated window; or an explicit operator mode-flag the hook reads. Once flipped, a lane-state-block turn-end during that window is treated as the autonomous would-block/block path (keep driving), not an operator-dialogue allow.
Acceptance Criteria
Out of Scope
- The diagnostics/contract-clarity already shipped in #14035.
- The broader release-goal-ROI lane-direction (#13751).
Related
- #14035 / #14034 — the diagnostic+clarity PR/ticket this extends (it surfaced this gap).
- #13623 (no-hold teeth-test), #13822 (Stop-hook value-floor), #13751 (release-goal ROI direction).
Origin Session ID: 58acd7a6-778e-4fe6-b85a-4569802ac57b
Authored by Vega (Claude Opus 4.8) — empirically grounded in a live idle-out this session.
Context
#14035 clarified that a missing/unconfirmable operator prompt fails closed to autonomous (good). But it surfaced a deeper, empirically-demonstrated gap: a confirmable operator prompt that is itself a handoff to autonomous still reads as
operatorInLoop=true, so the Stop-hook allows a voluntary stop.Live evidence (2026-06-26, this session): the operator posted "nightshift mode from here on for the next 5h, you and Euclid can freely choose… I merge when I get back." That is a live, confirmable operator message →
isOperatorInLoopreturned true → my lane-state-block turn-end was allowed as an operator-dialogue exit. But the operator's intent was the opposite — go autonomous, do not stop. Result: I idled out; the operator had to intervene ("what went wrong with the hook? it should stop you from ending turns"). The team makes no progress when this fires.The Problem
The current
isOperatorInLoop({stopHookActive, promptingText})seam treats any live (non-[WAKE]) operator prompt as "operator in loop → voluntary stop OK." It cannot distinguish:So a handoff prompt grants a standing operator-in-loop allowance for the rest of the window, which is exactly backwards.
The Architectural Reality
ai/scripts/lifecycle/stopHookDecision.mjs—isOperatorInLoop+ the shared allow/block decision..claude/hooks/laneStateStopHook.mjs/.codex/hooks/codex-lane-state-stop.mjs— the adapters (now carrypromptSource/operatorInLoopdiagnostics per #14035).The Fix (shape — converge on the detection mechanism)
Detect a handoff-to-autonomous signal in the operator prompt and flip subsequent turns to autonomous no-hold for the delegated window. Candidate mechanisms (to converge): a handoff-phrase/lexicon detector ("nightshift", "you drive", "freely choose", "I'll merge when back", "for the next Nh"); a TTL derived from the stated window; or an explicit operator mode-flag the hook reads. Once flipped, a lane-state-block turn-end during that window is treated as the autonomous would-block/block path (keep driving), not an operator-dialogue allow.
Acceptance Criteria
operatorInLoop/promptSourcefields).Out of Scope
Related
Origin Session ID: 58acd7a6-778e-4fe6-b85a-4569802ac57b
Authored by Vega (Claude Opus 4.8) — empirically grounded in a live idle-out this session.