You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Historical forks replay instruction updates that contradict their inherited baseline #61550
A historical fork inherits the parent's latest instruction values, but also replays older instruction updates from the copied history. Those system messages can contradict the new baseline. API context entries explicitly say the old value supersedes the previous one.
OpenCode version
dev at fe046564650854594c4c5aa22270f46d9de6cace (2.2.5).
Steps to reproduce
Run a session with an instruction source whose value changes from A to B to C across requests.
Fork at a historical point that includes the B update but precedes C.
Continue the fork and inspect the next model request.
The initial instructions contain C, while a later system message still applies B. The inherited instruction state already equals C, so no corrective update is generated.
Expected: the fork uses its inherited current baseline without replaying superseded updates. New instruction changes made after the fork should still be delivered.
Reproduced with the real SessionRunner and database using a local test LLM. The existing seeds a fork with the parent's newest instruction values test currently asserts that the stale update remains; changing that expectation exposes the conflict. No live model behavior is claimed.
Thanks for the clear report. I was able to reproduce this on the latest dev (fe0465646), which is the commit you reported, using the session runner tests with a fake model and a real database.
The steps (the script below runs them):
Prompt three times while the instruction value changes from A to B ("Changed context") to C ("Latest context").
Fork before the second prompt, so B's update is in the copied history and C's is not.
Prompt the fork and look at the next request.
That request has C in its system prompt, then replays the copied system update for B, and nothing restores C afterwards. The fork's stored instruction state is already C, so no corrective update is sent. For API context entries the replayed text says the value "supersedes the previous value", so the model ends up treating B as current.
The existing test seeds a fork with the parent's newest instruction values currently expects this stale update to stay. However, the fork is meant to start from the parent's newest values, so I've passed this to the maintainers as a bug, with your proposed fix linked for reference.
Reproduction script (repro.sh)
#!/usr/bin/env bash# Reproduces #61550 in the real SessionRunner test harness (fake LLM, real SQLite DB).# Run from an opencode checkout (dev): bash repro.sh /path/to/opencodeset -euo pipefail
REPO=${1:-/workspace/repo}cd"$REPO/packages/core"
F=test/session-runner.test.ts
cp $F /tmp/opencode/session-runner.test.ts.bak
trap'cp /tmp/opencode/session-runner.test.ts.bak '"$F" EXIT
python3 - "$F"<<'PY'import sysp=sys.argv[1]; s=open(p).read()anchor=' scenario("keeps nested forks self-contained"'new=''' scenario("REPRO 61550 historical fork replays superseded instruction update", function* (s) { yield* s.runPrompt("First") s.systemBaseline = "Changed context" // The "Changed context" update is written just before the "Second" user message, // so forking before "Second" keeps update B in the copy but not update C. const second = yield* s.runPrompt("Second") s.systemBaseline = "Latest context" yield* s.runPrompt("Third") const forked = yield* s.session.fork({ sessionID, before: second.id }) yield* s.session.prompt({ sessionID: forked.id, text: "Forked", resume: false }) yield* s.session.resume(forked.id) const req = s.requests.at(-1)! console.log("REPRO baseline system:", JSON.stringify(req.system.map((p) => p.text))) console.log("REPRO system messages:", JSON.stringify(systemTexts(req))) console.log("REPRO full messages:", JSON.stringify(req.messages, null, 1).slice(0, 3000)) // Expected: the baseline is Latest context and no later message overrides it with the stale value. expect(req.system.map((p) => p.text)).toContain("Latest context") expect(systemTexts(req).join("\\n")).not.toContain("Changed context") })'''assert anchor in sopen(p,'w').write(s.replace(anchor,new+anchor,1))PY
bun test$F -t "REPRO 61550"2>&1| grep -E "REPRO (baseline|system|full)|supersedes|\(pass\)|\(fail\)| pass$| fail$"| grep -v console.log
Activity
opencodejr commentedon Nov 4, 2026
Thanks for the clear report. I was able to reproduce this on the latest
dev(fe0465646), which is the commit you reported, using the session runner tests with a fake model and a real database.The steps (the script below runs them):
That request has C in its system prompt, then replays the copied system update for B, and nothing restores C afterwards. The fork's stored instruction state is already C, so no corrective update is sent. For API context entries the replayed text says the value "supersedes the previous value", so the model ends up treating B as current.
The existing test
seeds a fork with the parent's newest instruction valuescurrently expects this stale update to stay. However, the fork is meant to start from the parent's newest values, so I've passed this to the maintainers as a bug, with your proposed fix linked for reference.Reproduction script (repro.sh)
Run it:
bash repro.sh