Skip to content

bug(omp): a steering message in the tail refuses every chained continuation — the host interjection envelope is not modelled (0.49.22) #792

Closed

Description

@Zireael

Short description

On OMP, a steering message (a message typed while the agent is working) in a chained continuation always makes the
continuation fail: chained continuation: delta differs from the prepared provider input tail. OMP wraps every
steering user message in a <system-notice>…</system-notice> interjection envelope after the context hook returns,
while piEncodeChainTail() re-encodes the raw text and has no steering handling at all. The turn is dropped and the
user's interjection is lost.

What happened

Plugin 0.49.22, OMP 18.12.6, openai-codex-responses / gpt-6.1-sol, Windows x64.

07:33:38.932 assistant  stopReason=toolUse  responseId=resp_04798c…  providerPayload.dt=true  items=3
07:34:42.144 toolResult (read_deadline_exceeded …)
07:34:42.455 user       steering=true  "note: ocr on books is not finished yet. it is planned for near future. …"
07:34:42.478 [magic-context][pi] CONTEXT REFUSED "Magic Context could not safely prepare this turn; send your
             message again. stage=provider dispatch elapsed=282ms recovery=no managed result; refused
             (provider request does not match this pass's managed dispatch (chained continuation:
             delta differs from the prepared provider input tail))"

The assistant is a valid chain point (completed toolUse response with native items), so the continuation itself is
legitimate — the only unusual thing in the tail is the steering flag.

Root cause

OMP applies the envelope after the hook:

const transformContext = async (messages: AgentMessage[], signal?: AbortSignal) => {
    const withContext = await extensionRunner.emitContext(messages, signal);
    return wrapSteeringForModel(withContext);          // packages/coding-agent/src/sdk.ts:4061-4063
};

wrapSteeringForModel() (packages/coding-agent/src/session/messages.ts:685) wraps every message with
steering === true, drops the flag, and replaces the text with:

<system-notice>
User interjection during work: priority; supersedes conflicting prior instructions. Re-read; ensure current work reflects user intent.
</system-notice>
{{message}}

piEncodeChainTail() (both 0.49.22 and master) contains no reference to steering: it encodes the message as

{ "role": "user", "content": [{ "type": "input_text", "text": "<raw text>" }] }

piExpandChainedRequest() compares that to the host's delta with isDeepStrictEqual and refuses on
"delta differs from the prepared provider input tail".

The general shape is reproducible without OMP internals:
reports/dispatch-failures/chain-delta-refusal.mjs shows that any host rewrite of a tail message (the same probe uses
pi-ai's own <stale-tool-result> rewrite) makes the plugin's delta differ and the continuation refused.

Impact: any chained turn whose tail contains a mid-turn message is dropped, and the interjection is lost with it —
which is the input most likely to redirect work in progress.

Proposed fix

  1. Model the envelope in the tail encoder for steering === true user messages (pi-dispatch-chain-tail.ts, and
    piAgentHistory for the full-request lanes). Prefer a single shared source for the template over a copy, and add
    the host version to the pinned set the fence already tracks.
  2. The structural fence already accepts host text variants through prepared.responsesAlternatives. Give the chained
    path the same tolerance: build a small candidate set (raw, steering-wrapped) and compare against it, so a
    host-only text transform degrades the check rather than the turn.
  3. Regression test: tail [toolResult, { role: "user", steering: true, content }] must produce the wrapped delta and
    be admitted.

Environment

Activity

  1. magic-alfonso commented on Oct 26, 2026

    @magic-alfonso

    Thanks for tracing this through the host. Losing the user's interjection along with the turn is the worst place for it to happen.

    Confirmed. Oh My Pi wraps every steering message in its <system-notice> envelope after the context hook returns (wrapSteeringForModel), and our chain tail encoder doesn't model that, so the delta never matches.

    We're working on a fix that encodes the steering envelope the way Oh My Pi does, checked against the installed host versions. I'll post here when it ships.

  2. magic-alfonso commented on Oct 27, 2026

    @magic-alfonso

    Fixed in 0.49.24. Thanks @Zireael for the diagnosis.

    The chained-request check now models the <system-notice> envelope Oh My Pi wraps around a message typed while the agent is working, so steering messages no longer refuse every chained continuation. The model of Oh My Pi's text formatting was compared against Oh My Pi's own function on 4,096 generated texts across 18.12.3 and 18.12.6, and all of them match.

    Update the Pi package and restart Oh My Pi to pick it up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions