Skip to content

fix: point context to the latest persistent input - #185

Closed
kalectory wants to merge 2 commits into
alexzhang13:mainfrom
kalectory:fix/latest-context-alias
Closed

kalectory wants to merge 2 commits into
alexzhang13:mainfrom
kalectory:fix/latest-context-alias

Conversation

@kalectory

@kalectory kalectory commented Sep 10, 2026 •

Copy link
Copy Markdown

In persistent sessions, the system prompt directs the model to context, but that alias continues to refer to the first input after subsequent completion() calls. This can lead weaker models to process an earlier batch instead of the current one.

Point context to the latest numbered input in Local, Docker, and IPython REPLs, including scaffold restoration. Historical inputs remain available through context_0, context_1, etc. Update the persistence protocol documentation accordingly.

Compatibility: callers relying on context remaining the first input should use context_0 explicitly.

Validation: local smoke check covered two inputs, retained numbered contexts, and alias restoration after overwrite; formatting and git diff --check passed. No regression tests added; existing tests asserting the first-input alias have not been updated, and Docker/IPython behavior has not been runtime-tested. Draft for review.

Copilot AI lite review requested due to automatic review settings September 10, 2026 04:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Existing persistence tests in the repo still assert context aliases context_0, and the scaffold-restore logic should not depend on context_0 existing when explicit non-zero context indices are supported.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates persistence semantics for RLM REPL environments so the unversioned context name always refers to the most recently added context_N, preventing models in persistent sessions from accidentally using the first-turn context after later completion() calls.

Changes:

  • Update add_context() in LocalREPL, DockerREPL, and IPythonREPL to always set context = context_N for the latest index.
  • Update scaffold restoration logic so context is restored to the latest context_N if overwritten by executed code.
  • Update the persistence protocol documentation to describe the new aliasing behavior.
File summaries
File Description
rlm/environments/local_repl.py Always aliases context to the latest added context and restores that alias after overwrites.
rlm/environments/ipython_repl.py Updates both subprocess-mode context injection and in-process scaffold restoration to use the latest context.
rlm/environments/docker_repl.py Updates container-side scaffold restoration and add_context() to alias context to the latest context.
rlm/environments/base_env.py Updates SupportsPersistence documentation to reflect new context aliasing semantics.
Review details

Suppressed comments (3)

rlm/environments/base_env.py:302

  • The docstring contradicts itself: it says unversioned names always point to index 0, but then states context points to the latest numbered context. Update the lead-in line so it matches the new aliasing behavior.
        Use isinstance(env, SupportsPersistence) to check if an environment
        supports persistence capabilities.

    IMPLEMENTING THIS PROTOCOL:

rlm/environments/local_repl.py:549

  • Scaffold restoration only resets context when context_0 exists. Since add_context(..., context_index=N) supports explicit non-zero indices, context may exist without context_0; in that case an overwrite would not be restored. Consider restoring whenever any context_\d+ key exists.
                    self.locals["answer"] = replacement
            elif name == "context" and "context_0" in self.locals:
                self.locals["context"] = get_latest_context(self.locals)
            elif name == "history" and "history_0" in self.locals and not self.compaction:
                self.locals["history"] = self.locals["history_0"]
            elif name == "history" and self.compaction:
                self.locals["history"] = self._compaction_history

    def execute_code(self, code: str) -> REPLResult:
        """Execute code in the persistent namespace and return result."""
        start_time = time.perf_counter()

rlm/environments/ipython_repl.py:1406

  • In-process scaffold restoration only resets context when context_0 exists. If contexts are loaded with an explicit non-zero index (supported by the persistence protocol), context could exist without context_0 and would not be restored after an overwrite.
                    self._last_final_answer = str(current.get("content", ""))
            ns["answer"] = replacement
        if "context_0" in ns:
            ns["context"] = get_latest_context(ns)
        if "history_0" in ns:
            ns["history"] = ns["history_0"]
        # Re-inject custom tools if overwritten
        for name, entry in self.custom_tools.items():
  • Files reviewed: 4/4 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread rlm/environments/docker_repl.py Outdated
Comment on lines +388 to +393
# Restore scaffold aliases if overwritten by executed code
if "context_0" in _locals:
_locals["context"] = _locals["context_0"]
_locals["context"] = _locals[max(
(key for key in _locals if key.startswith("context_") and key[8:].isdigit()),
key=lambda key: int(key[8:]),
)]
Comment on lines +434 to 438
# Alias the latest context as 'context'.
self.execute_code(f"context = {var_name}")

self._context_count = max(self._context_count, context_index + 1)
return context_index
Copilot AI review requested due to automatic review settings September 10, 2026 04:53
@kalectory kalectory closed this Sep 10, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The Docker exec-script injection via inspect.getsource() currently risks generating an indented top-level script (IndentationError), and existing tests asserting context == context_0 must be updated to match the new contract.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

rlm/environments/base_env.py:315

  • This change updates the persistence contract for the context alias, but existing tests still assert the old behavior (e.g., tests/test_local_repl_persistent.py::test_context_alias_points_to_first and tests/test_docker_repl_persistent.py::test_context_alias_points_to_first). The PR should update those tests (and any other callers) to check context == context_{latest} and/or use context_0 explicitly when they want the first payload.
        - context  -> latest numbered context
        - history  -> history_0 (first history)

  • Files reviewed: 4/4 changed files
  • Comments generated: 2
  • Review effort level: Lite

except ImportError:
import pickle as dill

{inspect.getsource(get_latest_context)}
@@ -298,7 +310,7 @@ class SupportsPersistence(Protocol):

ALIASING BEHAVIOR:
The unversioned names always point to index 0:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants