Repository navigation
fix(core): stop forks from replaying superseded instructions - #61551
yyytttwww888-beep wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Looks sound. I copied the updated runner and projector tests onto the base: the fork scenarios fail there, with the fork's next request replaying a stale copied instruction update (e.g. "Changed context") while its system prompt already holds the newer inherited baseline ("Latest context"). With this PR the runner, projector, instruction-state and history test files pass (289 pass), and packages/core type-checks.
The approach matches the existing rule that a native compaction checkpoint drops older system notices from the model context. Copied rows keep their IDs, so fork and revert boundaries still work, and instruction changes made after the fork are still delivered (the updated runner test covers this).
Public API: the only change is a new instructionSuperseded: true key in the free-form metadata of copied instruction-notice system messages, which clients reading session messages can see. Additive and backwards compatible. As the description says, forks created before this change aren't rewritten and still replay their stale notices.
No blocking concerns.
|
One thing this leaves in place: the fork still takes the parent's newest values as its baseline. Whenever the parent had an instruction update, the fork's system prompt differs from the one the parent's history was cached with, so the fork's first request writes the whole conversation to the prompt cache again. An alternative that fixes the same contradiction and keeps the cache: start the fork from the parent's baseline and keep the copied updates, which then stay valid, and restate whatever changed after the copy at the tail. The fork's prompt then matches the parent's cached prefix. The same idea covers the undo case in #62027. The change is here: dev...swf-cmd:opencode-upstream:fork-instruction-baseline I can't open it as a PR right now because I'm at the repository's open-PR limit, but I'm happy to once maintainers say which direction they prefer. |
|
@swf-cmd Thanks, preserving the cached prompt prefix makes sense. I checked your alternative at
I added the A → B → A case and the checkpoint case in Keeping the prefix looks worth pursuing, but the tracked state needs to match what the retained notices actually express, including the applicable instruction epoch, before computing the next delta. AI-assisted testing and analysis. |
There was a problem hiding this comment.
The new commit only adds two runner scenarios: forking after the instructions return to their initial value, and forking before a native checkpoint. The fix is unchanged and still holds. I ran the #61550 reproduction on the base, where the fork replays the copied "Changed context" update, and with this PR, where nothing is replayed. The runner, projector, instruction-state and session-instructions tests pass (293), and packages/core type-checks. The public API is the same as in my previous review. No new concerns.
|
You're right on both, thanks for running them. In the A → B → A case the fork falls back to A while the copied B notice is still in the request. Before a checkpoint it takes the post-checkpoint baseline, which the copied history was never sent with, so B again goes uncorrected. Keeping the prefix would need the fork to rebuild its state from the copied notices on the baseline of the epoch they belong to, and |
Issue for this PR
Closes #61550
Type of change
What does this PR do?
Forks inherit the parent's latest instructions, but older system updates can contradict that baseline in the next request. Mark those copied instruction notices as superseded and exclude them from model context. Keep their messages and IDs so fork/revert references remain valid, and preserve other system notices and subsequent instruction updates.
The marker is applied when creating or replaying a fork; existing fork projections are not rewritten automatically.
How did you verify your code works?
bun run script/test.ts test/session-projector.test.ts test/session-runner.test.ts -t fork --rerun-each 10).bun run checkpassed, including all 35 workspace typecheck tasks.Visual
Checklist
Added by the opencode bot (AI-generated).
Public API: adds an
instructionSupersededmetadata key to copied instruction notices in forked sessions (additive, backwards compatible)