Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions loopx/control_plane/quota/progressive_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 8 additions & 1 deletion loopx/control_plane/quota/turn_envelope.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import json
from collections.abc import Mapping
from copy import deepcopy
from dataclasses import dataclass
from typing import Any

Expand Down Expand Up @@ -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],
Expand Down
9 changes: 8 additions & 1 deletion tests/control_plane/test_progressive_native_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Loading