From 12e6caaf4a5fd058c91e3e46c9035cbe8c03d9ea Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Sat, 7 Nov 2026 20:08:50 +0800 Subject: [PATCH] Reuse the projected body in full native context delivery Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- loopx/control_plane/quota/progressive_context.ts | 3 +++ loopx/control_plane/quota/turn_envelope.py | 9 ++++++++- tests/control_plane/test_progressive_native_context.py | 9 ++++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/loopx/control_plane/quota/progressive_context.ts b/loopx/control_plane/quota/progressive_context.ts index 38a97d03dc..3234ad6e5d 100644 --- a/loopx/control_plane/quota/progressive_context.ts +++ b/loopx/control_plane/quota/progressive_context.ts @@ -402,6 +402,9 @@ export function prepareProgressiveContextDelivery(request: JsonObject, legacyFie const codec = nativeContextContinuity({...request, context: required.context, ...(request.source_number_tokens === undefined ? {} : {source_number_tokens: required.tokens})}); const delivery = encodeContextDelivery(codec, legacyFields, sourceValues, fileNavigationPaths(required.context)); + // The Python edit adapter already reconstructs this exact required view. + // Full native delivery can use that copy; delta still carries its own edits. + if (request.source_edits === true && delivery.mode === "full") delete delivery.context; const observe = request.observe_first_read === true && !!jsonObject(required.context.selected_todo)?.todo_id; const pointers = observe ? initialContextReadPointers(required.context, decisionFields) : []; const observed = pointers.length ? observedFirstRead(codec, pointers) : undefined; diff --git a/loopx/control_plane/quota/turn_envelope.py b/loopx/control_plane/quota/turn_envelope.py index 77f22ab38f..421ac1872f 100644 --- a/loopx/control_plane/quota/turn_envelope.py +++ b/loopx/control_plane/quota/turn_envelope.py @@ -4,6 +4,7 @@ import json from collections.abc import Mapping +from copy import deepcopy from dataclasses import dataclass from typing import Any @@ -211,7 +212,13 @@ def prepare_context_delivery( if consumed_pointers and observe_first_read: source["observe_first_read"] = True result = _turn_envelope_result("context_delivery", **source, source_edits=True) - return _apply_context_projection_changes(source, result) + transaction = _apply_context_projection_changes(source, result) + if native_projection is not None: + delivery = transaction["delivery"] + if delivery["mode"] == "full" and "context" not in delivery: + # Preserve the separately owned delivery body for callers. + delivery["context"] = deepcopy(transaction["context"]) + return transaction def prepare_progressive_context(context: Mapping[str, Any], *, source_reference: Mapping[str, Any], diff --git a/tests/control_plane/test_progressive_native_context.py b/tests/control_plane/test_progressive_native_context.py index e56881d3d2..f35629c344 100644 --- a/tests/control_plane/test_progressive_native_context.py +++ b/tests/control_plane/test_progressive_native_context.py @@ -381,19 +381,26 @@ def test_native_required_view_and_encoding_use_one_runtime_request(tmp_path, mon setup(tmp_path, monkeypatch) invoke = turn_envelope.effect_runtime_projection_result requests = [] + responses = [] def observe(method, params, **kwargs): requests.append((method, params["operation"])) - return invoke(method, params, **kwargs) + response = invoke(method, params, **kwargs) + responses.append(response) + return response monkeypatch.setattr(turn_envelope, "effect_runtime_projection_result", observe) original = payload() before = json.dumps(original, sort_keys=True) for capture in ("cold", "warm"): requests.clear() + responses.clear() _, wire = project(tmp_path, capture, payload=original) assert requests == [("quota.turn_envelope.evaluate", "context_delivery")] required = json.loads(Path(wire["recovery"]["path"]).read_bytes()) + if capture == "cold": + assert wire["mode"] == "full" and wire["context"] == required + assert not any(edit["path"][:2] == ["delivery", "context"] for edit in responses[0]["changes"]) assert outcome(required)["requirements"][0]["description"] == "Preserve this final requirement." assert json.loads(Path(required["context_details"]["path"]).read_bytes()) == original assert wire["mode"] == "delta"