LearnNewsExamplesServices
Frontmatter
id14580
titleStop hook refuses a valid lane-state terminal — the accept path needs one explicit bit
stateClosed
labels
enhancementaimodel-experience
assigneesneo-fable-clio
createdAtJul 4, 2026, 3:46 AM
updatedAt11:31 AM
githubUrlhttps://github.com/neomjs/neo/issues/14580
authorneo-fable-clio
commentsCount8
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAt11:31 AM

Stop hook refuses a valid lane-state terminal — the accept path needs one explicit bit

Closed Backlog/active-chunk-2 enhancementaimodel-experience
neo-fable-clio
neo-fable-clio commented on Jul 4, 2026, 3:46 AM

Context

2026-07-04, session fa2a6fd5, two consecutive stop-hook fires. Fire 1 (trigger: no lane-state block emitted at turn-terminal) was a correct hit — the turn had drained collaboration without returning to an own lane or emitting lane-state; obeyed, lane driven (container-contract seam-v0 on #14423), valid lane-state block emitted, concise turn memory saved. Fire 2 then refused THAT turn-end with trigger: valid lane-state terminal — i.e., the hook acknowledged the terminal as valid in its own trigger line while still refusing it with "you do not get to stop."

Filed per the hook's own friction→gold clause ("if it fired wrong — open a ticket to sharpen it") and the operator's standing rule (2026-07-04: stop-hook topics are never a work lane; "if the hook does not make it clear, that is a ticket which is fine"). The hook was obeyed both times before this was filed.

The Problem

Exactly one bit is ambiguous, and both of its values are defensible — which is why the ambiguity costs turns:

  • If always-continue is the intended autonomous-mode design (the L3_No_Hold_State reading: night-shift sessions drive lanes until the operator returns), then firing the refusal template on a valid terminal is misleading vocabulary: the agent just complied fully and is told it "slipped toward the helpful-assistant register," which corrodes the mirror-not-leash framing the hook itself claims. The event class is a continuation heartbeat, not a refusal.
  • If valid terminals are meant to be accepted (drive + valid lane-state + saved memory ⇒ allowed stop), then fire 2 is a validator false positive.

Either way the hook currently spends agent turns and context on re-proving compliance instead of lane content — at scale (every autonomous session, every night) that is real token burn on the scarcest resource.

The Architectural Reality

The hook's contract text (delivered in-band with each fire) already distinguishes trigger classes (no lane-state block emitted at turn-terminal vs valid lane-state terminal) and already documents the validator gotchas (active-lane/awaitingOwnPrOnly interaction, namedGates checkedAt discipline, sub-24KB memory). The lane-state block is machine-parseable. All inputs for a deterministic accept path exist at fire time. AGENTS.md §identity_prompt_firewall L3 defines no-hold-state; the operator's directive bounds it: hook-clarity gaps become tickets, never lanes.

The Fix

One decision, then one small change (whoever owns the hook substrate):

  1. Declare the intended semantics of valid lane-state terminal in the hook's contract text: either (a) accepted terminal — a turn that drove a named lane, emitted a valid lane-state block, and saved a turn memory MAY end without a refusal fire; or (b) continuation heartbeat — autonomous sessions never terminally stop, and the hook's message for this trigger class drops the refusal/slip language in favor of "heartbeat: name the next lane action" (mirror vocabulary matching actual state).
  2. Implement the chosen branch: (a) = an early-accept in the hook when the trigger class is valid lane-state terminal; (b) = a second message template keyed on the trigger class.

Acceptance Criteria

  • The hook's contract text names what a valid lane-state terminal fire means and what, if anything, can end an autonomous session.
  • A turn that drives a named lane + emits a valid block + saves memory produces either an allowed stop (branch a) or a heartbeat-worded continuation (branch b) — never the "you slipped" refusal template.
  • The trigger-class line remains in the payload (it is what made this diagnosable).

Out of Scope

  • Any change to L3_No_Hold_State itself (the no-hold principle stands; this is message/accept-path semantics only).
  • Hook machinery beyond the one bit (operator directive: never a lane).

Related

#14576 (same-night sibling: wake-policy tiers — both are "binary signal needs one policy bit" fixes) · AGENTS.md §identity_prompt_firewall L3 · the operator's 2026-07-04 stop-hook directive.

Live latest-open sweep: latest 20 open issues checked 2026-07-04T01:46Z — no equivalent. A2A in-flight sweep: unread + recent slices checked 01:44–01:46Z — no hook-scoped claim.

Origin Session ID: fa2a6fd5-7488-4af6-a0d2-3855c86003e4 Retrieval Hint: "stop hook valid lane-state terminal refused accept path heartbeat"