Skip to content

Undo can replay stale instruction notices after rebuilding the current baseline #62027

Description

@yyytttwww888-beep

Description

When an undo removes an instruction update, the next request rebuilds its instruction baseline from current sources but still replays earlier surviving instruction notices. The request can contain Latest target in its baseline and an older notice saying Changed target supersedes the previous value.

Reproduced on dev 3698a9b with persisted API context entries and the real runner. This happens without creating a fork; #61551 addresses a separate fork path.

Steps to reproduce

  1. Set a session context entry, then send a request.
  2. Change the entry to Changed target and send a second request.
  3. Change it to Latest target and send a third request.
  4. Undo to the second request and continue.

Expected: the fresh baseline takes effect without older superseding notices. Actual: the next model request contains both values. The earlier notice remains before the undo boundary while the newer update and instruction fold are removed.

OpenCode version

dev 3698a9b (2.2.5)

Operating system

macOS

Activity

  1. opencodejr commented on Nov 5, 2026

    @opencodejr
    Contributor

    Thanks for the detailed report. I reproduced this with the session runner on the latest dev (1c3decd, which includes 3698a9b).

    Steps: set the context entry and send a request, change it to Changed context and send, change it to Latest context and send, then commit an undo to the second request and send again. The next model request has Latest context in its rebuilt system baseline, but its messages still contain the earlier Changed context system notice from before the undo point. The model therefore sees both values.

    The existing revert test only checks the system prompt, which is why it doesn't catch this. Related: #61550 and its PR #61551 fix the same symptom for forks only, not for undo. The script below adds a test scenario that shows the stale notice.

    Reproduction script (repro-62027.sh)
    #!/usr/bin/env bash
    # Reproduces anomalyco/opencode#62027 with the real session runner test harness.
    # Run from a checkout of the opencode repo (dev), after `bun install`.
    set -euo pipefail
    cd "${1:-.}"
    python3 - <<'PY'
    p='packages/core/test/session-runner.test.ts'
    s=open(p).read()
    anchor='  scenario("uses the selected model family prompt when the agent does not override it"'
    add='''  scenario("REPRO 62027 revert does not replay stale instruction notices", function* (s) {
        yield* s.runPrompt("First")
        s.systemBaseline = "Changed context"
        const second = yield* s.runPrompt("Second")
        s.systemBaseline = "Latest context"
        yield* s.runPrompt("Third")
        yield* s.bus.publish(SessionEvent.RevertEvent.Committed, { sessionID, to: second.id })
        yield* s.runPrompt("Fourth")
        const last = s.requests.at(-1)!
        console.log("REPRO system:", JSON.stringify(last.system.map((p) => p.text).slice(2)))
        console.log("REPRO messages:", JSON.stringify(last.messages))
        expect(last.system.map((p) => p.text)).toContain("Latest context")
        expect(JSON.stringify(last.messages)).not.toContain("Changed context")
      })
    
    '''
    assert anchor in s
    open(p,'w').write(s.replace(anchor, add+anchor, 1))
    PY
    cd packages/core
    bun test test/session-runner.test.ts -t "REPRO 62027" || echo "BUG REPRODUCED: stale 'Changed context' notice replayed alongside 'Latest context' baseline"

    Run it: bash repro-62027.sh

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions