From 5d29f26325d64449bc1fcd09657494accbaa11fb Mon Sep 17 00:00:00 2001
From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Date: Wed, 4 Nov 2026 23:14:47 +0800
Subject: [PATCH 1/6] fix(context): separate progressive presentation from
native delta
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
---
.../capability-localization.ts | 12 +-
.../machine-configuration-settings.tsx | 34 +--
loopx/capabilities/configuration_ui.py | 11 +-
.../machine_configuration/context_delivery.py | 16 +-
loopx/cli_commands/context_machine.py | 32 ++-
loopx/cli_commands/quota.py | 26 ++-
loopx/cli_commands/quota_capture.py | 50 ++++-
loopx/cli_commands/quota_registration.py | 6 +-
.../cli_commands/support_control_heartbeat.py | 1 +
.../support_control_heartbeat_registration.py | 6 +-
.../heartbeat/bootstrap_prompt.py | 3 +-
loopx/control_plane/heartbeat/builder.py | 25 ++-
.../quota/native_context_lifecycle.ts | 33 +++
.../quota/progressive_context.ts | 69 +++++-
loopx/control_plane/quota/turn_envelope.py | 15 +-
loopx/control_plane/quota/turn_envelope.ts | 8 +-
.../turn_driver/codex_context.py | 82 ++++++--
.../turn_driver/decision_capture.py | 21 ++
.../turn_driver/native_context_selection.py | 75 +++++++
scripts/codex_app_apply_rrule.py | 1 +
scripts/external_scheduler_worker.py | 1 +
scripts/qualify-native-goal-release.py | 1 +
.../test_codex_context_lifecycle.py | 4 +-
.../test_context_delivery_cli.py | 3 +-
.../test_context_machine_configuration.py | 10 +-
.../test_heartbeat_envelope_transport.py | 22 +-
.../test_progressive_context_entrypoints.py | 196 ++++++++++++++++++
.../test_progressive_native_context.py | 5 +-
tests/test_codex_app_apply_rrule.py | 21 ++
tests/test_external_scheduler_worker.py | 13 ++
30 files changed, 700 insertions(+), 102 deletions(-)
create mode 100644 loopx/control_plane/turn_driver/native_context_selection.py
create mode 100644 tests/control_plane/test_progressive_context_entrypoints.py
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts b/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts
index 26f86233b8..e7145d34c3 100644
--- a/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts
+++ b/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts
@@ -12,7 +12,7 @@ type FieldCopy = Record> = {
en: {
- context_delivery: {displayName: "Differential context", description: "Reuse unchanged context across supported Agent turns. A missing retained baseline keeps the full context."},
+ context_delivery: {displayName: "Progressive context", description: "Read current requirements before supporting material. Supported hosts can reuse unchanged context independently."},
codex_chat: {displayName: "Codex Goal conversation defaults", description: "Choose the native Codex profile, model, speed tier and reasoning effort for new Goal conversations. Existing conversations keep their original history. This does not start or reconfigure an active Agent Loop, worker or steward."},
decision_context: {displayName: "Find evidence", description: "Find advisory evidence with a temporary private profile. OpenViking and BM25 are retrieval implementations; this page does not save a binding or enable automatic memory."},
content_ops: {displayName: "Content production", description: "Prepare source-backed outlines, compose local videos or generate cloud images and footage with the optional media provider. Review the result before sharing."},
@@ -82,7 +82,7 @@ const capabilityCopy: Record> = {
},
},
"zh-CN": {
- context_delivery: {displayName: "差分上下文", description: "在支持的 Agent 轮次间复用未变化的上下文;无法确认基线保留时使用完整上下文。"},
+ context_delivery: {displayName: "渐进上下文", description: "先展示当前目标与约束,按需读取材料;支持的宿主可独立复用跨轮上下文。"},
codex_chat: {displayName: "Codex Goal 对话默认值", description: "分别选择 Codex 配置来源、模型、速度档和推理强度,作用于本机的新 Goal 对话。已有对话保留原历史;不会启动或重配正在运行的 Agent Loop、工作 Agent 或管家。"},
decision_context: {displayName: "资料召回", description: "通过临时私有配置查找参考证据。OpenViking、BM25 是检索实现;本页不保存绑定,也不启用自动记忆。"},
content_ops: {displayName: "内容制作", description: "准备有来源的提纲,使用可选媒体扩展制作本机视频、生成云端图像与镜头,检查作品后再分享。"},
@@ -247,9 +247,13 @@ export function localizeCapability(
export function localizedCapabilityFieldCopy(locale: WorkspaceLocale, capabilityId?: string): FieldCopy {
if (capabilityId === "context_delivery") return {...fieldCopy[locale], mode: locale === "zh-CN" ? {
- label: "Codex", description: "仅作用于支持的 Codex 心跳;显式关闭的实验保持关闭。", options: {off: "关闭", on: "开启"},
+ label: "渐进读取", description: "适用于各宿主;关闭后保留完整内联输入。", options: {off: "关闭", on: "开启"},
} : {
- label: "Codex", description: "Applies only to supported Codex heartbeats; explicitly disabled runs stay disabled.", options: {off: "Off", on: "On"},
+ label: "Progressive reads", description: "Applies across hosts; off keeps full inline input.", options: {off: "Off", on: "On"},
+ }, delta_delivery: locale === "zh-CN" ? {
+ label: "跨轮差分", description: "仅在支持连续性的宿主自动启用;可独立关闭,保留渐进读取。", options: {off: "关闭", auto: "自动"},
+ } : {
+ label: "Cross-Turn Delta", description: "Automatic only on supported continuity hosts; off preserves progressive reads.", options: {off: "Off", auto: "Automatic"},
}, antigravity_mode: locale === "zh-CN" ? {
label: "Antigravity", description: "仅作用于强能力 Antigravity 管家的交付历史渐进读取;关闭时保持完整内联。", options: {off: "关闭", on: "开启"},
} : {
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/machine-configuration-settings.tsx b/apps/presentation/dashboard/src/features/personal-workspace/machine-configuration-settings.tsx
index 0f18eeb462..7aa426d34f 100644
--- a/apps/presentation/dashboard/src/features/personal-workspace/machine-configuration-settings.tsx
+++ b/apps/presentation/dashboard/src/features/personal-workspace/machine-configuration-settings.tsx
@@ -279,7 +279,7 @@ export function MachineConfigurationSettings({ section, onChanged }: {
setNotice(null);
}
- async function setContextDelivery(mode: "off" | "on", key: "mode" | "antigravity_mode" = "mode") {
+ async function setContextDelivery(mode: "off" | "on" | "auto", key: "mode" | "delta_delivery" | "antigravity_mode" = "mode") {
if (busy || !editorAvailable || selected?.capability_id !== "context_delivery" || !selected.machine_namespace) return;
const namespace = selected.machine_namespace;
const configuration = {...selected.default, ...selectedCurrent, [key]: mode};
@@ -298,8 +298,10 @@ export function MachineConfigurationSettings({ section, onChanged }: {
if (next.machine_configuration?.namespaces[namespace]?.[key] !== mode) {
throw new Error(locale === "zh-CN" ? "保存后的配置已变化,请刷新后重试。" : "The saved configuration changed. Refresh and retry.");
}
- const targetLabel = key === "antigravity_mode" ? "Antigravity" : "Codex";
- setNotice(locale === "zh-CN" ? `${targetLabel} 偏好已保存。` : `${targetLabel} preference saved.`);
+ const targetLabel = key === "antigravity_mode" ? "Antigravity" : key === "delta_delivery"
+ ? locale === "zh-CN" ? "跨轮差分" : "Cross-turn delta"
+ : locale === "zh-CN" ? "渐进读取" : "Progressive reads";
+ setNotice(locale === "zh-CN" ? `${targetLabel}偏好已保存。` : `${targetLabel} preference saved.`);
onChanged?.();
} catch (cause) {
if (generation === editorGeneration.current) setError(cause instanceof Error ? cause.message : t("machine.applyError"));
@@ -526,12 +528,17 @@ export function MachineConfigurationSettings({ section, onChanged }: {
) : null}
- {selected.capability_id === "context_delivery" ?
+ {selected.capability_id === "context_delivery" ?
+ {(selectedCurrent?.delta_delivery ?? selected.default?.delta_delivery ?? "auto") === "auto"
+ ? locale === "zh-CN" ? "跨轮差分自动选择;当前会话是否采用尚未验证。" : "Delta is automatic; current-session use is unverified."
+ : locale === "zh-CN" ? "跨轮差分已关闭。" : "Cross-turn delta is off."}
{(selectedCurrent?.antigravity_mode ?? selected.default?.antigravity_mode ?? "on") === "on"
? locale === "zh-CN" ? "Antigravity 管家历史渐进读取已开启。" : "Antigravity progressive manager history is on."
: locale === "zh-CN" ? "Antigravity 已关闭。" : "Off for Antigravity."}
- {locale === "zh-CN"
- ? "Codex(mode)与 Antigravity(antigravity_mode)独立控制:受支持的 POSIX Codex App/SSH 和 benchmark 心跳默认开启差分,已保存的关闭继续生效,benchmark trial 可单独显式关闭;强能力 Antigravity 管家默认开启私有快照的交付历史渐进读取,关闭时保持完整内联。其他应用和平台保留完整交付;显式开启遇到未知或冲突跑法会报错。保存偏好不代表当前会话已采用差分。宿主就绪且旧上下文完整时才使用差分,否则完整恢复;私有存储与会话隔离自动管理。"
- : "Codex (mode) and Antigravity (antigravity_mode) are controlled independently: supported POSIX Codex App/SSH and benchmark heartbeats default on (saved off is preserved; benchmark trials can disable it independently), while trusted-owner Antigravity manager turns default on for progressive private-capture history reads and keep full inline input when off. Other applications and platforms retain full delivery. Explicit on rejects unknown or conflicting modes. Saving a preference does not establish current-session adoption. Delta needs a ready host and complete retained context; otherwise full context is restored. Private storage and session isolation are automatic."}
+ {locale === "zh-CN"
+ ? "渐进读取先提供当前要求,支持材料按需展开,适用于所有宿主。跨轮差分独立控制:仅在受支持的 POSIX Codex App/SSH、benchmark 心跳已保留完整旧上下文时自动使用,否则恢复完整当前输入。Antigravity 管家历史另有独立开关。关闭偏好和实验显式关闭均继续生效。保存不会安装 hook、启动实验或证明当前会话已采用差分。"
+ : "Progressive reads present current requirements before expandable supporting material on every host. Cross-turn delta is independent: automatic reuse requires a supported POSIX Codex App/SSH or benchmark heartbeat and complete retained context; otherwise the current full input is restored. Antigravity manager history has its own switch. Saved off preferences and explicit experiment opt-outs remain effective. Saving installs no hook, starts no experiment and does not prove current-session delta use."}
: null}
{editorAvailable && selected.capability_id !== "context_delivery" ? <>{editorMode === "json" || !selected.configuration_editor.fields.some((field) => field.key === "enabled" && field.input_kind === "boolean") ?
changeMode(editorMode === "guided" ? "json" : "guided")} type="button">
diff --git a/loopx/capabilities/configuration_ui.py b/loopx/capabilities/configuration_ui.py
index 8ae7f745f2..2960570c97 100644
--- a/loopx/capabilities/configuration_ui.py
+++ b/loopx/capabilities/configuration_ui.py
@@ -85,16 +85,17 @@ def capability_configuration_editor(
# effort the owning namespace would reject.
steward_endpoints, steward_efforts = _steward_executor_editor_options()
from .native_chat.machine_defaults import codex_profile_options
- from ..control_plane.turn_driver.codex_context import CONTEXT_DELIVERY_SETTINGS
definitions: dict[str, dict[str, Any]] = {
"context_delivery": {
"supported_scopes": ["machine"], "writable_scopes": ["machine"],
"fields": [
- _field("mode", "Codex App / benchmark heartbeats", "select",
- options=CONTEXT_DELIVERY_SETTINGS, required=True,
- description="On accepts only declared Codex App or benchmark heartbeats. Native host setup is still required; unsupported or unknown modes return an error."),
+ _field("mode", "Context presentation", "select",
+ options=("off", "on"), required=True,
+ description="Present current requirements before expandable supporting material on every host. Off keeps complete inline delivery."),
+ _field("delta_delivery", "Cross-Turn Delta", "select", options=("off", "auto"), required=True,
+ description="Auto reuses exact saved captures only on supported continuity hosts. Off leaves progressive presentation enabled. Neither choice proves retained model input."),
_field("antigravity_mode", "Antigravity manager history", "select",
- options=CONTEXT_DELIVERY_SETTINGS, required=True,
+ options=("off", "on"), required=True,
description="On defers trusted-owner Antigravity manager delivery histories to private capture reads while keeping current facts inline; off keeps full inline input."),
],
},
diff --git a/loopx/capabilities/machine_configuration/context_delivery.py b/loopx/capabilities/machine_configuration/context_delivery.py
index d8e63e3bd1..70b38cea59 100644
--- a/loopx/capabilities/machine_configuration/context_delivery.py
+++ b/loopx/capabilities/machine_configuration/context_delivery.py
@@ -5,7 +5,6 @@
from typing import Any
from .contract import MachineConfigurationNamespace
-from ...control_plane.turn_driver.codex_context import CONTEXT_DELIVERY_SETTINGS
CONTEXT_DELIVERY_MACHINE_SCHEMA = "context_delivery_machine_defaults_v0"
@@ -13,16 +12,19 @@
def normalize_context_delivery_machine_defaults(raw: Mapping[str, Any]) -> dict[str, Any]:
keys = set(raw)
- if not ({"schema_version", "mode"} <= keys <= {"schema_version", "mode", "antigravity_mode"}) or (
+ if not ({"schema_version", "mode"} <= keys <= {"schema_version", "mode", "delta_delivery", "antigravity_mode"}) or (
raw.get("schema_version") != CONTEXT_DELIVERY_MACHINE_SCHEMA
):
raise ValueError("context_delivery requires its schema_version and mode")
antigravity_mode = raw.get("antigravity_mode", "on")
- if raw["mode"] not in CONTEXT_DELIVERY_SETTINGS or antigravity_mode not in CONTEXT_DELIVERY_SETTINGS:
- raise ValueError("context_delivery mode must be off or on")
+ delta = raw.get("delta_delivery", "auto")
+ if (raw["mode"] not in ("off", "on") or antigravity_mode not in ("off", "on")
+ or delta not in ("off", "auto")):
+ raise ValueError("context_delivery mode and antigravity_mode must be off/on; delta_delivery off/auto")
return {
"schema_version": CONTEXT_DELIVERY_MACHINE_SCHEMA,
"mode": raw["mode"],
+ "delta_delivery": delta,
"antigravity_mode": antigravity_mode,
}
@@ -34,9 +36,10 @@ def context_delivery_machine_configuration_namespace() -> MachineConfigurationNa
normalize=normalize_context_delivery_machine_defaults,
project_public=lambda value: dict(value),
apply_public_update=lambda current, update: {**dict(current or {}), **dict(update)},
- title="Differential context",
+ title="Progressive context",
description=(
- "Reuse unchanged context for Codex App heartbeats, SSH Goals and benchmark heartbeats (`mode`), "
+ "Read current requirements before expandable supporting material on every host (`mode`). "
+ "Reuse unchanged context independently on supported continuity hosts (`delta_delivery`), "
"and read trusted-owner Antigravity manager delivery histories progressively from private captures "
"(`antigravity_mode`). Both default on independently; explicit unsupported Codex activation fails "
"and known context loss or disabled provider preferences keep full context. "
@@ -47,6 +50,7 @@ def context_delivery_machine_configuration_namespace() -> MachineConfigurationNa
default_configuration={
"schema_version": CONTEXT_DELIVERY_MACHINE_SCHEMA,
"mode": "on",
+ "delta_delivery": "auto",
"antigravity_mode": "on",
},
)
diff --git a/loopx/cli_commands/context_machine.py b/loopx/cli_commands/context_machine.py
index df9d522f54..cc6622bc15 100644
--- a/loopx/cli_commands/context_machine.py
+++ b/loopx/cli_commands/context_machine.py
@@ -94,6 +94,7 @@ def apply_context_machine_options(
from ..paths import effective_runtime_root
runtime_root = effective_runtime_root(registry_path, runtime_root_arg)
using_default = False
+ value: dict[str, Any] = {}
if explicit is None:
from ..capabilities.machine_configuration.builtins import build_builtin_machine_configuration_registry
from ..capabilities.machine_configuration.store import read_machine_configuration
@@ -106,16 +107,18 @@ def apply_context_machine_options(
using_default = value is None
if using_default:
value = machine_registry.resolve("context_delivery").public_descriptor()["configuration_template"]
- if value["mode"] == "off" or (using_default and os.name != "posix"):
- return
- if command == "should-run" and not (
- getattr(args, "turn_instance_id", None) or bool(getattr(args, "begin_turn", False))
- ):
- args.context_delivery = "off"
+ if value["mode"] == "off":
return
+ # Presentation is host-neutral. Only Delta needs declared lifecycle
+ # continuity. A read-only query must not manufacture an admitted Turn.
+ args.context_delivery = explicit or "auto"
+ if getattr(args, "delta_delivery", None) is None:
+ args.delta_delivery = value.get("delta_delivery", "auto")
+ if ((command == "should-run" and not (getattr(args, "turn_instance_id", None)
+ or bool(getattr(args, "begin_turn", False)))) or os.name != "posix") and explicit != "on":
+ args.delta_delivery = "off"
# Recovery does not activate a run mode or create a missing session.
if command != "context-read":
- args.context_delivery = "on"
try:
enabled = context_delivery_for_arguments(args, codex_machine_preference=explicit is None)["enabled"]
except ValueError:
@@ -125,13 +128,20 @@ def apply_context_machine_options(
# Ordinary CLI and unknown declarations retain their original path;
# explicit on still rejects an unsupported or conflicting host.
enabled = False
- if not enabled:
- args.context_delivery = "off"
- return
- if command == "should-run" and args.format != "json":
+ if command == "should-run" and args.format != "json" and enabled:
raise ValueError("native Codex context delivery needs JSON and a capture destination")
if explicit is None:
args._context_delivery_machine_runtime = str(runtime_root.expanduser().resolve())
+ if command == "should-run" and args.format == "json":
+ args._progressive_context_runtime = str(runtime_root.expanduser().resolve())
+ if command != "context-read" and not enabled:
+ return # Stateless presentation needs neither a journal nor native setup.
+ if (heartbeat and explicit != "on" and any(getattr(args, field, False) for field in ("brief", "compact", "full"))
+ and not any(getattr(args, field, None) for field in ("codex_context_dir", "codex_context_root",
+ "decision_output_dir", "decision_output_root", "decision_handoff_socket"))):
+ # Rendering an expanded prompt does not start native transport. Its
+ # generated guard retains AUTO and resolves paths when actually run.
+ return
# An off/on round trip can miss lifecycle events. Store replacement
# invalidates reuse even when its content hash returns to the old value.
# This metadata only narrows reuse; it is not retention or work authority.
diff --git a/loopx/cli_commands/quota.py b/loopx/cli_commands/quota.py
index 8d05efbc4c..e3ed262702 100644
--- a/loopx/cli_commands/quota.py
+++ b/loopx/cli_commands/quota.py
@@ -15,7 +15,7 @@
from .quota_capture import (
bind_capture_selection_transport, budgeted_settlement_result, capture_decision, handoff_decision,
handle_native_context_command, handle_replan_view, prepare_quota_capture, native_context_capture_view,
- native_context_activation, model_context_reference,
+ native_context_activation, model_context_reference, progressive_context_capture_view,
)
from ..control_plane.turn_driver.decision_capture import (
project_captured_context,
@@ -23,6 +23,7 @@
from ..usage_goal import observe_quota_result
from ..control_plane.coordination.local_authority import CanonicalAuthorityRequired
+from ..control_plane.effect_runtime import EffectRuntimeRemoteError, EffectRuntimeStartupError
from ..control_plane.quota.effect_program import SettlementIdentity
from ..control_plane.quota.error_codes import (
CloseoutQueryUnavailableError,
@@ -360,12 +361,14 @@ def _emit_quota_result(
print_payload(view, args.format, _quota_renderer(args, failure=payload.get("ok") is not True))
return 0 if payload.get("ok") is True else 1
try:
- context_delivery_enabled = native_context_activation(args)["enabled"]
+ activation = native_context_activation(args)
+ context_delivery_enabled = activation["enabled"]
except QuotaCommandValidationError:
if payload.get("ok") is True:
raise
# Preserve the original validation error when activation itself failed.
context_delivery_enabled = False
+ activation = {"progressive_enabled": False}
bind_capture_selection_transport(payload, args)
delivery_request = None
decision_identity = ("", "")
@@ -426,6 +429,18 @@ def _emit_quota_result(
request=delivery_request[0], capture_id=delivery_request[1],
goal_id=decision_identity[0], agent_id=decision_identity[1],
surface="turn_envelope" if getattr(args, "turn_envelope", False) else "quota_packet")
+ if (not deferred_context and args.format == "json" and succeeded and args.quota_command == "should-run"
+ and activation["progressive_enabled"] and not native_context and delivery_request is None):
+ try:
+ payload = progressive_context_capture_view(payload, args,
+ runtime_root=context.runtime_root if context is not None else Path(args._progressive_context_runtime),
+ directory=capture_directory,
+ surface="turn_envelope" if getattr(args, "turn_envelope", False) else "quota_packet",
+ reader_argv=reader_argv)
+ except (QuotaDecisionTransportError, OSError, ValueError, EffectRuntimeRemoteError, EffectRuntimeStartupError):
+ # Stateless optional presentation has no stale native selector.
+ # Retain this complete decided input/receipt when capture fails.
+ pass
if (not deferred_context and args.format == "json" and succeeded and capture_directory
and native_context):
import hashlib
@@ -446,7 +461,8 @@ def _emit_quota_result(
payload = project_codex_context(payload, directory=directory,
capture_directory=capture_directory, goal_id=decision_identity[0], agent_id=decision_identity[1],
surface="turn_envelope" if getattr(args, "turn_envelope", False) else "quota_packet",
- capture_id=capture_id, continuity_generation=getattr(args, "_context_delivery_generation", None))
+ capture_id=capture_id, continuity_generation=getattr(args, "_context_delivery_generation", None),
+ progressive_enabled=activation["progressive_enabled"])
recovery = payload.get("recovery")
# Without a prepared native projection, the view adapter publishes
# this complete CLI view and its reader commands as current recovery.
@@ -614,7 +630,7 @@ def handle_quota_command(
status_payload,
goal_id=args.goal_id,
agent_id=args.agent_id,
- inline_goal_source=native_context_activation(args)["enabled"],
+ inline_goal_source=native_context_activation(args)["progressive_enabled"],
available_capabilities=args.available_capabilities,
include_scheduler_detail="scheduler" in detail_sections,
include_agent_todo_detail=(
@@ -644,7 +660,7 @@ def handle_quota_command(
interaction_projection_hooks=interaction_projection_hooks,
turn_start_hook_dispatch=turn_start_hook_dispatch,
context_navigation=(
- native_context_activation(args)["enabled"]
+ native_context_activation(args)["progressive_enabled"]
and not bool(getattr(args, "turn_envelope", False))
),
goal_ref=goal_ref,
diff --git a/loopx/cli_commands/quota_capture.py b/loopx/cli_commands/quota_capture.py
index 37a31d584f..b23e25868b 100644
--- a/loopx/cli_commands/quota_capture.py
+++ b/loopx/cli_commands/quota_capture.py
@@ -517,6 +517,7 @@ def _native_context_read_bytes(reference: dict[str, Any], raw: bytes, *,
def native_context_capture_view(projected: dict[str, Any], directory: Path, *,
context_directory: str | None = None,
+ captured_recovery: dict[str, Any] | None = None,
metadata: dict[str, Any] | None = None,
max_page_output_bytes: int | None = None,
reader_argv: list[str] | None = None) -> dict[str, Any]:
@@ -537,13 +538,13 @@ def native_context_capture_view(projected: dict[str, Any], directory: Path, *,
typed = projected.get("schema_version") == "context_delivery_v1"
mode = projected["mode"] if typed else "full"
ancestry = projected.get("ancestry", 0)
- publish_wire = not (typed and mode == "full")
+ publish_wire = captured_recovery is None and not (typed and mode == "full")
wire = directory / "delivery.json"
raw = _native_output_bytes(projected) if publish_wire else b""
reference = ({"path": str(wire), "sha256": hashlib.sha256(raw).hexdigest()}
- if publish_wire else projected["recovery"])
- current = (projected.get("recovery") if typed else None) or reference
- current_raw = Path(current["path"]).read_bytes() if typed else raw
+ if publish_wire else captured_recovery or projected["recovery"])
+ current = captured_recovery or (projected.get("recovery") if typed else None) or reference
+ current_raw = Path(current["path"]).read_bytes() if typed or captured_recovery is not None else raw
current_document = json.loads(current_raw)
if not publish_wire:
raw = current_raw
@@ -608,6 +609,33 @@ def view(kind: str, ref: dict[str, Any], body: bytes) -> dict[str, Any]:
return result
+def progressive_context_capture_view(payload: dict[str, Any], args: argparse.Namespace, *,
+ runtime_root: Path, directory: Path | None,
+ surface: str = "quota_packet",
+ reader_argv: list[str] | None = None) -> dict[str, Any]:
+ """Same-capture presentation for every caller, without a native journal.
+
+ A plain read-only should-run remains read-only. Private transport files do
+ not admit work, mint a Turn or stand in for observed model consumption.
+ """
+ from .context_machine import _private_transport_root
+ from ..control_plane.turn_driver.decision_capture import capture_progressive_context
+
+ if directory is None:
+ root = Path(_private_transport_root(runtime_root))
+ directory = Path(tempfile.mkdtemp(prefix="context-", dir=root))
+ bind_capture_selection_transport(payload, args, capture_root=directory.parent)
+ required, reference = capture_progressive_context(payload, directory=directory, surface=surface)
+ view = native_context_capture_view(required, directory, captured_recovery=reference,
+ metadata={"context_delivery": native_context_activation(args),
+ **({"capture_sha256": args.capture_sha256} if getattr(args, "capture_sha256", None) else {})},
+ max_page_output_bytes=getattr(args, "max_page_output_bytes", None), reader_argv=reader_argv)
+ readable = model_context_reference(view, reader_argv=reader_argv)
+ # Small results need no extra navigation. The complete original and required
+ # captures remain available; never shrink by dropping current obligations.
+ return readable if len(_native_output_bytes(readable)) < len(_native_output_bytes(required)) else required
+
+
def project_saved_context_capture(args: argparse.Namespace) -> dict[str, Any]:
"""Present an immutable already-decided quota capture, without authority IO.
@@ -646,6 +674,15 @@ def project_saved_context_capture(args: argparse.Namespace) -> dict[str, Any]:
target = None
native_prepared = False
native_view = None
+ if not activation["enabled"] and activation["progressive_enabled"]:
+ # Recovery is presentation of this exact saved decision, including its
+ # original Turn. It does not need a supported host or a native session.
+ try:
+ return progressive_context_capture_view(payload, args,
+ runtime_root=Path(getattr(args, "_context_delivery_machine_runtime", path.parent)),
+ directory=None, reader_argv=reader_argv)
+ except (QuotaDecisionTransportError, OSError, ValueError, EffectRuntimeRemoteError, EffectRuntimeStartupError):
+ pass # The complete original reference remains the fallback below.
try:
from ..control_plane.turn_driver.codex_context import codex_context_directory, project_codex_context
@@ -685,7 +722,8 @@ def project_saved_context_capture(args: argparse.Namespace) -> dict[str, Any]:
projected = project_codex_context(payload, directory=directory, capture_directory=cache,
goal_id=args.goal_id, agent_id=args.agent_id, surface="quota_packet",
capture_id=hashlib.sha256(raw).hexdigest(),
- continuity_generation=getattr(args, "_context_delivery_generation", None))
+ continuity_generation=getattr(args, "_context_delivery_generation", None),
+ progressive_enabled=activation["progressive_enabled"])
native_prepared = True
if projected.get("schema_version") == "context_delivery_v1":
# Native publication owns the complete required view. Keep its
@@ -931,6 +969,8 @@ def bind_capture_selection_transport(payload: dict[str, Any], args: argparse.Nam
options["--decision-handoff-socket"] = args.decision_handoff_socket
if getattr(args, "context_delivery", "off") != "off":
options["--context-delivery"] = args.context_delivery
+ if getattr(args, "delta_delivery", None) is not None:
+ options["--delta-delivery"] = args.delta_delivery
if getattr(args, "codex_context_dir", None):
options["--codex-context-dir"] = args.codex_context_dir
if getattr(args, "codex_context_root", None):
diff --git a/loopx/cli_commands/quota_registration.py b/loopx/cli_commands/quota_registration.py
index 56762e4b68..f88a0f6435 100644
--- a/loopx/cli_commands/quota_registration.py
+++ b/loopx/cli_commands/quota_registration.py
@@ -217,13 +217,15 @@ def register_quota_command(
# Host preflight captures the complete native input, then presents that same
# immutable view after the model's lifecycle hooks establish continuity.
quota_parser.add_argument("--defer-context-presentation", action="store_true", help=argparse.SUPPRESS)
- from ..control_plane.turn_driver.codex_context import CONTEXT_DELIVERY_SETTINGS
+ from ..control_plane.turn_driver.codex_context import CONTEXT_DELIVERY_SETTINGS, DELTA_DELIVERY_SETTINGS
quota_parser.add_argument("--context-delivery", choices=CONTEXT_DELIVERY_SETTINGS,
- help="Experimental native packet reuse; inherits the machine setting, otherwise off. Explicit off bypasses machine defaults. On uses existing host declarations: "
+ help="Auto defaults to progressive current-context reads on every host, with Delta on supported continuity hosts. Explicit off keeps the original inline path. Legacy on uses existing host declarations: "
"Codex App heartbeat/resume/recovery (--codex-app), or the Codex benchmark heartbeat worker "
"(generic_cli plus its explicit heartbeat worker settings). On rejects missing, contradictory or unsupported modes. "
"Enabled supported calls choose private context/capture paths automatically unless overridden. A directory alone never enables it; declarations are not retention proof.")
+ quota_parser.add_argument("--delta-delivery", choices=DELTA_DELIVERY_SETTINGS,
+ help="Independently disable cross-Turn Delta or use it automatically on supported continuity hosts. Does not disable progressive presentation or grant host continuity.")
context_location = quota_parser.add_mutually_exclusive_group()
context_location.add_argument("--codex-context-dir",
help="Opt-in private native Codex lifecycle directory. For context-hook, consume one native hook event on stdin. "
diff --git a/loopx/cli_commands/support_control_heartbeat.py b/loopx/cli_commands/support_control_heartbeat.py
index 148b6ab141..1d558b7282 100644
--- a/loopx/cli_commands/support_control_heartbeat.py
+++ b/loopx/cli_commands/support_control_heartbeat.py
@@ -170,6 +170,7 @@ def handle_heartbeat_prompt_command(
codex_context_dir=args.codex_context_dir,
codex_context_root=args.codex_context_root,
context_delivery=args.context_delivery,
+ delta_delivery=args.delta_delivery or "auto",
turn_envelope=args.turn_envelope,
reward_memory_enabled=reward_memory_enabled,
)
diff --git a/loopx/cli_commands/support_control_heartbeat_registration.py b/loopx/cli_commands/support_control_heartbeat_registration.py
index 4ac448ef69..09c1749d65 100644
--- a/loopx/cli_commands/support_control_heartbeat_registration.py
+++ b/loopx/cli_commands/support_control_heartbeat_registration.py
@@ -180,13 +180,15 @@ def register_heartbeat_control_commands(
help="Retain the explicit private Host handoff on generated guards; requires --decision-output-root.",
)
- from ..control_plane.turn_driver.codex_context import CONTEXT_DELIVERY_SETTINGS
+ from ..control_plane.turn_driver.codex_context import CONTEXT_DELIVERY_SETTINGS, DELTA_DELIVERY_SETTINGS
heartbeat_prompt_parser.add_argument("--context-delivery", choices=CONTEXT_DELIVERY_SETTINGS,
- help="Experimental native packet reuse; inherits the machine setting, otherwise off. Explicit off bypasses machine defaults. On uses existing host declarations: "
+ help="Auto presents context progressively across hosts, with independent Delta on supported continuity hosts. Explicit off preserves complete inline delivery. Legacy on uses existing declarations: "
"Codex App heartbeat/resume/recovery (--codex-app), or the Codex benchmark heartbeat worker "
"(generic_cli plus its explicit heartbeat worker settings). On rejects missing, contradictory or unsupported modes. "
"Enabled supported calls choose private context/capture paths automatically unless overridden. A directory alone never enables it; declarations are not retention proof.")
+ heartbeat_prompt_parser.add_argument("--delta-delivery", choices=DELTA_DELIVERY_SETTINGS,
+ help="Independently disable cross-Turn Delta or inherit supported-host automatic reuse. Progressive reads remain enabled.")
context_location = heartbeat_prompt_parser.add_mutually_exclusive_group()
context_location.add_argument(
"--codex-context-dir",
diff --git a/loopx/control_plane/heartbeat/bootstrap_prompt.py b/loopx/control_plane/heartbeat/bootstrap_prompt.py
index 183b5812cc..9694a21fe3 100644
--- a/loopx/control_plane/heartbeat/bootstrap_prompt.py
+++ b/loopx/control_plane/heartbeat/bootstrap_prompt.py
@@ -72,6 +72,7 @@ def _goal_command(args: Any, *, registry: Path, legacy: bool) -> list[str]:
("decision_output_root", "--decision-output-root"),
("codex_context_root", "--codex-context-root"),
("context_delivery", "--context-delivery"),
+ ("delta_delivery", "--delta-delivery"),
):
value = getattr(args, field, None)
if value is not None:
@@ -130,7 +131,7 @@ def host_bootstrap_binding(prompt: str) -> dict[str, Any] | None:
"registry", "runtime_root", "goal_id", "agent_id", "active_state",
"material_rule", "permission_rule", "runtime_profile", "visible_goal_host",
"host_surface", "scheduler_owner", "execution_mode", "cli_bin",
- "decision_output_root", "codex_context_root", "context_delivery")}
+ "decision_output_root", "codex_context_root", "context_delivery", "delta_delivery")}
repeated = {"--agent-scope": "agent_scopes", "--available-capability": "available_capabilities"}
booleans = {
"--codex-app": "codex_app",
diff --git a/loopx/control_plane/heartbeat/builder.py b/loopx/control_plane/heartbeat/builder.py
index 40bb2aea0b..aebd7a4360 100644
--- a/loopx/control_plane/heartbeat/builder.py
+++ b/loopx/control_plane/heartbeat/builder.py
@@ -178,8 +178,9 @@ def _heartbeat_prompt_commands(
decision_handoff_socket: str | None,
codex_context_dir: str | None,
codex_context_root: str | None,
- context_delivery: str,
+ context_delivery: str | None,
turn_envelope: bool,
+ delta_delivery: str = "auto",
) -> dict[str, str | None]:
quota_guard_command = render_quota_guard_command(
goal_id,
@@ -279,16 +280,22 @@ def _heartbeat_prompt_commands(
"brief_prompt_command": brief_prompt_command,
"thin_prompt_command": thin_prompt_command,
}
+ capture_arg = ""
if decision_output_root is not None:
capture_arg = " --decision-output-root " + shlex.quote(str(decision_output_root))
+ if context_delivery is not None:
+ capture_arg += " --context-delivery " + shlex.quote(context_delivery)
if decision_handoff_socket is not None:
capture_arg += " --decision-handoff-socket " + shlex.quote(decision_handoff_socket)
- if context_delivery != "off":
- capture_arg += " --context-delivery " + shlex.quote(context_delivery)
if codex_context_dir is not None:
capture_arg += " --codex-context-dir " + shlex.quote(codex_context_dir)
if codex_context_root is not None:
capture_arg += " --codex-context-root " + shlex.quote(codex_context_root)
+ elif context_delivery is not None:
+ capture_arg += " --context-delivery " + shlex.quote(context_delivery)
+ if delta_delivery != "auto":
+ capture_arg += " --delta-delivery " + shlex.quote(delta_delivery)
+ if capture_arg:
display_arg = " --turn-envelope" if turn_envelope else ""
for key in ("quota_guard_command", "task_body_quota_guard_command"):
commands[key] = str(commands[key]) + display_arg + capture_arg
@@ -326,7 +333,8 @@ def build_heartbeat_prompt(
decision_handoff_socket: str | None = None,
codex_context_dir: str | None = None,
codex_context_root: str | None = None,
- context_delivery: str = "off",
+ context_delivery: str | None = None,
+ delta_delivery: str = "auto",
turn_envelope: bool = False,
) -> dict[str, Any]:
if not (full or compact or brief or thin):
@@ -389,13 +397,17 @@ def build_heartbeat_prompt(
import os
- activation = context_delivery_activation(context_delivery, runtime_profile=runtime_profile,
+ activation = context_delivery_activation(context_delivery or "off", runtime_profile=runtime_profile,
scheduler_execution_context=scheduler_execution_context,
+ delta_delivery=delta_delivery,
benchmark_mode=os.environ.get("LOOPX_EXECUTION_MODE")
if os.environ.get("LOOPX_CONTEXT_DELIVERY") == "on" else None)
if not activation["enabled"]:
codex_context_dir = codex_context_root = None
effective_context_delivery = "on" if activation["enabled"] else "off"
+ if context_delivery != "on" and not any((decision_output_root, decision_handoff_socket,
+ codex_context_dir, codex_context_root)):
+ effective_context_delivery = "off" # prompt rendering is not native capture activation
decision_output_root = resolve_heartbeat_capture_root(
decision_output_root,
thin=thin, full=full, compact=compact, brief=brief,
@@ -496,7 +508,8 @@ def build_heartbeat_prompt(
decision_handoff_socket=decision_handoff_socket,
codex_context_dir=codex_context_dir,
codex_context_root=codex_context_root,
- context_delivery=effective_context_delivery,
+ context_delivery=context_delivery,
+ delta_delivery=delta_delivery,
turn_envelope=turn_envelope,
)
cli_preflight = render_cli_preflight(cli_bin=cli_bin)
diff --git a/loopx/control_plane/quota/native_context_lifecycle.ts b/loopx/control_plane/quota/native_context_lifecycle.ts
index 4ba2e50773..06e551f741 100644
--- a/loopx/control_plane/quota/native_context_lifecycle.ts
+++ b/loopx/control_plane/quota/native_context_lifecycle.ts
@@ -47,6 +47,9 @@ export function updateNativeContextLifecycle(request: JsonObject): JsonObject {
delete state.candidate;
delete state.pending;
delete state.active_call; // retire legacy diagnostic-call binding
+ delete state.consumed_pointers;
+ delete state.confirmed_read_sections;
+ delete state.section_reads;
};
if (name === "SessionStart") {
// The provider may qualify the native-selected replay source against the
@@ -92,6 +95,31 @@ export function updateNativeContextLifecycle(request: JsonObject): JsonObject {
for (const value of pages) {
const page = jsonObject(value);
if (!page || page.schema_version !== "context_capture_page_v1") continue;
+ const selected = jsonObject(page.read_sections);
+ if (selected) {
+ // IO has checked exact selected bytes against this journal's current full
+ // source. This is observed tool delivery, never a full-input baseline.
+ if (request.pages_verified !== true || page.ok !== true
+ || page.source_sha256 !== jsonObject(state.source_recovery)?.sha256) continue;
+ const offset = page.offset, total = page.total_bytes, end = page.eof === true ? total : page.next_offset;
+ if (!Number.isSafeInteger(total) || Number(total) <= 0 || !Number.isSafeInteger(offset)
+ || !Number.isSafeInteger(end) || Number(offset) < 0 || Number(end) <= Number(offset)
+ || Number(end) > Number(total) || typeof page.content !== "string"
+ || Buffer.byteLength(page.content) !== Number(end) - Number(offset)
+ || (page.eof === true && page.next_offset !== null)
+ || (page.eof === false && Number(end) >= Number(total)) || typeof page.sha256 !== "string") continue;
+ const reads = jsonObject(state.section_reads) ?? {};
+ const previous = jsonObject(reads[page.sha256]);
+ const ranges = mergedRanges(previous?.ranges, Number(offset), Number(end));
+ reads[page.sha256] = {ranges};
+ if (ranges.length === 1 && ranges[0][0] === 0 && ranges[0][1] === total) {
+ state.consumed_pointers = {...jsonObject(state.consumed_pointers), ...selected};
+ state.confirmed_read_sections = Object.keys(state.consumed_pointers as JsonObject);
+ delete reads[page.sha256];
+ }
+ state.section_reads = reads;
+ continue;
+ }
if ("selection_sha256" in page || "selected_pointers" in page || "list_fields" in page) continue;
const candidate = jsonObject(state.candidate);
if (!state.pending && candidate?.capture_sha256 === recovery.sha256
@@ -129,6 +157,11 @@ export function updateNativeContextLifecycle(request: JsonObject): JsonObject {
state.candidate = {basis: NATIVE_CONTEXT_BASIS, capture_bytes_verified: true, target,
capture_file: recovery.path, capture_sha256: recovery.sha256,
ancestry: original ? 0 : pending?.ancestry ?? 0};
+ const sections = jsonObject(reads.read_sections);
+ if (sections) {
+ state.consumed_pointers = {...jsonObject(state.consumed_pointers), ...sections};
+ state.confirmed_read_sections = Object.keys(state.consumed_pointers as JsonObject);
+ }
delete state.pending;
}
return state;
diff --git a/loopx/control_plane/quota/progressive_context.ts b/loopx/control_plane/quota/progressive_context.ts
index b0ca41608a..62b715eac9 100644
--- a/loopx/control_plane/quota/progressive_context.ts
+++ b/loopx/control_plane/quota/progressive_context.ts
@@ -1,4 +1,4 @@
-/** Native model presentation: requirements stay inline, supporting material is
+/** Model presentation: requirements stay inline, supporting material is
* addressed in the immutable source. This plan changes no canonical state. */
import type {JsonObject} from "../effect_program.ts";
import {jsonObject, requireJsonObject} from "../runtime_decode.ts";
@@ -7,14 +7,38 @@ import {FULL_OUTCOME_READ_GUIDANCE, PROGRESSIVE_OUTCOME_READ_GUIDANCE} from "../
import {quotaSummaryReferences, contextSourceIdentity, contextProjectionChanges,
type ProjectionSourceValues} from "./diagnostic_projection.ts";
import {encodeContextDelivery} from "./context_delivery.ts";
+import {createHash} from "node:crypto";
type Path = (string | number)[];
-const pointer = (path: Path): string => "/" + path.map(key =>
- String(key).replaceAll("~", "~0").replaceAll("/", "~1")).join("/");
+const pointer = (path: Path): string => path.length ? "/" + path.map(key =>
+ String(key).replaceAll("~", "~0").replaceAll("/", "~1")).join("/") : "";
const at = (root: unknown, path: Path): unknown => path.reduce((row, key) =>
Array.isArray(row) ? row[Number(key)] : jsonObject(row)?.[key], root);
const known = (row: JsonObject, fields: string[]): boolean => Object.keys(row).every(key => fields.includes(key));
+/** Digests stay in the private observed-read journal, never repeated to the model.
+ * The existing exact-source identity preserves non-JS numeric spellings. */
+export function contextReadSectionDigests(request: JsonObject, pointers: string[]): JsonObject {
+ const context = requireJsonObject(request.context, "read section source");
+ const identity = contextSourceIdentity(request, request.source_number_tokens);
+ return Object.fromEntries(pointers.map(address => {
+ const path = address === "" ? [] : address.slice(1).split("/").map(key => key.replaceAll("~1", "/").replaceAll("~0", "~"));
+ return [address, createHash("sha256").update(identity(at(context, path), ["context", ...path])).digest("hex")];
+ }));
+}
+
+function inlineReadSections(request: JsonObject, required: JsonObject): JsonObject {
+ const original = requireJsonObject(request.context, "inline source"), paths: string[] = [];
+ const visit = (source: unknown, shown: unknown, path: Path) => {
+ if (source === shown) { paths.push(pointer(path)); return; }
+ if (!source || !shown || typeof source !== "object" || typeof shown !== "object") return;
+ for (const key of Object.keys(source)) if (Object.hasOwn(shown, key)) visit(
+ (source as JsonObject)[key], (shown as JsonObject)[key], [...path, Array.isArray(source) ? Number(key) : key]);
+ };
+ visit(original, required, []);
+ return contextReadSectionDigests(request, paths);
+}
+
/** Return paths instead of round-tripping the caller's JSON numeric values
* through JS. The IO adapter performs only these typed-owner-selected edits. */
export function progressiveContextPlan(request: JsonObject): JsonObject {
@@ -147,12 +171,31 @@ function requiredNativeContext(request: JsonObject, sourceValues: ProjectionSour
const path = edit.path as Path;
parent(path)[path.at(-1)!] = edit.value;
}
- if (deferred.length) required.context_details = {...details,
+ if (deferred.length) {
+ const consumed = jsonObject(request.consumed_pointers) ?? {};
+ const digests = new Map();
+ const currentDigest = (path: Path) => {
+ const address = pointer(path);
+ if (!digests.has(address)) digests.set(address,
+ createHash("sha256").update(identity(at(context, path), ["context", ...path])).digest("hex"));
+ return digests.get(address);
+ };
+ const hasRead = (path: Path) => path.map((_, i) => path.slice(0, i + 1)).concat([[]]).some(parent => {
+ const address = pointer(parent), seen = consumed[address];
+ return typeof seen === "string" && currentDigest(parent) === seen;
+ });
+ const sourcePath: Path = ["interaction_contract", "agent_channel", "work_context", "sources"];
+ const sources = at(context, sourcePath);
+ required.context_details = {...details, source_path: details.path,
unread_context_index: {
source: {path: details.path, sha256: details.sha256},
coverage_confirmed: false,
read_before_dependent_work: true,
- pointers: [...new Set(deferred.map(edit => pointer(edit.path as Path)))],
+ pointers: [...new Set(deferred.filter(edit => !hasRead(edit.path as Path)).map(edit => pointer(edit.path as Path)))],
+ source_blocks: Array.isArray(sources) ? sources.flatMap((source, i) => {
+ const path = [...sourcePath, i, "content"];
+ return jsonObject(source)?.content !== undefined && !hasRead(path) ? [pointer(path)] : [];
+ }) : [],
},
instruction: "This view retains complete requirements and current review/check states. "
+ "Source history, review reasoning and evidence references are supporting material. "
@@ -160,11 +203,13 @@ function requiredNativeContext(request: JsonObject, sourceValues: ProjectionSour
+ "For source history use supporting_material_pointer plus /sources. For review detail append "
+ "/requirements//agent_review/note or /requirements//agent_review/evidence_refs instead. "
+ "Repeat --select to batch needed fields without replaying the outcome's requirements. "
- + "unread_context_index lists unconfirmed supporting fields in the current complete source. "
+ + "unread_context_index lists supporting fields not observed read in this epoch, or changed since that read. "
+ + "source_blocks conservatively includes partially read current sources; this index is not a full-read gate. "
+ "Use its source path and sha256 with quota context-read --select for each exact pointer. "
+ "A prior selected read, EOF or saved file does not confirm model-visible coverage or retention. "
+ "Detail reads never establish a full baseline. "
+ "Uncertain or missing necessary facts must be recovered before dependent action; Agent review is not independent acceptance."};
+ }
}
const remaining = tokens.filter(([path]) => !removed.some(start => pathStartsWith(path, start)));
// Unchanged source spellings cancel. Removed registered records contain only
@@ -204,7 +249,17 @@ export function prepareProgressiveContextDelivery(request: JsonObject, legacyFie
? [["context_details", "unread_context_index"]] : [];
const delivery = encodeContextDelivery(codec, legacyFields, sourceValues, navigation);
const {operation: _operation, source_edits: _edits, source_number_tokens: _numbers, ...source} = request;
- return contextProjectionChanges(source, {context: required.context, delivery, projected: required.projected}, sourceValues);
+ return contextProjectionChanges(source, {context: required.context, delivery, projected: required.projected,
+ read_sections: inlineReadSections(request, required.context)}, sourceValues);
+}
+
+/** Stateless presentation uses the same plan without inventing a native session,
+ * retained baseline or admission identity. Hosts may add delta independently. */
+export function prepareProgressiveContext(request: JsonObject): JsonObject {
+ const values: ProjectionSourceValues = new WeakMap();
+ const required = requiredNativeContext(request, values);
+ const {operation: _operation, source_edits: _edits, source_number_tokens: _numbers, ...source} = request;
+ return contextProjectionChanges(source, {context: required.context, projected: required.projected}, values);
}
export function initialContextReadPointers(context: JsonObject, decisionFields: readonly string[]): string[] {
diff --git a/loopx/control_plane/quota/turn_envelope.py b/loopx/control_plane/quota/turn_envelope.py
index 5011e7ce31..7b1111fede 100644
--- a/loopx/control_plane/quota/turn_envelope.py
+++ b/loopx/control_plane/quota/turn_envelope.py
@@ -56,7 +56,7 @@ def _turn_envelope_result(
"""Call the coarse TS owner and fail closed on transport shape drift."""
request = {"operation": operation, **params}
- if operation in {"context_delivery", "context_recovery"}:
+ if operation in {"context_delivery", "context_recovery", "progressive_context_delivery", "context_read_sections"}:
tokens = source_number_tokens(params)
if tokens:
request["source_number_tokens"] = tokens
@@ -180,6 +180,7 @@ def prepare_context_delivery(
retained: Mapping[str, Any] | None = None,
continuity: Mapping[str, Any] | None = None,
surface: str = "work_context", native_projection: Mapping[str, Any] | None = None,
+ consumed_pointers: Mapping[str, str] | None = None,
) -> dict[str, Any]:
"""Prepare under the Host's explicit continuity basis, not a model assertion.
@@ -196,10 +197,22 @@ def prepare_context_delivery(
continuity=dict(continuity) if continuity is not None else None)
if native_projection is not None:
source["native_projection"] = dict(native_projection)
+ if consumed_pointers is not None:
+ source["consumed_pointers"] = dict(consumed_pointers)
result = _turn_envelope_result("context_delivery", **source, source_edits=True)
return _apply_context_projection_changes(source, result)
+def prepare_progressive_context(context: Mapping[str, Any], *, source_reference: Mapping[str, Any],
+ surface: str = "quota_packet") -> dict[str, Any]:
+ """Stateless IO adapter to the same typed presentation owner; no Delta identity."""
+ from .cli_projection import _apply_context_projection_changes
+
+ source = dict(context=dict(context), native_projection=dict(source_reference), surface=surface)
+ return _apply_context_projection_changes(source,
+ _turn_envelope_result("progressive_context_delivery", **source, source_edits=True))
+
+
def update_native_context_lifecycle(state: Mapping[str, Any], event: Mapping[str, Any], *,
new_epoch: str, pages: list[dict[str, Any]],
pages_verified: bool = False,
diff --git a/loopx/control_plane/quota/turn_envelope.ts b/loopx/control_plane/quota/turn_envelope.ts
index b0c94fd52a..68b5ddadac 100644
--- a/loopx/control_plane/quota/turn_envelope.ts
+++ b/loopx/control_plane/quota/turn_envelope.ts
@@ -1,5 +1,5 @@
import {capturedContextSelection} from "./context_selection.ts";
-import {initialContextReadPointers, prepareProgressiveContextDelivery} from "./progressive_context.ts";
+import {contextReadSectionDigests, initialContextReadPointers, prepareProgressiveContext, prepareProgressiveContextDelivery} from "./progressive_context.ts";
import {contextProjectionChanges, projectQuotaDiagnostics} from "./diagnostic_projection.ts";
import type { LoopXTurnRouteValue } from "../turn_driver/turn_contract_generated.ts";
import { EffectiveAction, type QuotaEffectiveActionValue } from "./effective_action.generated.ts";
@@ -1492,6 +1492,12 @@ export function evaluateTurnEnvelope(value: unknown): JsonObject {
return contextProjectionChanges(source, payload);
}
if (operation === "build") return buildTurnEnvelope(request);
+ if (operation === "context_read_sections") {
+ const selected = capturedContextSelection({...request, list_fields: false});
+ return {sections: contextReadSectionDigests(request,
+ (selected.selections as JsonObject[]).map(row => String(row.pointer)))};
+ }
+ if (operation === "progressive_context_delivery") return prepareProgressiveContext(request);
if (operation === "context_delivery") return request.native_projection === undefined
? prepareContextDelivery(request, LEGACY_QUOTA_CONTEXT_FIELDS)
: prepareProgressiveContextDelivery(request, LEGACY_QUOTA_CONTEXT_FIELDS);
diff --git a/loopx/control_plane/turn_driver/codex_context.py b/loopx/control_plane/turn_driver/codex_context.py
index c6a0f848e2..04fc70de84 100644
--- a/loopx/control_plane/turn_driver/codex_context.py
+++ b/loopx/control_plane/turn_driver/codex_context.py
@@ -29,7 +29,8 @@
# Native adapter activation reuses scheduler-owned host declarations. These
# settings are presentation opt-ins, never host authentication or authority.
-CONTEXT_DELIVERY_SETTINGS = ("off", "on")
+CONTEXT_DELIVERY_SETTINGS = ("off", "on", "auto")
+DELTA_DELIVERY_SETTINGS = ("off", "auto")
CONTEXT_DELIVERY_SCENARIOS = ("codex_benchmark_heartbeat", "codex_app_heartbeat", "codex_app_ssh_goal")
CONTEXT_LIFECYCLE_HOOKS = ("SessionStart", "PreCompact", "PostCompact", "PostToolUse", "Interrupt")
@@ -46,29 +47,33 @@ def context_delivery_for_arguments(args: Any, *, codex_machine_preference: bool
"trae_app" if getattr(args, "trae_app", False) else None,
"antigravity_app" if getattr(args, "antigravity_app", False) else None) if value is not None]
setting = getattr(args, "context_delivery", None)
- setting = "off" if setting is None else setting
+ setting = ("off" if os.environ.get("LOOPX_CONTEXT_DELIVERY") == "off" else "auto") if setting is None else setting
+ delta = getattr(args, "delta_delivery", None) or "auto"
if len(profiles) > 1:
- return context_delivery_activation(setting)
+ return context_delivery_activation(setting, delta_delivery=delta)
return context_delivery_activation(setting, runtime_profile=profiles[0] if profiles else None,
scheduler_execution_context=fields if any(fields.values()) else None,
benchmark_mode=os.environ.get("LOOPX_EXECUTION_MODE")
if os.environ.get("LOOPX_CONTEXT_DELIVERY") == "on" else None,
- codex_machine_preference=codex_machine_preference)
+ codex_machine_preference=codex_machine_preference, delta_delivery=delta)
def context_delivery_activation(setting: str, *, runtime_profile: str | None = None,
scheduler_execution_context: dict[str, Any] | None = None,
benchmark_mode: str | None = None,
- codex_machine_preference: bool = False) -> dict[str, Any]:
+ codex_machine_preference: bool = False,
+ delta_delivery: str = "auto") -> dict[str, Any]:
from ..scheduler.execution_context import (
ExecutionMode, HostSurface, SchedulerOwner, resolve_scheduler_execution_context,
scheduler_execution_context_for_runtime_profile,
)
if setting not in CONTEXT_DELIVERY_SETTINGS:
- raise ValueError("context-delivery must be off or on")
+ raise ValueError("context-delivery must be off, on or auto")
+ if delta_delivery not in DELTA_DELIVERY_SETTINGS:
+ raise ValueError("delta-delivery must be off or auto")
scenario = None
- if setting == "on":
+ if setting != "off" and delta_delivery != "off":
# Conflicting declarations cannot activate transport. The scheduler
# owner still validates execution; this adapter does not repair it.
if runtime_profile is not None and scheduler_execution_context is not None:
@@ -88,21 +93,21 @@ def context_delivery_activation(setting: str, *, runtime_profile: str | None = N
HostSurface.CLAUDE_CODE, HostSurface.KUNLUNCODE, HostSurface.KIRO_CLI,
HostSurface.LOCAL_SCHEDULER,
}:
- return context_delivery_activation("off")
- if (context.host_surface is HostSurface.CODEX_APP
+ context = None
+ if (context is not None and context.host_surface is HostSurface.CODEX_APP
and context.scheduler_owner is SchedulerOwner.HOST_AUTOMATION
and context.execution_mode is ExecutionMode.HOSTED_AUTOMATION):
scenario = "codex_app_heartbeat"
- elif (context.host_surface is HostSurface.CODEX_APP_SSH
+ elif (context is not None and context.host_surface is HostSurface.CODEX_APP_SSH
and context.scheduler_owner is SchedulerOwner.AGENT_CLI_LOOP
and context.execution_mode is ExecutionMode.INTERACTIVE):
scenario = "codex_app_ssh_goal"
- elif (context.host_surface is HostSurface.GENERIC_CLI
+ elif (context is not None and context.host_surface is HostSurface.GENERIC_CLI
and context.scheduler_owner is SchedulerOwner.AGENT_CLI_LOOP
and context.execution_mode is ExecutionMode.INTERACTIVE
and benchmark_mode == "heartbeat"):
scenario = "codex_benchmark_heartbeat"
- if scenario is None:
+ if scenario is None and setting == "on":
raise ValueError(
"--context-delivery on requires a supported declared run mode: "
"Codex App heartbeat (--codex-app or --runtime-profile codex_app_heartbeat), "
@@ -111,7 +116,8 @@ def context_delivery_activation(setting: str, *, runtime_profile: str | None = N
"declarations are rejected; use --context-delivery off for ordinary full delivery."
)
return {"requested": setting, "enabled": scenario is not None, "scenario": scenario,
- "reason": "supported_declared_run_mode" if scenario else "disabled",
+ "progressive_enabled": setting != "off", "delta_delivery": "auto" if scenario else "off",
+ "reason": "supported_declared_run_mode" if scenario else "progressive_only" if setting != "off" else "disabled",
"supported_scenarios": list(CONTEXT_DELIVERY_SCENARIOS)}
@@ -336,12 +342,14 @@ def codex_context_hook(directory: str | None, event: dict[str, Any]) -> dict[str
recovery = state.get("recovery")
if name == "PostToolUse":
pages = _verified_context_pages(state, pages)
- read_state = observe_native_read(state, event, pages)
+ read_state = observe_native_read(state, event,
+ [page for page in pages if "read_sections" not in page])
updated = update_native_context_lifecycle(read_state, event,
new_epoch=uuid.uuid4().hex, pages=pages, pages_verified=True,
resume_verified=name == "SessionStart" and native_resume_verified(state, event))
if name == "PostToolUse":
- checkpoint_native_read(read_state, updated, event, pages)
+ checkpoint_native_read(read_state, updated, event,
+ [page for page in pages if "read_sections" not in page])
if updated != state:
_save(root, updated)
saved = updated.get("recovery")
@@ -397,7 +405,7 @@ def _context_pages(value: object) -> list[dict[str, Any]]:
return pages
if not isinstance(value, dict):
return []
- if value.get("schema_version") == "context_capture_page_v1":
+ if value.get("schema_version") in ("context_capture_page_v1", "context_capture_selection_page_v1"):
return [value]
if isinstance(value.get("output"), str):
pages = _context_pages(value["output"])
@@ -424,8 +432,21 @@ def _verified_context_pages(state: dict[str, Any], pages: list[dict[str, Any]])
files: dict[str, bytes] = {}
result = []
for page in pages:
- if any(key in page for key in ("selection_sha256", "selected_pointers", "list_fields")):
- continue # A directory/detail read makes no full-delivery claim.
+ # These observations originate only below, after byte/source checks.
+ page = {key: value for key, value in page.items() if key not in ("read_sections", "source_sha256")}
+ source = state.get("source_recovery")
+ if (any(key in page for key in ("selection_sha256", "selected_pointers", "list_fields", "reference_file"))
+ or isinstance(source, dict) and page.get("sha256") == source.get("sha256")
+ and page.get("sha256") != (state.get("recovery") or {}).get("sha256")):
+ from .native_context_selection import verified_context_selection
+
+ try:
+ observed = verified_context_selection(state, page)
+ except (OSError, ValueError, KeyError, TypeError, RecursionError):
+ observed = None
+ if observed is not None:
+ result.append(observed)
+ continue # Never promote a selected read to full-delivery proof.
reference = next((value for value in references if value.get("sha256") == page.get("sha256")), None)
if reference is None or page.get("ok") is not True:
result.append(page) # the typed owner handles failures and unrelated reads
@@ -490,13 +511,15 @@ def register_native_context_view(directory: str | None, view: dict[str, Any]) ->
or state.get("session_id") != os.environ.get("CODEX_THREAD_ID")):
raise ValueError("native page view does not match the current pending capture")
pending.update(path=view["path"], sha256=view["sha256"], total_bytes=view["total_bytes"],
- ancestry=view.get("ancestry", 0))
+ ancestry=view.get("ancestry", 0),
+ read_sections=pending.get("full_read_sections", {}) if view.get("mode") == "full" else {})
_save(root, state)
def project_codex_context(payload: dict[str, Any], *, directory: str | None, capture_directory: Path,
goal_id: str, agent_id: str, surface: str, capture_id: str,
- continuity_generation: str | None = None) -> dict[str, Any]:
+ continuity_generation: str | None = None,
+ progressive_enabled: bool = False) -> dict[str, Any]:
"""Commit current recovery before optional projection or candidate updates.
Serialization prevents invalidation from moving the epoch during preparation.
@@ -508,7 +531,11 @@ def project_codex_context(payload: dict[str, Any], *, directory: str | None, cap
from ..effect_runtime import EffectRuntimeRemoteError, EffectRuntimeStartupError
if directory is None:
- return payload
+ if not progressive_enabled:
+ return payload
+ from .decision_capture import capture_progressive_context
+
+ return capture_progressive_context(payload, directory=capture_directory, surface=surface)[0]
try:
with _locked(directory) as root:
recovery_committed = False
@@ -529,9 +556,15 @@ def project_codex_context(payload: dict[str, Any], *, directory: str | None, cap
scope = dict(goal_id=goal_id, agent_id=agent_id, session_id=session, context_epoch=epoch)
if continuity_generation is not None:
scope["continuity_generation"] = continuity_generation
+ if state.get("read_scope") != scope:
+ for key in ("consumed_pointers", "confirmed_read_sections", "section_reads"):
+ state.pop(key, None)
+ state["read_scope"] = scope
request = _native_context_request(state, scope)
recovery = capture_context_projection(payload, directory=capture_directory,
read_guidance=CONTEXT_CAPTURE_PAGE_GUIDANCE)
+ state["source_recovery"] = {key: recovery[key] for key in ("path", "sha256")}
+ state.pop("section_reads", None) # partial reads of an older source are not current coverage
page_bytes, output_bytes = native_context_page_budget()
def publish_recovery(reference: dict[str, Any]) -> None:
@@ -554,10 +587,11 @@ def publish_recovery(reference: dict[str, Any]) -> None:
retained=request.get("retained"), continuity=request.get("continuity"),
native_projection={
"path": recovery["path"], "sha256": recovery["sha256"],
+ "source_path": recovery["path"],
"command_template": context_capture_read_command(Path(recovery["path"]), recovery["sha256"],
page_bytes=page_bytes, max_page_output_bytes=output_bytes)
+ " --select '/sources'",
- })
+ }, consumed_pointers=state.get("consumed_pointers"))
except (EffectRuntimeRemoteError, EffectRuntimeStartupError):
return payload
if transaction["projected"]:
@@ -571,7 +605,9 @@ def publish_recovery(reference: dict[str, Any]) -> None:
if result.get("schema_version") == "context_delivery_v1":
state["recovery"]["target"] = result["target"]
state["recovery"]["continuity_basis"] = "captured_file"
- state["pending"].update(target=result["target"], ancestry=result["ancestry"])
+ state["pending"].update(target=result["target"], ancestry=result["ancestry"],
+ full_read_sections=transaction["read_sections"],
+ read_sections=transaction["read_sections"] if result["mode"] == "full" else {})
_save(root, state)
return result
except (OSError, ValueError, KeyError, TypeError, RecursionError):
diff --git a/loopx/control_plane/turn_driver/decision_capture.py b/loopx/control_plane/turn_driver/decision_capture.py
index da18eea8d4..e56af0d5ea 100644
--- a/loopx/control_plane/turn_driver/decision_capture.py
+++ b/loopx/control_plane/turn_driver/decision_capture.py
@@ -370,6 +370,27 @@ def capture_context_projection(payload: dict[str, Any], *, directory: Path,
}
+def capture_progressive_context(payload: dict[str, Any], *, directory: Path,
+ surface: str = "quota_packet") -> tuple[dict[str, Any], dict[str, Any]]:
+ """Publish the complete current source before optional stateless presentation.
+
+ The typed owner applies the shrink guard. This neither creates a native
+ journal nor requires/adopts an execution Turn. All recovery is same-capture.
+ """
+ from ..quota.turn_envelope import prepare_progressive_context
+
+ source = capture_context_projection(payload, directory=directory)
+ transaction = prepare_progressive_context(payload, surface=surface, source_reference={
+ **{key: source[key] for key in ("path", "sha256")},
+ "source_path": source["path"],
+ "command_template": source["command"] + " --select ''",
+ })
+ if not transaction["projected"]:
+ return payload, source
+ required = transaction["context"]
+ return required, capture_context_projection(required, directory=directory, filename="required-context.json")
+
+
def project_captured_context(
payload: dict[str, Any], *, directory: Path | None, request: dict[str, Any] | None,
goal_id: str, agent_id: str, surface: str, capture_id: str,
diff --git a/loopx/control_plane/turn_driver/native_context_selection.py b/loopx/control_plane/turn_driver/native_context_selection.py
new file mode 100644
index 0000000000..bcdc8ab575
--- /dev/null
+++ b/loopx/control_plane/turn_driver/native_context_selection.py
@@ -0,0 +1,75 @@
+"""Verify selected tool-output bytes for the private native read journal.
+
+The existing reader/typed selector owns selection semantics. Paths supplied by
+tool output cannot introduce a source outside the journal's current captures.
+Successful observations are section reads, never full model-retention receipts.
+"""
+from __future__ import annotations
+
+from argparse import Namespace
+from pathlib import Path
+from typing import Any
+
+from .decision_capture import read_context_capture_file, read_context_read_reference
+
+
+def verified_context_selection(state: dict[str, Any], page: dict[str, Any]) -> dict[str, Any] | None:
+ from ...cli_commands.quota_capture import read_context_capture
+ from ..effect_runtime import MAX_REQUEST_BYTES
+ from ..quota.turn_envelope import _turn_envelope_result
+
+ current = state.get("source_recovery")
+ if not isinstance(current, dict) or page.get("ok") is not True:
+ return None
+ references = [entry for key in ("source_recovery", "recovery")
+ if isinstance(entry := state.get(key), dict)]
+ reference_file = page.get("reference_file")
+ selected = None
+ if isinstance(reference_file, str):
+ _, metadata = read_context_read_reference(reference_file)
+ selected = metadata.get("selection")
+ if not isinstance(selected, dict) or selected.get("list_fields") is not False:
+ return None
+ path, source_digest = metadata["path"], metadata["sha256"]
+ pointers, view_digest = selected.get("select"), selected.get("sha256")
+ else:
+ path = next((entry["path"] for entry in references if entry.get("sha256") == page.get("sha256")), None)
+ source_digest = page.get("sha256")
+ if path is None or page.get("list_fields"):
+ return None
+ pointers, view_digest = page.get("selected_pointers"), page.get("selection_sha256")
+ if pointers is None:
+ # A whole original-source read covers sections without pretending
+ # it was the separate native required-view delivery.
+ pointers, view_digest = [""], source_digest
+ physical = Path(path).expanduser().absolute()
+ physical = physical.parent.resolve(strict=True) / physical.name
+ trusted = next((entry for entry in references if entry.get("sha256") == source_digest
+ and Path(entry["path"]).parent.resolve(strict=True) / Path(entry["path"]).name == physical), None)
+ if trusted is None or not isinstance(pointers, list) or not pointers or not all(isinstance(p, str) for p in pointers):
+ return None
+ offset, total = page.get("offset"), page.get("total_bytes")
+ content = page.get("content")
+ if type(offset) is not int or offset < 0 or type(total) is not int or total <= 0 or not isinstance(content, str):
+ return None
+ actual = content.encode("utf-8")
+ if not actual or offset + len(actual) > total:
+ return None
+ expected = read_context_capture(Namespace(format="json", offset=offset,
+ page_bytes=max(256, len(actual)), max_page_output_bytes=MAX_REQUEST_BYTES,
+ reference_file=reference_file, capture_file=None if reference_file else str(physical),
+ capture_sha256=None if reference_file else source_digest,
+ select=None if reference_file or pointers == [""] and "selected_pointers" not in page else pointers,
+ selection_sha256=None if reference_file else page.get("selection_sha256")))
+ if (expected.get("ok") is not True or expected.get("total_bytes") != total
+ or expected.get("offset") != offset or not expected.get("content", "").encode().startswith(actual)):
+ return None
+ end = offset + len(actual)
+ if ((page.get("eof") is True and (end != total or page.get("next_offset") is not None))
+ or (page.get("eof") is False and (end >= total or page.get("next_offset") != end))
+ or type(page.get("eof")) is not bool):
+ return None
+ _, _, source = read_context_capture_file(str(physical), source_digest, private=True)
+ sections = _turn_envelope_result("context_read_sections", context=source, select=pointers)["sections"]
+ return {**page, "schema_version": "context_capture_page_v1", "sha256": view_digest,
+ "selected_pointers": pointers, "source_sha256": current["sha256"], "read_sections": sections}
diff --git a/scripts/codex_app_apply_rrule.py b/scripts/codex_app_apply_rrule.py
index 2305009256..615fc7676f 100644
--- a/scripts/codex_app_apply_rrule.py
+++ b/scripts/codex_app_apply_rrule.py
@@ -405,6 +405,7 @@ def _load_scheduler_hint(
check=False,
capture_output=True,
text=True,
+ env={**os.environ, "LOOPX_CONTEXT_DELIVERY": "off"},
)
if completed.returncode != 0:
raise SystemExit(
diff --git a/scripts/external_scheduler_worker.py b/scripts/external_scheduler_worker.py
index 9a7e3a125c..61feb64de3 100644
--- a/scripts/external_scheduler_worker.py
+++ b/scripts/external_scheduler_worker.py
@@ -207,6 +207,7 @@ def run_quota_should_run(
stdin=b"",
timeout_seconds=max(0.01, timeout_seconds),
output_limit_bytes=PROCESS_OUTPUT_LIMIT_BYTES,
+ env={**os.environ, "LOOPX_CONTEXT_DELIVERY": "off"},
)
if completed.failure_kind is not None:
raise RuntimeError(f"quota should-run failed: {completed.failure_kind}")
diff --git a/scripts/qualify-native-goal-release.py b/scripts/qualify-native-goal-release.py
index 8b80d58711..89e5854022 100644
--- a/scripts/qualify-native-goal-release.py
+++ b/scripts/qualify-native-goal-release.py
@@ -193,6 +193,7 @@ def cli(launcher: Path, *args: str) -> dict:
result = subprocess.run(
[str(launcher), "--format", "json", *args], cwd=launcher.parent.parent,
capture_output=True, text=True, timeout=120,
+ env={**os.environ, "LOOPX_CONTEXT_DELIVERY": "off"},
)
if result.returncode:
raise RuntimeError("fixture_cli_failed")
diff --git a/tests/control_plane/test_codex_context_lifecycle.py b/tests/control_plane/test_codex_context_lifecycle.py
index d7c855c7f6..a4c2814089 100644
--- a/tests/control_plane/test_codex_context_lifecycle.py
+++ b/tests/control_plane/test_codex_context_lifecycle.py
@@ -1043,8 +1043,8 @@ def test_activation_reuses_declared_host_mode_and_off_is_inert(tmp_path, monkeyp
return
assert code == 0 and result["ok"] is True
activation = result["context_delivery"]
- expected = expected if setting == "on" else None
- assert activation["requested"] == (setting or "off")
+ expected = expected if setting != "off" else None
+ assert activation["requested"] == (setting or "auto")
assert activation["enabled"] is (expected is not None) and activation["scenario"] == expected
assert activation["supported_scenarios"] == ["codex_benchmark_heartbeat", "codex_app_heartbeat", "codex_app_ssh_goal"]
if expected is None:
diff --git a/tests/control_plane/test_context_delivery_cli.py b/tests/control_plane/test_context_delivery_cli.py
index 316598e1ce..f783ad5e12 100644
--- a/tests/control_plane/test_context_delivery_cli.py
+++ b/tests/control_plane/test_context_delivery_cli.py
@@ -462,7 +462,8 @@ def release():
"retained": {"complete": True, "target": cold["target"]}}, setting="off")
assert "target" not in disabled and not (disabled_directory / "projection.json").exists()
ordinary, directory = invoke(None, opt_in=False)
- assert "target" not in ordinary and not (directory / "projection.json").exists()
+ assert "target" not in ordinary and ordinary["mode"] == "full"
+ assert (directory / "projection.json").exists(), "ordinary defaults present the current source without native continuity"
assert state.read_bytes() == before_source and _spend_run_count(runtime) == 0
assert all(path.read_bytes() == raw for path, raw in saved)
diff --git a/tests/control_plane/test_context_machine_configuration.py b/tests/control_plane/test_context_machine_configuration.py
index fb74c1d6f8..8e0dd969e5 100644
--- a/tests/control_plane/test_context_machine_configuration.py
+++ b/tests/control_plane/test_context_machine_configuration.py
@@ -76,7 +76,7 @@ def test_machine_catalog_discovers_context_delivery_without_activation(tmp_path)
assert len(contexts) == 1
assert contexts[0]["schema_versions"] == [CONTEXT_DELIVERY_MACHINE_SCHEMA]
assert contexts[0]["configuration_template"] == {
- "schema_version": CONTEXT_DELIVERY_MACHINE_SCHEMA, "mode": "on", "antigravity_mode": "on",
+ "schema_version": CONTEXT_DELIVERY_MACHINE_SCHEMA, "mode": "on", "delta_delivery": "auto", "antigravity_mode": "on",
}
assert not registry.exists() and not (runtime / "machine/configuration.json").exists()
assert not (runtime / "context-delivery").exists()
@@ -207,14 +207,16 @@ def cli(*args):
@pytest.mark.parametrize("host", [[], ["--runtime-profile", "codex_cli"],
["--codex-app", "--runtime-profile", "codex_app_heartbeat"],
["--host-surface", "codex_app"], ["--runtime-profile", "generic_cli"]])
-def test_inherited_on_rejects_unknown_or_unsupported_before_admission(tmp_path, monkeypatch, host):
+def test_inherited_progressive_does_not_invent_unknown_native_continuity(tmp_path, monkeypatch, host):
monkeypatch.delenv("LOOPX_CONTEXT_DELIVERY", raising=False)
monkeypatch.delenv("LOOPX_EXECUTION_MODE", raising=False)
registry, runtime = tmp_path / "absent.json", tmp_path / "runtime"
assert configure(registry, runtime, tmp_path, "on")[0] == 0
code, result = _run_cli(registry, runtime, "quota", "context-config", *host,
"--goal-id", "fixture", "--agent-id", "worker")
- assert code != 0 and not result["ok"], result
+ assert code == 0 and result["ok"], result
+ assert result["context_delivery"]["progressive_enabled"] is True
+ assert result["context_delivery"]["enabled"] is False and "native_config" not in result
assert not (runtime / "context-delivery").exists() and not registry.exists()
assert _spend_run_count(runtime) == 0
@@ -349,7 +351,7 @@ def test_bootstrap_reloads_machine_setting_and_preserves_explicit_off(tmp_path,
args = ["heartbeat-prompt", "--thin", "--codex-app", "--goal-id", GOAL_ID, "--agent-id", AGENT_ID]
assert configure(registry, runtime, tmp_path, "on")[0] == 0
code, enabled = _run_cli(registry, runtime, *args)
- assert code == 0 and "--context-delivery on" in enabled["task_body"], enabled
+ assert code == 0 and "--context-delivery auto" in enabled["task_body"], enabled
code, bootstrap = _run_cli(registry, runtime, *args, "--bootstrap")
assert code == 0, bootstrap
assert "--context-delivery" not in bootstrap["task_body"]
diff --git a/tests/control_plane/test_heartbeat_envelope_transport.py b/tests/control_plane/test_heartbeat_envelope_transport.py
index 3caf2b3788..6905ec9680 100644
--- a/tests/control_plane/test_heartbeat_envelope_transport.py
+++ b/tests/control_plane/test_heartbeat_envelope_transport.py
@@ -24,6 +24,19 @@
)
+def assert_explicit_off_keeps_legacy_prompt(original, disabled):
+ # Omitted low-level API values keep their old prompt. Explicit OFF must
+ # also fence the new CLI default when the generated guard actually runs.
+ assert "--context-delivery off" in disabled["quota_guard_command"]
+ assert {key: value.replace(" --context-delivery off", "") if isinstance(value, str) else value
+ for key, value in disabled.items() if key != "interface_budget"} == {
+ key: value for key, value in original.items() if key != "interface_budget"}
+ extra = len(" --context-delivery off")
+ assert disabled["interface_budget"]["char_count"] == original["interface_budget"]["char_count"] + extra
+ assert disabled["interface_budget"]["budget_char_count"] == original["interface_budget"]["budget_char_count"] + extra
+ assert disabled["interface_budget"]["max_chars"] == original["interface_budget"]["max_chars"]
+
+
def test_shared_native_root_keeps_dynamic_turn_binding_and_bootstrap_options(tmp_path):
from loopx.cli import build_parser
from loopx.control_plane.heartbeat.bootstrap_prompt import goal_bootstrap, host_bootstrap_binding
@@ -250,6 +263,9 @@ def test_real_worker_generated_guard_selection_reentry_and_settle_once(
# same worker declarations carried by the native tool environment.
monkeypatch.setenv('LOOPX_CONTEXT_DELIVERY', 'on')
monkeypatch.setenv('LOOPX_EXECUTION_MODE', 'heartbeat')
+ else:
+ env['LOOPX_CONTEXT_DELIVERY'] = 'off'
+ monkeypatch.setenv('LOOPX_CONTEXT_DELIVERY', 'off')
body = heartbeat_body(env, TURN_ID, native_goal=False, decision_handoff_socket=private_handoff)
# Execute the renderer's actual guard, preserving its route and flags.
block = body.split('```sh\n', 1)[1].split('```', 1)[0]
@@ -395,7 +411,7 @@ def test_native_context_prompt_rejects_unqualified_on_and_keeps_off_inert(tmp_pa
monkeypatch.delenv("LOOPX_CONTEXT_DELIVERY", raising=False)
args = dict(goal_id=GOAL_ID, agent_id=AGENT_ID, runtime_profile=profile,
thin=True)
- assert build_heartbeat_prompt(**args) == build_heartbeat_prompt(**args, context_delivery="off")
+ assert_explicit_off_keeps_legacy_prompt(build_heartbeat_prompt(**args), build_heartbeat_prompt(**args, context_delivery="off"))
with pytest.raises(ValueError, match="supported declared run mode"):
build_heartbeat_prompt(**args, context_delivery="on", codex_context_dir=str(tmp_path / "absent"))
assert list(tmp_path.iterdir()) == []
@@ -433,7 +449,7 @@ def test_native_context_prompt_keeps_capture_on_reentry(tmp_path, monkeypatch):
def test_ssh_goal_capture_keeps_native_begin_turn_and_off_boundary(tmp_path, turn_envelope):
args = dict(goal_id=GOAL_ID, agent_id=AGENT_ID, runtime_profile="codex_app_ssh_goal", thin=True)
original = build_heartbeat_prompt(**args)
- assert original == build_heartbeat_prompt(**args, context_delivery="off")
+ assert_explicit_off_keeps_legacy_prompt(original, build_heartbeat_prompt(**args, context_delivery="off"))
assert "--decision-output-root" not in original["quota_guard_command"]
with pytest.raises(ValueError, match="host-owned"):
build_heartbeat_prompt(**args, decision_output_root=tmp_path)
@@ -471,7 +487,7 @@ def test_ssh_goal_capture_fits_host_with_full_command_paths(tmp_path, turn_envel
args = dict(goal_id=GOAL_ID, agent_id=AGENT_ID, runtime_profile="codex_app_ssh_goal",
thin=True, **paths)
ordinary = build_heartbeat_prompt(**args)
- assert ordinary == build_heartbeat_prompt(**args, context_delivery="off")
+ assert_explicit_off_keeps_legacy_prompt(ordinary, build_heartbeat_prompt(**args, context_delivery="off"))
enabled = build_heartbeat_prompt(**args, context_delivery="on", decision_output_root=captures,
codex_context_root=str(context), turn_envelope=turn_envelope)
body, command = enabled["task_body"], shlex.split(enabled["quota_guard_command"])
diff --git a/tests/control_plane/test_progressive_context_entrypoints.py b/tests/control_plane/test_progressive_context_entrypoints.py
new file mode 100644
index 0000000000..37d1aed49f
--- /dev/null
+++ b/tests/control_plane/test_progressive_context_entrypoints.py
@@ -0,0 +1,196 @@
+"""Current requirements stay usable independently of native Delta continuity."""
+from argparse import Namespace
+from copy import deepcopy
+import json
+from pathlib import Path
+
+import pytest
+
+from loopx.cli_commands.quota_capture import read_context_capture
+from loopx.control_plane.turn_driver import codex_context as native
+from loopx.control_plane.turn_driver.decision_capture import read_context_read_reference, write_context_read_reference
+from test_codex_context_lifecycle import setup, project, deliver, read_pages
+from test_goal_acceptance_cli import acceptance_goal as acceptance_goal
+from test_progressive_native_context import payload, outcome
+
+
+def required_document(packet):
+ _, reference = read_context_read_reference(packet["recovery"]["reference_file"])
+ return json.loads(Path(reference["path"]).read_bytes())
+
+
+def selected_pages(reference, pointer, *, page_bytes=1024):
+ reference_file = write_context_read_reference(Path(reference["path"]), reference["sha256"])
+ request = Namespace(format="json", reference_file=str(reference_file), select=[pointer],
+ offset=0, page_bytes=page_bytes, max_page_output_bytes=6000)
+ pages = []
+ while True:
+ page = read_context_capture(request)
+ assert page["ok"], page
+ pages.append(page)
+ if page["eof"]:
+ return pages
+ request.reference_file = page["reference_file"]
+ request.select = None
+ request.offset = page["next_offset"]
+
+
+@pytest.mark.parametrize("profile", [None, "generic_cli", "trae_app", "antigravity_app", "codex_app_heartbeat"])
+def test_progressive_activation_does_not_require_native_continuity(profile):
+ result = native.context_delivery_activation("auto", runtime_profile=profile, delta_delivery="off")
+ assert result["progressive_enabled"] is True
+ assert result["enabled"] is False
+ assert result["scenario"] is None
+ if profile in (None, "generic_cli", "trae_app", "antigravity_app"):
+ assert native.context_delivery_activation("auto", runtime_profile=profile)["enabled"] is False
+ else:
+ assert native.context_delivery_activation("auto", runtime_profile=profile)["enabled"] is True
+ assert native.context_delivery_activation("off", runtime_profile=profile)["progressive_enabled"] is False
+
+
+@pytest.mark.parametrize("host", [(), ("--runtime-profile", "generic_cli"), ("--trae_app",), ("--antigravity_app",)])
+def test_generic_read_only_cli_defaults_progressive_without_admitting_a_turn(acceptance_goal, host):
+ workspace, document, cli, run = acceptance_goal
+ for i in range(8):
+ document.write_text(json.dumps({"outcome_id": "export", "owner_agent_id": "agent-a",
+ "todo_ids": ["todo_export"], "objective": "Deliver the export.",
+ "requirements": [{"id": "tail", "description": "Stop before publication."}],
+ "source": {"ref": f"source:{i}", "summary": ("Prior supporting observation. " * 16).strip()}}))
+ code, result = cli("refine", "--agent-id", "agent-a", "--document", str(document),
+ "--expected-provider-revision", cli("inspect")[1]["provider_revision"],
+ "--operation-id", f"observation-{i}", "--execute")
+ assert code == 0, result
+ before = cli("inspect")[1]
+ args = ("quota", "should-run", "--goal-id", "goal-acceptance", "--agent-id", "agent-a", *host)
+ code, packet = run(*args)
+ assert code == 0, packet
+ required = required_document(packet)
+ assert "heartbeat_receipt" not in required, "plain observation must not invent a work Turn"
+ assert "target" not in packet, "stateless presentation must not invent native continuity"
+ assert "context_details" in required
+ details = required["context_details"]
+ assert details["source_path"] == details["path"]
+ source = json.loads(Path(details["source_path"]).read_bytes())
+ assert "Stop before publication." in json.dumps(required)
+ assert "Prior supporting observation" not in json.dumps(required)
+ assert "Prior supporting observation" in json.dumps(source)
+ code, off = run(*args, "--context-delivery", "off")
+ assert code == 0 and "context_details" not in off and "reference_file" not in off
+ assert "Prior supporting observation" in json.dumps(off)
+ assert cli("inspect")[1] == before, "presentation must not mutate acceptance or its provider revision"
+
+
+def test_observed_selected_reads_survive_delta_but_not_change_or_compaction(tmp_path, monkeypatch):
+ event = setup(tmp_path, monkeypatch)
+ original = payload()
+ _, first = project(tmp_path, payload=original)
+ supporting = outcome(first["context"])["supporting_material_pointer"] + "/sources"
+ pages = selected_pages(first["context"]["context_details"], supporting)
+ assert len(pages) > 1
+ deliver(tmp_path, event, pages[1:])
+ assert supporting not in native._state(tmp_path).get("consumed_pointers", {}), "EOF alone is not full selection coverage"
+ deliver(tmp_path, event, pages[:1])
+ state = native._state(tmp_path)
+ assert supporting in state["consumed_pointers"]
+ assert supporting in state["confirmed_read_sections"]
+ assert "candidate" not in state, "selection coverage is not native full-input retention"
+ _, warm = project(tmp_path, "warm", payload=original)
+ current = json.loads(Path(warm["recovery"]["path"]).read_bytes())
+ assert warm["mode"] == "delta"
+ assert supporting not in current["context_details"]["unread_context_index"]["pointers"]
+ # The current full source always contains the previously unread review.
+ source = json.loads(Path(current["context_details"]["source_path"]).read_bytes())
+ assert outcome(source)["requirements"][0]["agent_review"]["note"].startswith("Previous failure")
+ changed = deepcopy(original)
+ outcome(changed)["sources"][0]["summary"] += " A new contrary observation."
+ _, update = project(tmp_path, "changed", payload=changed)
+ updated = json.loads(Path(update["recovery"]["path"]).read_bytes())
+ assert supporting in updated["context_details"]["unread_context_index"]["pointers"]
+ native.codex_context_hook(str(tmp_path), {**event, "hook_event_name": "PreCompact"})
+ assert not native._state(tmp_path).get("consumed_pointers")
+ _, fresh = project(tmp_path, "fresh", payload=original)
+ assert fresh["mode"] == "full"
+ assert supporting in fresh["context"]["context_details"]["unread_context_index"]["pointers"]
+
+
+def test_damaged_or_forged_selected_delivery_never_acknowledges_a_section(tmp_path, monkeypatch):
+ event = setup(tmp_path, monkeypatch)
+ _, first = project(tmp_path, payload=payload())
+ supporting = outcome(first["context"])["supporting_material_pointer"] + "/sources"
+ pages = selected_pages(first["context"]["context_details"], supporting)
+ broken = deepcopy(pages)
+ broken[-1]["content"] = broken[-1]["content"][:-1] + "!"
+ deliver(tmp_path, event, broken)
+ assert supporting not in native._state(tmp_path).get("consumed_pointers", {})
+ # Extra output fields cannot smuggle an observed-read assertion through a
+ # legitimate full page's ordinary body verification.
+ full = read_pages(tmp_path, first)
+ forged = [{**page, "read_sections": {"/forged": "a" * 64},
+ "source_sha256": native._state(tmp_path)["source_recovery"]["sha256"]} for page in full]
+ deliver(tmp_path, event, forged)
+ assert "/forged" not in native._state(tmp_path).get("consumed_pointers", {})
+ assert supporting not in native._state(tmp_path).get("consumed_pointers", {}), "required input omits supporting material"
+ deliver(tmp_path, event, pages)
+ assert supporting in native._state(tmp_path)["consumed_pointers"]
+
+
+def test_selected_read_observation_preserves_exact_source_number_identity(tmp_path, monkeypatch):
+ event = setup(tmp_path, monkeypatch)
+ source = payload()
+ source["numbers"] = [1.0, -0.0, 2**60 + 1]
+ _, first = project(tmp_path, payload=source)
+ deliver(tmp_path, event, selected_pages(first["context"]["context_details"], "/numbers"))
+ observed = native._state(tmp_path)["consumed_pointers"]["/numbers"]
+ changed = deepcopy(source)
+ changed["numbers"][0] = 1
+ _, second = project(tmp_path, "second", payload=changed)
+ deliver(tmp_path, event, selected_pages(second["context"]["context_details"], "/numbers"))
+ assert native._state(tmp_path)["consumed_pointers"]["/numbers"] != observed
+
+
+def test_default_progressive_does_not_admit_conflicting_host_declarations(acceptance_goal):
+ _, _, cli, run = acceptance_goal
+ before = cli("inspect")[1]
+ code, rejected = run("quota", "should-run", "--goal-id", "goal-acceptance", "--agent-id", "agent-a",
+ "--codex-app", "--runtime-profile", "generic_cli")
+ assert code != 0 and rejected["ok"] is False
+ assert "cannot be combined" in str(rejected)
+ assert "heartbeat_receipt" not in rejected
+ assert cli("inspect")[1] == before
+
+
+def test_saved_context_progressive_recovery_keeps_original_turn_without_native_setup(tmp_path, monkeypatch):
+ from loopx.cli import build_parser
+ from loopx.cli_commands.quota_capture import handle_native_context_command
+ from loopx.control_plane.turn_driver.decision_capture import write_decision_capture
+ import hashlib
+
+ monkeypatch.delenv("CODEX_THREAD_ID", raising=False)
+ original = {**payload(), "agent_identity": {"agent_id": "agent"},
+ "heartbeat_receipt": {"turn_instance_id": "original-work"}}
+ path = tmp_path / "captured.json"
+ write_decision_capture(path, original)
+ saved = path.read_bytes()
+ args = build_parser().parse_args(["--format", "json", "quota", "context-project",
+ "--goal-id", "fixture", "--agent-id", "agent", "--turn-instance-id", "original-work",
+ "--capture-file", str(path), "--capture-sha256", hashlib.sha256(saved).hexdigest(),
+ "--context-delivery", "auto", "--delta-delivery", "off"])
+ result = []
+ code = handle_native_context_command(args, print_payload=lambda value, *_: result.append(value))
+ assert code == 0
+ current = required_document(result[0])
+ assert current["heartbeat_receipt"] == original["heartbeat_receipt"]
+ assert "sources" not in outcome(current)
+ assert path.read_bytes() == saved and not list(tmp_path.rglob("session.json"))
+
+
+def test_heartbeat_keeps_layer_choices_in_the_generated_guard():
+ from loopx.control_plane.heartbeat.builder import build_heartbeat_prompt
+
+ for mode, delta in [("auto", "off"), ("off", "auto")]:
+ prompt = build_heartbeat_prompt(goal_id="fixture", agent_id="agent", active_state=Path("state.md"),
+ thin=True, context_delivery=mode, delta_delivery=delta)
+ guard = prompt["quota_guard_command"]
+ assert f"--context-delivery {mode}" in guard
+ if delta == "off":
+ assert "--delta-delivery off" in guard
diff --git a/tests/control_plane/test_progressive_native_context.py b/tests/control_plane/test_progressive_native_context.py
index 0d702d8323..7eaaf16620 100644
--- a/tests/control_plane/test_progressive_native_context.py
+++ b/tests/control_plane/test_progressive_native_context.py
@@ -266,7 +266,10 @@ def test_saved_cli_references_keep_tail_constraints_and_recover_without_detail_r
context.codex_context_hook(str(tmp_path), {**event, "source": "compact"})
code, view = _run_cli(registry, runtime, *command, cwd=tmp_path)
assert code == 0 and view["ok"], view
- assert view["mode"] == ("delta" if cycle == 1 else "full")
+ # The real adapter compares complete reader framing, including this
+ # checkout's argv/path lengths. A warm view may legitimately prefer full;
+ # it must not fake a delta when that would cost more than the same capture.
+ assert view["mode"] in ({"delta", "full"} if cycle == 1 else {"full"})
argv = shlex.split(view["recovery"]["command"])
pages, contents = [], b""
while True:
diff --git a/tests/test_codex_app_apply_rrule.py b/tests/test_codex_app_apply_rrule.py
index 70246340f9..8e96ac160d 100644
--- a/tests/test_codex_app_apply_rrule.py
+++ b/tests/test_codex_app_apply_rrule.py
@@ -1,9 +1,11 @@
from __future__ import annotations
import json
+import os
import re
import shlex
import sqlite3
+import sys
import tomllib
from pathlib import Path
@@ -11,6 +13,7 @@
from loopx.cli import build_parser
from scripts.codex_app_apply_rrule import (
+ _load_scheduler_hint,
_now_ms,
_parse_args,
_scheduler_hint_turn_instance_id,
@@ -21,6 +24,24 @@
)
+def test_scheduler_subprocess_reads_raw_hint_with_presentation_enabled(tmp_path, monkeypatch):
+ monkeypatch.setenv("LOOPX_CONTEXT_DELIVERY", "on")
+ executable = tmp_path / "quota-probe"
+ executable.write_text(
+ f"#!{sys.executable}\n"
+ "import json, os\n"
+ "print(json.dumps({'scheduler_hint': {'codex_app': {'apply_needed': True, "
+ "'stateful_backoff': {'interval': 20}}}} "
+ "if os.environ.get('LOOPX_CONTEXT_DELIVERY') == 'off' "
+ "else {'reference_file': 'model-reader.json'}))\n"
+ )
+ executable.chmod(0o700)
+ hint, stateful = _load_scheduler_hint(loopx=str(executable), registry=tmp_path / "registry.json",
+ goal_id="fixture", agent_id="agent", parent_turn_instance_id="fixture-turn", capabilities=[])
+ assert hint["apply_needed"] is True and stateful == {"interval": 20}
+ assert os.environ["LOOPX_CONTEXT_DELIVERY"] == "on"
+
+
def _write_toml(path: Path) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(
diff --git a/tests/test_external_scheduler_worker.py b/tests/test_external_scheduler_worker.py
index 9d3e82d559..78e65ab0af 100644
--- a/tests/test_external_scheduler_worker.py
+++ b/tests/test_external_scheduler_worker.py
@@ -22,6 +22,19 @@
import external_scheduler_worker as worker # noqa: E402
+def test_quota_subprocess_keeps_machine_json_with_presentation_enabled(monkeypatch):
+ monkeypatch.setenv("LOOPX_CONTEXT_DELIVERY", "on")
+ probe = (
+ "import json, os; "
+ "print(json.dumps({'should_run': False, 'scheduler_hint': {'interval': 20}} "
+ "if os.environ.get('LOOPX_CONTEXT_DELIVERY') == 'off' "
+ "else {'reference_file': 'model-reader.json'}))"
+ )
+ payload = worker.run_quota_should_run([sys.executable, "-c", probe], timeout_seconds=10)
+ assert payload == {"should_run": False, "scheduler_hint": {"interval": 20}}
+ assert os.environ["LOOPX_CONTEXT_DELIVERY"] == "on"
+
+
def test_default_registry_follows_single_runtime_route(
tmp_path: Path,
monkeypatch: pytest.MonkeyPatch,
From e73fc092383b9ddfbc8e6361d75e44de1c58ea68 Mon Sep 17 00:00:00 2001
From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Date: Wed, 4 Nov 2026 23:14:48 +0800
Subject: [PATCH 2/6] docs(context): describe independent presentation and
delta recovery
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
---
docs/reference/required-work-context.md | 127 +++++++++++++++---------
1 file changed, 81 insertions(+), 46 deletions(-)
diff --git a/docs/reference/required-work-context.md b/docs/reference/required-work-context.md
index c587374c35..d78c4210b3 100644
--- a/docs/reference/required-work-context.md
+++ b/docs/reference/required-work-context.md
@@ -574,30 +574,34 @@ the existing Turn or its recovery files.
### Machine default
-**Settings → This machine → Capabilities → Differential context** exposes independent
-application rows for **Codex** (`mode`) and **Antigravity** (`antigravity_mode`), using the
-existing revision-locked preview, apply and readback operations in one switch action.
-Switching off uses the same transaction. A saved preference does not certify native
-host setup or actual delta use; the settings view states this explicitly. Its
-`context_delivery` machine namespace accepts
-`{"schema_version":"context_delivery_machine_defaults_v0","mode":"off","antigravity_mode":"on"}`
-(or `"off"`/`"on"` for either field; omitting `antigravity_mode` defaults it to `"on"` while
-preserving the saved `mode`). The CLI exposes that same owner through
-`machine-config preview/apply --namespace context_delivery --config-json FILE`;
-apply requires the exact preview revision. Removing the namespace restores the on defaults for supported native Codex sessions and trusted-owner Antigravity manager history reads; save `mode: "off"` or `antigravity_mode: "off"` to keep either application disabled independently.
-Sibling settings and Goal records are preserved. The Codex row (`mode`) remains scoped to Codex,
-while `antigravity_mode` controls progressive private-capture reads of `recent_delivery_history`
-in trusted-owner Antigravity manager turns (`off` or `LOOPX_CONTEXT_DELIVERY=off` keeps full inline input),
-with no additional global switch or host configuration authority. Read-only editors cannot
-save it. Each application row leaves the other host unchanged and does not initialize the current native session.
-
-An explicit `--context-delivery on|off` wins; otherwise each invocation reads the
-machine preference, preserving a saved off. An absent preference defaults on only
-for supported POSIX native Codex App/SSH and declared benchmark heartbeat callers.
-Ordinary CLI, other hosts and unsupported platforms keep full delivery. Explicit
-on, or an explicitly saved on for an unknown declaration, still rejects unsupported
-or conflicting modes. The worker environment's `LOOPX_CONTEXT_DELIVERY=off` also
-overrides inheritance; environment on alone supplies no host or execution proof.
+**Settings → This machine → Capabilities → Progressive context** exposes progressive
+reads (`mode`), independent cross-Turn reuse (`delta_delivery`) and the existing
+Antigravity manager-history setting (`antigravity_mode`). It uses the same
+revision-locked preview, apply, readback, disable and rollback owner. Read-only
+editors cannot save; sibling settings and Goal records remain unchanged. No choice
+installs hooks, trusts a host or proves actual delivery or model retention.
+
+The existing `context_delivery_machine_defaults_v0` namespace accepts
+`{"schema_version":"context_delivery_machine_defaults_v0","mode":"on","delta_delivery":"auto","antigravity_mode":"on"}`.
+`mode` and `antigravity_mode` keep their `on|off` values; omitted `delta_delivery`
+defaults to `auto` and also accepts `off`. Old saved rows remain readable.
+`machine-config preview/apply --namespace context_delivery --config-json FILE`
+requires the original preview revision. Removing the namespace restores progressive
+reads, supported-host Delta AUTO and Antigravity manager history reads. Save the
+relevant off setting to keep it disabled. `antigravity_mode` still independently
+controls private reads of `recent_delivery_history` in trusted-owner manager turns;
+it does not grant host configuration or execution authority.
+
+The CLI facade `--context-delivery auto` (also the omitted default) presents
+current requirements before expandable material across hosts. Stateless CLI,
+other declared hosts and recovery do not need native setup. A plain read-only
+`should-run` stays read-only: capture files do not create a Turn, receipt, session,
+journal or execution lease. `--delta-delivery off` independently disables Delta
+while retaining progressive reads. Delta AUTO only uses supported declared
+continuity hosts. Explicit `--context-delivery off`, a saved off or an inherited
+`LOOPX_CONTEXT_DELIVERY=off` keeps the original complete inline path. Environment
+on alone supplies no host, retention or execution proof. Private capture failure
+retains the complete current input rather than using an older capture.
New benchmark heartbeat trials default to `context_delivery=on`; pass `off` to
disable. Other benchmark modes remain off. Workers pin the resolved trial choice
in preflight and solver subprocesses; existing saved/frozen trials must not be
@@ -619,7 +623,8 @@ must explicitly request raw output on internal `quota should-run` calls using
and retain the exact registry, Goal, Agent and Turn. Enabled native output is a
presentation/capture envelope, not a raw authority decision; a missing
`should_run` in that envelope is not a denial. MCP settlement and Claude status
-readers use the existing `LOOPX_CONTEXT_DELIVERY=off` subprocess override, which
+readers, external scheduler workers and scheduler-hint readers use the existing
+`LOOPX_CONTEXT_DELIVERY=off` subprocess override, which
also preserves compatibility with older CLI parsers. This does not change the
machine preference or disable differential context for the interactive Agent.
@@ -627,16 +632,15 @@ machine preference or disable differential context for the interactive Agent.
调用中通过 `--context-delivery off` 或子进程 `LOOPX_CONTEXT_DELIVERY=off`
显式请求原始输出,并保留原 registry、Goal、Agent 和 Turn。
开启差分后的原生输出是展示/快照封装;封装没有 `should_run` 不表示准入拒绝。
-MCP 结算和 Claude 状态读取在子进程内设置已有的 `LOOPX_CONTEXT_DELIVERY=off`,
+MCP 结算、Claude 状态读取、外部调度 worker 和调度提示读取在子进程内设置已有的 `LOOPX_CONTEXT_DELIVERY=off`,
兼容旧版 CLI 解析器;不修改机器开关,也不关闭交互
Agent 的差分上下文。
-On accepts the declared native scenarios: Codex App heartbeat (`--codex-app` or its equivalent complete scheduler
+Legacy explicit on with Delta AUTO accepts the declared native scenarios: Codex App heartbeat (`--codex-app` or its equivalent complete scheduler
declaration), Codex App SSH Goal (`--runtime-profile codex_app_ssh_goal`), and the existing Codex benchmark heartbeat worker (`generic_cli`
plus its explicit heartbeat worker environment). Missing, contradictory or
-unsupported Codex declarations return an error before admission. This machine
-preference is scoped to Codex: other explicitly resolved hosts keep full delivery.
-An explicit `--context-delivery on` on those hosts still errors. Declarations select
+unsupported Codex declarations still return an error before admission. Other hosts
+use the auto facade for stateless progressive reads. Declarations select
an adapter; they do not authenticate a host or prove retained input.
Native continuity currently requires POSIX; other platforms reject on explicitly.
@@ -663,6 +667,23 @@ ceiling); if metadata cannot fit, recovery retains the current capture. Reader
pages remain independently bounded. A complete raw tool log is not proof that
the Host retained the same bytes in model history.
+Each progressive `context_details.source_path` names this Turn's complete immutable
+`projection.json`, including when a warm wire omits unchanged material. The current
+`unread_context_index` preserves unobserved or changed supporting pointers and
+conservative partially read source blocks. It is navigation, not a full-read gate;
+select the facts required for the current decision from that current source.
+
+The private native journal records `consumed_pointers` and `confirmed_read_sections`
+only after byte-verified, contiguous complete delivery of a selected view, or the
+complete native input's actually included sections. Digests remain in the journal;
+they are not repeated in model-facing index rows. A list, partial page, EOF without
+earlier coverage, failed/damaged output, subagent hook or unrelated capture cannot
+acknowledge a section. Selected reads never establish a full retained-input baseline.
+Changed content remains unread; compaction or a different Goal/Agent/scope retires
+the old epoch's observations. Stateless hosts make no such observation claim and
+keep the complete current source available. These observations do not establish
+model comprehension, later retention, execution authority or billed-token savings.
+
After the shared TypeScript codec accepts a delta, the native output adapter
compares its final reference plus a complete explicit-file read against the
same current full capture. The comparison includes compact JSON framing,
@@ -938,29 +959,43 @@ quota 能力候选沿用同一精确 codec 复用已登记 Todo 的正文、标
### 机器级默认
-在**设置 → 本机设置 → 能力中心 → 差分上下文**分别提供 **Codex**(`mode`)与 **Antigravity**
-(`antigravity_mode`)两行独立开关,沿用现有精确修订预览、应用和读回,由一次开关操作完成;关闭也使用同一事务。
-设置页明确区分已保存偏好与尚未验证的原生初始化、实际差分使用。机器 namespace 为 `context_delivery`,配置为
-`{"schema_version":"context_delivery_machine_defaults_v0","mode":"off","antigravity_mode":"on"}`
-(两个字段各自支持 `"off"` 或 `"on"`;省略 `antigravity_mode` 时默认 `"on"` 并保留所选 `mode`)。CLI 的 `machine-config preview/apply --namespace context_delivery
---config-json FILE` 使用同一 owner;应用须带原预览修订。移除此 namespace 恢复受支持 Codex 原生会话与强能力 Antigravity 管家历史渐进读取的默认开启;保持关闭须分别保存 `mode: "off"` 或 `antigravity_mode: "off"`,
-不改写其他配置和 Goal 记录。`mode` 仍表示 Codex 偏好,`antigravity_mode` 控制强能力 Antigravity 管家是否将 `recent_delivery_history` 移至私有快照渐进读取(`off` 或 `LOOPX_CONTEXT_DELIVERY=off` 保持完整内联),
-不新增总开关或宿主配置 authority。只读编辑器不能保存;两行应用开关互不影响,也不会初始化当前原生会话。
-
-显式 `--context-delivery on|off` 优先;省略时每次读取机器设置,已保存的关闭继续生效。
-未配置时,仅在受支持的 POSIX Codex App/SSH 和已声明的 benchmark 心跳入口默认开启;
-普通 CLI、其他宿主和不支持的平台仍完整交付。显式开启或已保存开启遇到未知/冲突声明
-仍拒绝。worker 环境的 `LOOPX_CONTEXT_DELIVERY=off` 也覆盖继承,环境 on 本身不证明宿主或执行权限。
+在**设置 → 本机设置 → 能力中心 → 渐进上下文**分别设置渐进读取(`mode`)、独立的跨轮差分
+(`delta_delivery`)及原有 Antigravity 管家历史读取(`antigravity_mode`),沿用现有精确修订的预览、
+应用、读回、关闭和回滚 owner。只读编辑器不能保存;不改写其他配置和 Goal,不安装/信任 hook,
+保存偏好不证明原生初始化、实际投递或模型保留。
+
+既有 `context_delivery_machine_defaults_v0` namespace 接受
+`{"schema_version":"context_delivery_machine_defaults_v0","mode":"on","delta_delivery":"auto","antigravity_mode":"on"}`。
+`mode` 与 `antigravity_mode` 保留 `on|off`;可选的 `delta_delivery` 默认为 `auto`,也可为 `off`;旧配置继续可读。
+CLI 的 `machine-config preview/apply --namespace context_delivery --config-json FILE` 仍需原预览修订。
+移除 namespace 恢复渐进读取、支持宿主的 Delta AUTO 与 Antigravity 管家历史读取;要保持关闭应保存对应 off。
+`antigravity_mode` 继续独立控制强能力管家的 `recent_delivery_history` 私有快照读取,不新增宿主配置或执行权限。
+
+CLI 的 `--context-delivery auto`(省略时也使用此门面)跨宿主先呈现当前要求,再按需展开材料。
+普通 CLI、其他已声明宿主及恢复读取不要求原生初始化;只读 `should-run` 仍不创建 Turn、回执、会话、journal 或执行 lease。
+`--delta-delivery off` 可独立关闭跨轮差分而保留渐进读取;Delta AUTO 只使用支持连续性的已声明宿主。
+显式 `--context-delivery off`、已保存的关闭及继承的 `LOOPX_CONTEXT_DELIVERY=off` 保留原完整内联路径。
+环境 on 不证明宿主、保留或执行权限。私有捕获失败时保留本次完整输入,不借用旧捕获。
新 benchmark heartbeat trial 默认 `context_delivery=on`,指定 `off` 可关闭;其他跑法仍关闭。
worker 把本次运行已解析的选择固定传给预检和 solver 子进程,不改写调用方原设置,
不修改或复用旧的在途/冻结 trial 来宣称新默认合格。
-开启接受以下原生声明:Codex App 心跳(`--codex-app` 或等价完整调度声明)、
+兼容的显式 on 与 Delta AUTO 接受以下原生声明:Codex App 心跳(`--codex-app` 或等价完整调度声明)、
Codex App SSH Goal(`--runtime-profile codex_app_ssh_goal`),以及现有 Codex benchmark 心跳 worker(`generic_cli` 与其显式心跳环境)。缺失、冲突、
-不支持的 Codex 声明在准入前报错。机器偏好仅作用于 Codex;其他已明确解析的宿主
-继续完整投递,对这些宿主显式指定 `--context-delivery on` 仍报错。声明只选择 adapter,
+不支持的 Codex 声明仍在准入前报错;其他宿主通过 auto 门面使用无状态渐进读取。声明只选择 adapter,
不证明宿主身份或上下文保留。
当前原生连续性依赖 POSIX;其他平台显式拒绝开启。
+每轮 `context_details.source_path` 都指向当轮完整且不可变的 `projection.json`,暖差分也可通过
+该文件选读未变化但此前未读的内容。`unread_context_index` 保留尚未观测到完整读取或已经变化的
+支持材料指针,以及保守标记的部分未读来源块;它是导航,不是要求读完整包的 gate。
+仅在当前决策依赖相关事实前选读必要部分。
+
+私有原生 journal 的 `consumed_pointers` 与 `confirmed_read_sections` 只记录经过字节核对、
+连续完整交付的选读视图,或完整原生输入中实际包含的部分;摘要留在 journal,不反复展示给模型。
+目录、部分页、仅 EOF、失败/篡改输出、子 Agent hook、无关捕获都不构成读取确认;选读不建立全量
+模型保留基线。内容变化继续标为未读;压缩、Goal/Agent/scope 变化使旧 epoch 观测失效。
+无状态宿主不声称观测确认,完整当前来源始终可达;这些记录不证明理解、后续保留、执行权限或计费下降。
+
受支持的 Codex 声明尚未完成原生连续性初始化时(包括尚未提供会话 id),
guard 仍通过文件 reader 交付本次完整捕获,
可以从同一当前来源渐进选读;不会制造替代会话、journal、epoch 或已保留基线。
From 2b8aff353a55fa2fb9ea7ee5edc60cbae11e86e4 Mon Sep 17 00:00:00 2001
From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Date: Wed, 4 Nov 2026 23:27:17 +0800
Subject: [PATCH 3/6] fix(context): share verified selection bytes with the
native journal
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
---
loopx/cli_commands/quota.py | 88 ++++++-----------
loopx/cli_commands/quota_capture.py | 96 ++++++++-----------
loopx/control_plane/heartbeat/builder.py | 38 +++++---
.../quota/progressive_context.ts | 4 +-
.../turn_driver/decision_capture.py | 58 +++++++++++
.../turn_driver/native_context_selection.py | 23 ++---
.../progressive_context.test.ts | 10 +-
7 files changed, 177 insertions(+), 140 deletions(-)
diff --git a/loopx/cli_commands/quota.py b/loopx/cli_commands/quota.py
index e3ed262702..bce2192865 100644
--- a/loopx/cli_commands/quota.py
+++ b/loopx/cli_commands/quota.py
@@ -14,8 +14,8 @@
)
from .quota_capture import (
bind_capture_selection_transport, budgeted_settlement_result, capture_decision, handoff_decision,
- handle_native_context_command, handle_replan_view, prepare_quota_capture, native_context_capture_view,
- native_context_activation, model_context_reference, progressive_context_capture_view,
+ handle_native_context_command, handle_replan_view, prepare_quota_capture,
+ native_context_activation, progressive_context_or_current, project_native_quota_context,
)
from ..control_plane.turn_driver.decision_capture import (
project_captured_context,
@@ -23,7 +23,6 @@
from ..usage_goal import observe_quota_result
from ..control_plane.coordination.local_authority import CanonicalAuthorityRequired
-from ..control_plane.effect_runtime import EffectRuntimeRemoteError, EffectRuntimeStartupError
from ..control_plane.quota.effect_program import SettlementIdentity
from ..control_plane.quota.error_codes import (
CloseoutQueryUnavailableError,
@@ -309,6 +308,27 @@ def _attach_turn_start_hook_dispatch(
key: value for key, value in dispatch.items() if key != "contexts"
}
+def _emit_bounded_settlement(payload, args, *, runtime_root, reader_argv, print_payload):
+ """Preserve the committed receipt even when bounded result delivery fails."""
+ try:
+ view = budgeted_settlement_result(payload, runtime_root=runtime_root,
+ output_bytes=args.max_page_output_bytes, reader_argv=reader_argv)
+ except QuotaDecisionTransportError as exc:
+ # Transport failure cannot replace an already evaluated refusal or
+ # committed receipt. Preserve unknown controls as well as identity;
+ # only the bulky diagnostic snapshots are omitted on this fallback.
+ view = {key: value for key, value in payload.items() if key not in ("before", "after")}
+ view["result_delivery_error"] = {"error_code": exc.error_code, "reason": str(exc),
+ "recommended_action": "Preserve the original result controls and Turn identity. "
+ "Repair capture privacy or remove --max-page-output-bytes and read back the "
+ "same operation; do not repeat admission or assume it did not commit.",
+ "omitted_diagnostics": [key for key in ("before", "after") if key in payload]}
+ print_payload(view, args.format, _quota_renderer(args, failure=True))
+ return 1
+ print_payload(view, args.format, _quota_renderer(args, failure=payload.get("ok") is not True))
+ return 0 if payload.get("ok") is True else 1
+
+
def _emit_quota_result(
payload: dict[str, object],
args: argparse.Namespace,
@@ -343,23 +363,8 @@ def _emit_quota_result(
)
if (args.quota_command == "spend-slot" and args.format == "json" and context is not None
and getattr(args, "max_page_output_bytes", None) is not None):
- try:
- view = budgeted_settlement_result(payload, runtime_root=context.runtime_root,
- output_bytes=args.max_page_output_bytes, reader_argv=reader_argv)
- except QuotaDecisionTransportError as exc:
- # Transport failure cannot replace an already evaluated refusal or
- # committed receipt. Preserve unknown controls as well as identity;
- # only the bulky diagnostic snapshots are omitted on this fallback.
- view = {key: value for key, value in payload.items() if key not in ("before", "after")}
- view["result_delivery_error"] = {"error_code": exc.error_code, "reason": str(exc),
- "recommended_action": "Preserve the original result controls and Turn identity. "
- "Repair capture privacy or remove --max-page-output-bytes and read back the "
- "same operation; do not repeat admission or assume it did not commit.",
- "omitted_diagnostics": [key for key in ("before", "after") if key in payload]}
- print_payload(view, args.format, _quota_renderer(args, failure=True))
- return 1
- print_payload(view, args.format, _quota_renderer(args, failure=payload.get("ok") is not True))
- return 0 if payload.get("ok") is True else 1
+ return _emit_bounded_settlement(payload, args, runtime_root=context.runtime_root,
+ reader_argv=reader_argv, print_payload=print_payload)
try:
activation = native_context_activation(args)
context_delivery_enabled = activation["enabled"]
@@ -431,46 +436,15 @@ def _emit_quota_result(
surface="turn_envelope" if getattr(args, "turn_envelope", False) else "quota_packet")
if (not deferred_context and args.format == "json" and succeeded and args.quota_command == "should-run"
and activation["progressive_enabled"] and not native_context and delivery_request is None):
- try:
- payload = progressive_context_capture_view(payload, args,
- runtime_root=context.runtime_root if context is not None else Path(args._progressive_context_runtime),
- directory=capture_directory,
- surface="turn_envelope" if getattr(args, "turn_envelope", False) else "quota_packet",
- reader_argv=reader_argv)
- except (QuotaDecisionTransportError, OSError, ValueError, EffectRuntimeRemoteError, EffectRuntimeStartupError):
- # Stateless optional presentation has no stale native selector.
- # Retain this complete decided input/receipt when capture fails.
- pass
+ payload = progressive_context_or_current(payload, args,
+ runtime_root=context.runtime_root if context is not None else Path(args._progressive_context_runtime),
+ directory=capture_directory, reader_argv=reader_argv)
if (not deferred_context and args.format == "json" and succeeded and capture_directory
and native_context):
- import hashlib
- from ..control_plane.turn_driver.codex_context import (
- NativeContextSessionUnavailable, codex_context_directory, project_codex_context,
- )
-
try:
- capture_id = hashlib.sha256((capture_directory / "decision.json").read_bytes()).hexdigest()
- try:
- directory = codex_context_directory(directory=args.codex_context_dir,
- root=getattr(args, "codex_context_root", None), create=True)
- except NativeContextSessionUnavailable:
- # A declared host may not have initialized its native session.
- # Deliver this complete capture without a session journal or
- # baseline claim; do not repeat the already-committed guard.
- directory = None
- payload = project_codex_context(payload, directory=directory,
- capture_directory=capture_directory, goal_id=decision_identity[0], agent_id=decision_identity[1],
- surface="turn_envelope" if getattr(args, "turn_envelope", False) else "quota_packet",
- capture_id=capture_id, continuity_generation=getattr(args, "_context_delivery_generation", None),
- progressive_enabled=activation["progressive_enabled"])
- recovery = payload.get("recovery")
- # Without a prepared native projection, the view adapter publishes
- # this complete CLI view and its reader commands as current recovery.
- # The original authority decision remains separately captured.
- payload = native_context_capture_view(payload, capture_directory, context_directory=directory,
- metadata={"capture_sha256": capture_id, **({"recovery": recovery} if recovery is not None else {})},
- max_page_output_bytes=getattr(args, "max_page_output_bytes", None), reader_argv=reader_argv)
- payload = model_context_reference(payload, reader_argv=reader_argv)
+ payload = project_native_quota_context(payload, args, capture_directory=capture_directory,
+ decision_identity=decision_identity, progressive_enabled=activation["progressive_enabled"],
+ reader_argv=reader_argv)
except (QuotaDecisionTransportError, OSError, ValueError) as exc:
if not isinstance(exc, QuotaDecisionTransportError):
exc = QuotaDecisionTransportError(
diff --git a/loopx/cli_commands/quota_capture.py b/loopx/cli_commands/quota_capture.py
index b23e25868b..bae17d1987 100644
--- a/loopx/cli_commands/quota_capture.py
+++ b/loopx/cli_commands/quota_capture.py
@@ -17,6 +17,9 @@
from ..control_plane.effect_runtime import EffectRuntimeRejected, EffectRuntimeRemoteError, EffectRuntimeStartupError
from ..control_plane.quota.error_codes import QuotaCommandValidationError, QuotaDecisionTransportError
from ..control_plane.turn_driver.decision_capture import (
+ context_index_fields as _context_index_fields,
+ context_selection_transport as _context_selection_transport,
+ context_selection_bytes as _context_selection_bytes,
validate_handoff_socket, CONTEXT_CAPTURE_READ_GUIDANCE, CONTEXT_CAPTURE_PAGE_GUIDANCE, context_capture_read_command,
CONTEXT_CAPTURE_NAVIGATION_GUIDANCE,
read_context_capture_file as _read_capture,
@@ -123,62 +126,10 @@ def fits(result: dict[str, Any]) -> bool:
return best
-def _context_index_fields(payload: dict[str, Any], children: list[dict[str, Any]]) -> list[dict[str, Any]]:
- """Serialize metadata for TS-verified addresses, preserving Python JSON values."""
- fields = []
- for child in children:
- value: Any = payload
- for key in child["path"]:
- value = value[key]
- field = {"pointer": child["pointer"], "type":
- "object" if isinstance(value, dict) else "array" if isinstance(value, list)
- else "null" if value is None else "boolean" if isinstance(value, bool)
- else "string" if isinstance(value, str) else "number",
- "bytes": len(json.dumps(value, ensure_ascii=False, separators=(",", ":")).encode("utf-8"))}
- if isinstance(value, (dict, list)):
- field["count"] = len(value)
- fields.append(field)
- return fields
-
-
-def _context_selection_transport(payload: dict[str, Any]) -> dict[str, Any]:
- """Keep address structure without retransmitting unused scalar prose.
-
- The TS owner validates pointers; selected values still come from the fully
- digest-checked original. Initial navigation and discovery need real scalar
- values and do not use this adapter. JSON null takes four bytes, so replacing
- only strings longer than two characters cannot increase request bytes.
- Iteration preserves the original JSON reader's supported nesting depth.
- """
- result: dict[str, Any] = {}
- pending: list[tuple[Any, Any]] = [(payload, result)]
- while pending:
- source, target = pending.pop()
- for key, value in source.items() if isinstance(source, dict) else enumerate(source):
- if isinstance(value, (dict, list)):
- child: Any = {} if isinstance(value, dict) else [None] * len(value)
- target[key] = child
- pending.append((value, child))
- else:
- target[key] = None if isinstance(value, str) and len(value) > 2 else value
- return result
-def _context_selection_bytes(payload: dict[str, Any], selections: list[dict[str, Any]],
- *, list_fields: bool, list_depth: int | None) -> bytes:
- """Render TS-verified addresses from original, digest-checked JSON values."""
- views: list[dict[str, Any]] = []
- for item in selections:
- selected: Any = payload
- for key in item["path"]:
- selected = selected[key]
- if list_fields:
- views.append({"pointer": item["pointer"], "fields": _context_index_fields(payload, item["children"])})
- else:
- views.append({"pointer": item["pointer"], "value": selected})
- view_options = {"list_depth": list_depth} if list_depth is not None and list_depth != 1 else {}
- return json.dumps({"schema_version": "context_capture_index_v1" if list_fields else "context_capture_selection_v1",
- "selections": views, **view_options}, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode("utf-8") + b"\n"
+
+
def read_context_capture(args: argparse.Namespace, *, presentation: dict[str, Any] | None = None,
@@ -609,6 +560,43 @@ def view(kind: str, ref: dict[str, Any], body: bytes) -> dict[str, Any]:
return result
+def project_native_quota_context(payload: dict[str, Any], args: argparse.Namespace, *,
+ capture_directory: Path, decision_identity: tuple[str, str],
+ progressive_enabled: bool, reader_argv: list[str] | None) -> dict[str, Any]:
+ """Prepare one already-decided native view; callers retain receipt failures."""
+ from ..control_plane.turn_driver.codex_context import (
+ NativeContextSessionUnavailable, codex_context_directory, project_codex_context,
+ )
+ capture_id = hashlib.sha256((capture_directory / "decision.json").read_bytes()).hexdigest()
+ try:
+ directory = codex_context_directory(directory=args.codex_context_dir,
+ root=getattr(args, "codex_context_root", None), create=True)
+ except NativeContextSessionUnavailable:
+ directory = None # Current full input, no fabricated native journal.
+ payload = project_codex_context(payload, directory=directory,
+ capture_directory=capture_directory, goal_id=decision_identity[0], agent_id=decision_identity[1],
+ surface="turn_envelope" if getattr(args, "turn_envelope", False) else "quota_packet",
+ capture_id=capture_id, continuity_generation=getattr(args, "_context_delivery_generation", None),
+ progressive_enabled=progressive_enabled)
+ recovery = payload.get("recovery")
+ view = native_context_capture_view(payload, capture_directory, context_directory=directory,
+ metadata={"capture_sha256": capture_id, **({"recovery": recovery} if recovery is not None else {})},
+ max_page_output_bytes=getattr(args, "max_page_output_bytes", None), reader_argv=reader_argv)
+ return model_context_reference(view, reader_argv=reader_argv)
+
+
+def progressive_context_or_current(payload: dict[str, Any], args: argparse.Namespace, *,
+ runtime_root: Path, directory: Path | None,
+ reader_argv: list[str] | None) -> dict[str, Any]:
+ """Optional stateless IO falls back to this complete decided input/receipt."""
+ try:
+ return progressive_context_capture_view(payload, args, runtime_root=runtime_root,
+ directory=directory, surface="turn_envelope" if getattr(args, "turn_envelope", False) else "quota_packet",
+ reader_argv=reader_argv)
+ except (QuotaDecisionTransportError, OSError, ValueError, EffectRuntimeRemoteError, EffectRuntimeStartupError):
+ return payload
+
+
def progressive_context_capture_view(payload: dict[str, Any], args: argparse.Namespace, *,
runtime_root: Path, directory: Path | None,
surface: str = "quota_packet",
diff --git a/loopx/control_plane/heartbeat/builder.py b/loopx/control_plane/heartbeat/builder.py
index aebd7a4360..5c0a03fb5a 100644
--- a/loopx/control_plane/heartbeat/builder.py
+++ b/loopx/control_plane/heartbeat/builder.py
@@ -303,6 +303,26 @@ def _heartbeat_prompt_commands(
return commands
+def _heartbeat_context_capture_activation(*, context_delivery: str | None, delta_delivery: str,
+ runtime_profile: str | None, scheduler_execution_context: Any, decision_output_root: Path | None,
+ decision_handoff_socket: str | None, codex_context_dir: str | None,
+ codex_context_root: str | None) -> tuple[dict[str, Any], str, str | None, str | None]:
+ from ..turn_driver.codex_context import context_delivery_activation
+ import os
+
+ activation = context_delivery_activation(context_delivery or "off", runtime_profile=runtime_profile,
+ scheduler_execution_context=scheduler_execution_context, delta_delivery=delta_delivery,
+ benchmark_mode=os.environ.get("LOOPX_EXECUTION_MODE")
+ if os.environ.get("LOOPX_CONTEXT_DELIVERY") == "on" else None)
+ if not activation["enabled"]:
+ codex_context_dir = codex_context_root = None
+ effective = "on" if activation["enabled"] else "off"
+ if context_delivery != "on" and not any((decision_output_root, decision_handoff_socket,
+ codex_context_dir, codex_context_root)):
+ effective = "off" # Rendering a prompt does not start native transport.
+ return activation, effective, codex_context_dir, codex_context_root
+
+
def build_heartbeat_prompt(
*,
goal_id: str,
@@ -393,21 +413,11 @@ def build_heartbeat_prompt(
runtime_profile=runtime_profile,
scheduler_execution_context=scheduler_execution_context,
)
- from ..turn_driver.codex_context import context_delivery_activation
-
- import os
-
- activation = context_delivery_activation(context_delivery or "off", runtime_profile=runtime_profile,
+ activation, effective_context_delivery, codex_context_dir, codex_context_root = _heartbeat_context_capture_activation(
+ context_delivery=context_delivery, delta_delivery=delta_delivery, runtime_profile=runtime_profile,
scheduler_execution_context=scheduler_execution_context,
- delta_delivery=delta_delivery,
- benchmark_mode=os.environ.get("LOOPX_EXECUTION_MODE")
- if os.environ.get("LOOPX_CONTEXT_DELIVERY") == "on" else None)
- if not activation["enabled"]:
- codex_context_dir = codex_context_root = None
- effective_context_delivery = "on" if activation["enabled"] else "off"
- if context_delivery != "on" and not any((decision_output_root, decision_handoff_socket,
- codex_context_dir, codex_context_root)):
- effective_context_delivery = "off" # prompt rendering is not native capture activation
+ decision_output_root=decision_output_root, decision_handoff_socket=decision_handoff_socket,
+ codex_context_dir=codex_context_dir, codex_context_root=codex_context_root)
decision_output_root = resolve_heartbeat_capture_root(
decision_output_root,
thin=thin, full=full, compact=compact, brief=brief,
diff --git a/loopx/control_plane/quota/progressive_context.ts b/loopx/control_plane/quota/progressive_context.ts
index 62b715eac9..46ea700718 100644
--- a/loopx/control_plane/quota/progressive_context.ts
+++ b/loopx/control_plane/quota/progressive_context.ts
@@ -388,7 +388,9 @@ export function initialContextReadPointers(context: JsonObject, decisionFields:
// Keep its original source, unknown coverage and read-before-work obligation
// inline; the complete pointer list remains at this same captured address.
// Unknown/future layouts stay whole rather than hiding a new obligation.
- if (unread && Object.keys(unread).length === 4 && unread.coverage_confirmed === false
+ if (unread && Object.keys(unread).every(key => ["source", "coverage_confirmed", "read_before_dependent_work", "pointers", "source_blocks"].includes(key))
+ && (unread.source_blocks === undefined || Array.isArray(unread.source_blocks)
+ && unread.source_blocks.every(pointer => typeof pointer === "string")) && unread.coverage_confirmed === false
&& unread.read_before_dependent_work === true && Array.isArray(unread.pointers)
&& unread.pointers.every(pointer => typeof pointer === "string")
&& typeof source?.path === "string" && typeof source.sha256 === "string"
diff --git a/loopx/control_plane/turn_driver/decision_capture.py b/loopx/control_plane/turn_driver/decision_capture.py
index e56af0d5ea..42ab5779d1 100644
--- a/loopx/control_plane/turn_driver/decision_capture.py
+++ b/loopx/control_plane/turn_driver/decision_capture.py
@@ -442,3 +442,61 @@ def project_captured_context(
# The original full payload is already available. An unavailable optional
# codec/capture must not convert safe full delivery into an execution gate.
return payload
+
+
+def context_index_fields(payload: dict[str, Any], children: list[dict[str, Any]]) -> list[dict[str, Any]]:
+ """Serialize metadata for TS-verified addresses, preserving Python JSON values."""
+ fields = []
+ for child in children:
+ value: Any = payload
+ for key in child["path"]:
+ value = value[key]
+ field = {"pointer": child["pointer"], "type":
+ "object" if isinstance(value, dict) else "array" if isinstance(value, list)
+ else "null" if value is None else "boolean" if isinstance(value, bool)
+ else "string" if isinstance(value, str) else "number",
+ "bytes": len(json.dumps(value, ensure_ascii=False, separators=(",", ":")).encode("utf-8"))}
+ if isinstance(value, (dict, list)):
+ field["count"] = len(value)
+ fields.append(field)
+ return fields
+
+
+def context_selection_transport(payload: dict[str, Any]) -> dict[str, Any]:
+ """Keep address structure without retransmitting unused scalar prose.
+
+ The TS owner validates pointers; selected values still come from the fully
+ digest-checked original. Initial navigation and discovery need real scalar
+ values and do not use this adapter. JSON null takes four bytes, so replacing
+ only strings longer than two characters cannot increase request bytes.
+ Iteration preserves the original JSON reader's supported nesting depth.
+ """
+ result: dict[str, Any] = {}
+ pending: list[tuple[Any, Any]] = [(payload, result)]
+ while pending:
+ source, target = pending.pop()
+ for key, value in source.items() if isinstance(source, dict) else enumerate(source):
+ if isinstance(value, (dict, list)):
+ child: Any = {} if isinstance(value, dict) else [None] * len(value)
+ target[key] = child
+ pending.append((value, child))
+ else:
+ target[key] = None if isinstance(value, str) and len(value) > 2 else value
+ return result
+
+
+def context_selection_bytes(payload: dict[str, Any], selections: list[dict[str, Any]],
+ *, list_fields: bool, list_depth: int | None) -> bytes:
+ """Render TS-verified addresses from original, digest-checked JSON values."""
+ views: list[dict[str, Any]] = []
+ for item in selections:
+ selected: Any = payload
+ for key in item["path"]:
+ selected = selected[key]
+ if list_fields:
+ views.append({"pointer": item["pointer"], "fields": context_index_fields(payload, item["children"])})
+ else:
+ views.append({"pointer": item["pointer"], "value": selected})
+ view_options = {"list_depth": list_depth} if list_depth is not None and list_depth != 1 else {}
+ return json.dumps({"schema_version": "context_capture_index_v1" if list_fields else "context_capture_selection_v1",
+ "selections": views, **view_options}, ensure_ascii=False, sort_keys=True, separators=(",", ":")).encode("utf-8") + b"\n"
diff --git a/loopx/control_plane/turn_driver/native_context_selection.py b/loopx/control_plane/turn_driver/native_context_selection.py
index bcdc8ab575..1ae4ed84e0 100644
--- a/loopx/control_plane/turn_driver/native_context_selection.py
+++ b/loopx/control_plane/turn_driver/native_context_selection.py
@@ -6,16 +6,15 @@
"""
from __future__ import annotations
-from argparse import Namespace
+import hashlib
from pathlib import Path
from typing import Any
-from .decision_capture import read_context_capture_file, read_context_read_reference
+from .decision_capture import (read_context_capture_file, read_context_read_reference,
+ context_selection_transport, context_selection_bytes)
def verified_context_selection(state: dict[str, Any], page: dict[str, Any]) -> dict[str, Any] | None:
- from ...cli_commands.quota_capture import read_context_capture
- from ..effect_runtime import MAX_REQUEST_BYTES
from ..quota.turn_envelope import _turn_envelope_result
current = state.get("source_recovery")
@@ -55,21 +54,19 @@ def verified_context_selection(state: dict[str, Any], page: dict[str, Any]) -> d
actual = content.encode("utf-8")
if not actual or offset + len(actual) > total:
return None
- expected = read_context_capture(Namespace(format="json", offset=offset,
- page_bytes=max(256, len(actual)), max_page_output_bytes=MAX_REQUEST_BYTES,
- reference_file=reference_file, capture_file=None if reference_file else str(physical),
- capture_sha256=None if reference_file else source_digest,
- select=None if reference_file or pointers == [""] and "selected_pointers" not in page else pointers,
- selection_sha256=None if reference_file else page.get("selection_sha256")))
- if (expected.get("ok") is not True or expected.get("total_bytes") != total
- or expected.get("offset") != offset or not expected.get("content", "").encode().startswith(actual)):
+ _, raw, source = read_context_capture_file(str(physical), source_digest, private=True)
+ if selected is not None or "selected_pointers" in page:
+ selection = _turn_envelope_result("context_select", context=context_selection_transport(source),
+ select=pointers, list_fields=False)
+ raw = context_selection_bytes(source, selection["selections"], list_fields=False,
+ list_depth=selected.get("list_depth") if selected else None)
+ if hashlib.sha256(raw).hexdigest() != view_digest or len(raw) != total or raw[offset:offset + len(actual)] != actual:
return None
end = offset + len(actual)
if ((page.get("eof") is True and (end != total or page.get("next_offset") is not None))
or (page.get("eof") is False and (end >= total or page.get("next_offset") != end))
or type(page.get("eof")) is not bool):
return None
- _, _, source = read_context_capture_file(str(physical), source_digest, private=True)
sections = _turn_envelope_result("context_read_sections", context=source, select=pointers)["sections"]
return {**page, "schema_version": "context_capture_page_v1", "sha256": view_digest,
"selected_pointers": pointers, "source_sha256": current["sha256"], "read_sections": sections}
diff --git a/tests/control_plane_ts/progressive_context.test.ts b/tests/control_plane_ts/progressive_context.test.ts
index de2e6807e3..6f8162fb13 100644
--- a/tests/control_plane_ts/progressive_context.test.ts
+++ b/tests/control_plane_ts/progressive_context.test.ts
@@ -17,7 +17,7 @@ test("initial navigation keeps unknown supporting-index obligations whole", () =
const base = "/context_details/unread_context_index";
for (const index of [{...known, future_obligation: "Preserve the newly required stop."},
{...known, coverage_confirmed: true}, {...known, read_before_dependent_work: false},
- {...known, pointers: [42]}, {...known, source: null}]) {
+ {...known, pointers: [42]}, {...known, source: null}, {...known, source_blocks: [42]}]) {
const context = {interaction_contract: {schema_version: "loopx_interaction_contract_v0"},
context_details: {instruction: "Read applicable supporting evidence before dependent work.", unread_context_index: index}};
const before = structuredClone(context);
@@ -27,6 +27,14 @@ test("initial navigation keeps unknown supporting-index obligations whole", () =
assert.ok(initialContextReadPointers({interaction_contract: {schema_version: "loopx_interaction_contract_v0"},
context_details: {unread_context_index: known}}, []).includes(base));
assert.deepEqual(initialContextReadPointers({interaction_contract: {schema_version: "loopx_interaction_contract_v0"}}, []), []);
+ for (const index of [known, {...known, source_blocks: ["/supporting/source/content"]}]) {
+ const pointers = initialContextReadPointers({interaction_contract: {schema_version: "loopx_interaction_contract_v0"},
+ context_details: {instruction: "Read applicable evidence before dependent work.", unread_context_index: index}}, []);
+ assert.ok(pointers.includes(`${base}/source`));
+ assert.ok(pointers.includes(`${base}/read_before_dependent_work`));
+ assert.ok(pointers.includes("/context_details/instruction"));
+ assert.ok(!pointers.includes(base), "address inventories remain reachable without crowding out current obligations");
+ }
});
test("only supporting materials move; cumulative obligations and merged source guidance survive", () => {
From b2355622ea66c6a918d4e56b85b20d3c4766d40c Mon Sep 17 00:00:00 2001
From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Date: Wed, 4 Nov 2026 23:37:30 +0800
Subject: [PATCH 4/6] fix(workspace): select manager history transport
automatically
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
---
.../capability-localization.ts | 4 ----
.../machine-configuration-settings.tsx | 24 ++++---------------
.../rfcs/manager-runtime-profile-v0.md | 6 ++---
.../rfcs/manager-runtime-profile-v0.zh-CN.md | 4 ++--
docs/reference/required-work-context.md | 15 +++++-------
.../configuration-backup.mjs | 10 ++++----
loopx/capabilities/configuration_ui.py | 3 ---
.../machine_configuration/context_delivery.py | 8 ++-----
.../test_context_machine_configuration.py | 2 +-
tests/test_manager_native_context.py | 11 ++++-----
10 files changed, 28 insertions(+), 59 deletions(-)
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts b/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts
index e7145d34c3..3ceeed9f20 100644
--- a/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts
+++ b/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts
@@ -254,10 +254,6 @@ export function localizedCapabilityFieldCopy(locale: WorkspaceLocale, capability
label: "跨轮差分", description: "仅在支持连续性的宿主自动启用;可独立关闭,保留渐进读取。", options: {off: "关闭", auto: "自动"},
} : {
label: "Cross-Turn Delta", description: "Automatic only on supported continuity hosts; off preserves progressive reads.", options: {off: "Off", auto: "Automatic"},
- }, antigravity_mode: locale === "zh-CN" ? {
- label: "Antigravity", description: "仅作用于强能力 Antigravity 管家的交付历史渐进读取;关闭时保持完整内联。", options: {off: "关闭", on: "开启"},
- } : {
- label: "Antigravity", description: "Applies only to progressive history reads in trusted-owner Antigravity manager sessions; off keeps full inline input.", options: {off: "Off", on: "On"},
}};
if (capabilityId === "codex_chat") return {...fieldCopy[locale], ...(locale === "zh-CN" ? {
codex_profile: {label: "Codex 配置来源", description: "选择已有本机配置,例如 codex-gpt。账户和凭据留在原目录,不复制;留空继承服务配置。"},
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/machine-configuration-settings.tsx b/apps/presentation/dashboard/src/features/personal-workspace/machine-configuration-settings.tsx
index 7aa426d34f..008c412f41 100644
--- a/apps/presentation/dashboard/src/features/personal-workspace/machine-configuration-settings.tsx
+++ b/apps/presentation/dashboard/src/features/personal-workspace/machine-configuration-settings.tsx
@@ -279,7 +279,7 @@ export function MachineConfigurationSettings({ section, onChanged }: {
setNotice(null);
}
- async function setContextDelivery(mode: "off" | "on" | "auto", key: "mode" | "delta_delivery" | "antigravity_mode" = "mode") {
+ async function setContextDelivery(mode: "off" | "on" | "auto", key: "mode" | "delta_delivery" = "mode") {
if (busy || !editorAvailable || selected?.capability_id !== "context_delivery" || !selected.machine_namespace) return;
const namespace = selected.machine_namespace;
const configuration = {...selected.default, ...selectedCurrent, [key]: mode};
@@ -298,7 +298,7 @@ export function MachineConfigurationSettings({ section, onChanged }: {
if (next.machine_configuration?.namespaces[namespace]?.[key] !== mode) {
throw new Error(locale === "zh-CN" ? "保存后的配置已变化,请刷新后重试。" : "The saved configuration changed. Refresh and retry.");
}
- const targetLabel = key === "antigravity_mode" ? "Antigravity" : key === "delta_delivery"
+ const targetLabel = key === "delta_delivery"
? locale === "zh-CN" ? "跨轮差分" : "Cross-turn delta"
: locale === "zh-CN" ? "渐进读取" : "Progressive reads";
setNotice(locale === "zh-CN" ? `${targetLabel}偏好已保存。` : `${targetLabel} preference saved.`);
@@ -539,26 +539,10 @@ export function MachineConfigurationSettings({ section, onChanged }: {
void setContextDelivery(event.target.checked ? "auto" : "off", "delta_delivery")} />
-
- Antigravity
- void setContextDelivery(event.target.checked ? "on" : "off", "antigravity_mode")} />
- {(selectedCurrent?.mode ?? selected.default?.mode) === "on"
- ? selectedCurrent
- ? locale === "zh-CN" ? "渐进读取已开启。" : "Progressive reads are on."
- : locale === "zh-CN" ? "渐进读取默认开启。" : "Progressive reads default on."
- : locale === "zh-CN" ? "渐进读取已关闭。" : "Progressive reads are off."}
- {(selectedCurrent?.delta_delivery ?? selected.default?.delta_delivery ?? "auto") === "auto"
- ? locale === "zh-CN" ? "跨轮差分自动选择;当前会话是否采用尚未验证。" : "Delta is automatic; current-session use is unverified."
- : locale === "zh-CN" ? "跨轮差分已关闭。" : "Cross-turn delta is off."}
- {(selectedCurrent?.antigravity_mode ?? selected.default?.antigravity_mode ?? "on") === "on"
- ? locale === "zh-CN" ? "Antigravity 管家历史渐进读取已开启。" : "Antigravity progressive manager history is on."
- : locale === "zh-CN" ? "Antigravity 已关闭。" : "Off for Antigravity."}
{locale === "zh-CN"
- ? "渐进读取先提供当前要求,支持材料按需展开,适用于所有宿主。跨轮差分独立控制:仅在受支持的 POSIX Codex App/SSH、benchmark 心跳已保留完整旧上下文时自动使用,否则恢复完整当前输入。Antigravity 管家历史另有独立开关。关闭偏好和实验显式关闭均继续生效。保存不会安装 hook、启动实验或证明当前会话已采用差分。"
- : "Progressive reads present current requirements before expandable supporting material on every host. Cross-turn delta is independent: automatic reuse requires a supported POSIX Codex App/SSH or benchmark heartbeat and complete retained context; otherwise the current full input is restored. Antigravity manager history has its own switch. Saved off preferences and explicit experiment opt-outs remain effective. Saving installs no hook, starts no experiment and does not prove current-session delta use."}
+ ? "渐进读取先提供当前要求,支持材料按需展开,适用于所有宿主。跨轮差分独立控制:仅在受支持的 POSIX Codex App/SSH、benchmark 心跳已保留完整旧上下文时自动使用,否则恢复完整当前输入。关闭偏好和实验显式关闭均继续生效。保存不会安装 hook、启动实验或证明当前会话已采用差分。"
+ : "Progressive reads present current requirements before expandable supporting material on every host. Cross-turn delta is independent: automatic reuse requires a supported POSIX Codex App/SSH or benchmark heartbeat and complete retained context; otherwise the current full input is restored. Saved off preferences and explicit experiment opt-outs remain effective. Saving installs no hook, starts no experiment and does not prove current-session delta use."}
: null}
{editorAvailable && selected.capability_id !== "context_delivery" ? <>{editorMode === "json" || !selected.configuration_editor.fields.some((field) => field.key === "enabled" && field.input_kind === "boolean") ?
changeMode(editorMode === "guided" ? "json" : "guided")} type="button">
diff --git a/docs/architecture/rfcs/manager-runtime-profile-v0.md b/docs/architecture/rfcs/manager-runtime-profile-v0.md
index d3bee0c390..ef9ffcea8e 100644
--- a/docs/architecture/rfcs/manager-runtime-profile-v0.md
+++ b/docs/architecture/rfcs/manager-runtime-profile-v0.md
@@ -83,9 +83,9 @@ These defaults do not change ordinary Goal Chat models or grant other Agents too
frozen snapshot reader, not the Codex-only live `loopx_manager_read` tool or a delta baseline.
Before relying on that history, read the required section through its final page. Context
loss recovers from the same capture without resending the request or repeating effects.
-- The machine `context_delivery.antigravity_mode=off` preference or host environment
- `LOOPX_CONTEXT_DELIVERY=off` keeps subsequent native manager inputs fully inline, while
- `context_delivery.mode` remains the independent Codex preference.
+- The manager selects history delivery automatically according to its authorized reader.
+ Existing explicit `context_delivery.antigravity_mode=off` preferences and the host environment
+ `LOOPX_CONTEXT_DELIVERY=off` retain complete inline history.
Restricted/text-only hosts, invalid settings and unavailable private capture IO also retain
that input; no host permission or approval is changed. These references preserve only the
already-authorized snapshot, not fresh observation or action authority. Capture files stay
diff --git a/docs/architecture/rfcs/manager-runtime-profile-v0.zh-CN.md b/docs/architecture/rfcs/manager-runtime-profile-v0.zh-CN.md
index ea690de24e..ca5836b5c9 100644
--- a/docs/architecture/rfcs/manager-runtime-profile-v0.zh-CN.md
+++ b/docs/architecture/rfcs/manager-runtime-profile-v0.zh-CN.md
@@ -66,8 +66,8 @@ LoopX 管家最初只有受限的规划会话:它可以读取 LoopX 提供的
执行供应的选择命令,不知道时再查目录。这是冻结快照读取,不是 Codex 专属的实时
`loopx_manager_read` 工具或差分基线。依赖该历史前,应读完所需片段的全部页;上下文
丢失后从同一 capture 恢复,不重新发送请求或重复副作用。
-- 机器配置 `context_delivery.antigravity_mode=off` 或宿主环境变量 `LOOPX_CONTEXT_DELIVERY=off`
- 使后续原生管家输入保持完整内联,`context_delivery.mode` 仍保持为独立的 Codex 偏好。
+- 管家依据已授权的读取能力自动选择历史交付方式。既有显式 `context_delivery.antigravity_mode=off` 偏好
+ 或宿主环境变量 `LOOPX_CONTEXT_DELIVERY=off` 使后续原生管家输入保持完整内联。
受限/文本宿主、配置损坏或私有 capture IO 不可用时
也保留原输入,不改变宿主权限或审批。引用只保留原已授权快照,不是新鲜观察或动作
授权;capture 私有保存于 Chat 存储,不写入所选项目的检出目录。RPC 与真实 CLI fixture
diff --git a/docs/reference/required-work-context.md b/docs/reference/required-work-context.md
index d78c4210b3..337a2bb461 100644
--- a/docs/reference/required-work-context.md
+++ b/docs/reference/required-work-context.md
@@ -575,22 +575,19 @@ the existing Turn or its recovery files.
### Machine default
**Settings → This machine → Capabilities → Progressive context** exposes progressive
-reads (`mode`), independent cross-Turn reuse (`delta_delivery`) and the existing
-Antigravity manager-history setting (`antigravity_mode`). It uses the same
+reads (`mode`) and cross-Turn reuse (`delta_delivery`). It uses the same
revision-locked preview, apply, readback, disable and rollback owner. Read-only
editors cannot save; sibling settings and Goal records remain unchanged. No choice
installs hooks, trusts a host or proves actual delivery or model retention.
The existing `context_delivery_machine_defaults_v0` namespace accepts
-`{"schema_version":"context_delivery_machine_defaults_v0","mode":"on","delta_delivery":"auto","antigravity_mode":"on"}`.
+`{"schema_version":"context_delivery_machine_defaults_v0","mode":"on","delta_delivery":"auto"}`.
`mode` and `antigravity_mode` keep their `on|off` values; omitted `delta_delivery`
defaults to `auto` and also accepts `off`. Old saved rows remain readable.
`machine-config preview/apply --namespace context_delivery --config-json FILE`
requires the original preview revision. Removing the namespace restores progressive
reads, supported-host Delta AUTO and Antigravity manager history reads. Save the
-relevant off setting to keep it disabled. `antigravity_mode` still independently
-controls private reads of `recent_delivery_history` in trusted-owner manager turns;
-it does not grant host configuration or execution authority.
+relevant off setting to keep it disabled. Manager history is delivered automatically. A trusted-owner native manager can read nonempty delivery history from a private snapshot using its permitted shell. Current facts stay inline. Existing explicit legacy `antigravity_mode=off` preferences remain effective.
The CLI facade `--context-delivery auto` (also the omitted default) presents
current requirements before expandable material across hosts. Stateless CLI,
@@ -960,16 +957,16 @@ quota 能力候选沿用同一精确 codec 复用已登记 Todo 的正文、标
### 机器级默认
在**设置 → 本机设置 → 能力中心 → 渐进上下文**分别设置渐进读取(`mode`)、独立的跨轮差分
-(`delta_delivery`)及原有 Antigravity 管家历史读取(`antigravity_mode`),沿用现有精确修订的预览、
+(`delta_delivery`),沿用现有精确修订的预览、
应用、读回、关闭和回滚 owner。只读编辑器不能保存;不改写其他配置和 Goal,不安装/信任 hook,
保存偏好不证明原生初始化、实际投递或模型保留。
既有 `context_delivery_machine_defaults_v0` namespace 接受
-`{"schema_version":"context_delivery_machine_defaults_v0","mode":"on","delta_delivery":"auto","antigravity_mode":"on"}`。
+`{"schema_version":"context_delivery_machine_defaults_v0","mode":"on","delta_delivery":"auto"}`。
`mode` 与 `antigravity_mode` 保留 `on|off`;可选的 `delta_delivery` 默认为 `auto`,也可为 `off`;旧配置继续可读。
CLI 的 `machine-config preview/apply --namespace context_delivery --config-json FILE` 仍需原预览修订。
移除 namespace 恢复渐进读取、支持宿主的 Delta AUTO 与 Antigravity 管家历史读取;要保持关闭应保存对应 off。
-`antigravity_mode` 继续独立控制强能力管家的 `recent_delivery_history` 私有快照读取,不新增宿主配置或执行权限。
+管家自动选择交付历史的读取方式。有权限读取私有快照的原生管家可按需读取已有历史,当前目标与待办仍直接可见。既有显式 `antigravity_mode=off` 偏好继续生效。
CLI 的 `--context-delivery auto`(省略时也使用此门面)跨宿主先呈现当前要求,再按需展开材料。
普通 CLI、其他已声明宿主及恢复读取不要求原生初始化;只读 `should-run` 仍不创建 Turn、回执、会话、journal 或执行 lease。
diff --git a/examples/personal-workspace-browser/configuration-backup.mjs b/examples/personal-workspace-browser/configuration-backup.mjs
index b2cb98c71c..506e90941f 100644
--- a/examples/personal-workspace-browser/configuration-backup.mjs
+++ b/examples/personal-workspace-browser/configuration-backup.mjs
@@ -210,20 +210,20 @@ export const configurationBackupScenario = {
const settings = page.getByRole("button", {name: "Settings", exact: true});
if (await settings.count()) await settings.click();
await page.locator(".personal-settings-tabs").getByRole("button", {name: /Capabilit/}).click();
- await page.getByRole("button", {name: /Differential context/}).click();
- return page.getByRole("switch", {name: "Use differential context in Codex", exact: true});
+ await page.getByRole("button", {name: /Progressive context/}).click();
+ return page.getByRole("switch", {name: "Read context progressively", exact: true});
}
let contextSwitch = await openContextSettings();
await page.screenshot({path: resolve(outputDir, "context-default-on-desktop.png"), animations: "disabled"});
assert.equal(await contextSwitch.isChecked(), true, "Unconfigured Codex must show its effective on default");
- await page.getByText("Default on; native setup and use unverified.", {exact: true}).waitFor();
+ assert.equal(await page.locator(".personal-capability-detail [role=switch]").count(), 2);
await page.setViewportSize({width: 390, height: 844});
assert.equal(await page.evaluate(() => document.documentElement.scrollWidth > window.innerWidth), false);
await contextSwitch.scrollIntoViewIfNeeded();
await page.screenshot({path: resolve(outputDir, "context-default-on-mobile.png"), animations: "disabled"});
await page.setViewportSize({width: 1512, height: 982});
await contextSwitch.click();
- await page.getByText("Off for Codex.", {exact: true}).waitFor();
+ await page.getByText("Progressive reads preference saved.", {exact: true}).waitFor();
const storedSettings = () => readFile(join(root, "runtime/machine/configuration.json"), "utf8").then(JSON.parse);
assert.equal((await storedSettings()).namespaces.context_delivery.mode, "off");
contextSwitch = await openContextSettings();
@@ -235,7 +235,7 @@ export const configurationBackupScenario = {
assert.equal((await storedSettings()).namespaces.context_delivery.mode, "off", "Failed apply must preserve saved off");
await page.unroute(applyRoute);
await contextSwitch.click();
- await page.getByText("On; native setup and use unverified.", {exact: true}).waitFor();
+ await page.getByText("Progressive reads preference saved.", {exact: true}).waitFor();
const afterSettings = await storedSettings();
assert.equal(afterSettings.namespaces.context_delivery.mode, "on");
assert.equal(afterSettings.namespaces.goal_storage.new_goal_provider, "sqlite", "The opt-out/on transaction must preserve sibling settings");
diff --git a/loopx/capabilities/configuration_ui.py b/loopx/capabilities/configuration_ui.py
index 2960570c97..ceee068e56 100644
--- a/loopx/capabilities/configuration_ui.py
+++ b/loopx/capabilities/configuration_ui.py
@@ -94,9 +94,6 @@ def capability_configuration_editor(
description="Present current requirements before expandable supporting material on every host. Off keeps complete inline delivery."),
_field("delta_delivery", "Cross-Turn Delta", "select", options=("off", "auto"), required=True,
description="Auto reuses exact saved captures only on supported continuity hosts. Off leaves progressive presentation enabled. Neither choice proves retained model input."),
- _field("antigravity_mode", "Antigravity manager history", "select",
- options=("off", "on"), required=True,
- description="On defers trusted-owner Antigravity manager delivery histories to private capture reads while keeping current facts inline; off keeps full inline input."),
],
},
"codex_chat": {
diff --git a/loopx/capabilities/machine_configuration/context_delivery.py b/loopx/capabilities/machine_configuration/context_delivery.py
index 70b38cea59..3c588d7be5 100644
--- a/loopx/capabilities/machine_configuration/context_delivery.py
+++ b/loopx/capabilities/machine_configuration/context_delivery.py
@@ -25,7 +25,7 @@ def normalize_context_delivery_machine_defaults(raw: Mapping[str, Any]) -> dict[
"schema_version": CONTEXT_DELIVERY_MACHINE_SCHEMA,
"mode": raw["mode"],
"delta_delivery": delta,
- "antigravity_mode": antigravity_mode,
+ **({"antigravity_mode": antigravity_mode} if "antigravity_mode" in raw else {}),
}
@@ -39,10 +39,7 @@ def context_delivery_machine_configuration_namespace() -> MachineConfigurationNa
title="Progressive context",
description=(
"Read current requirements before expandable supporting material on every host (`mode`). "
- "Reuse unchanged context independently on supported continuity hosts (`delta_delivery`), "
- "and read trusted-owner Antigravity manager delivery histories progressively from private captures "
- "(`antigravity_mode`). Both default on independently; explicit unsupported Codex activation fails "
- "and known context loss or disabled provider preferences keep full context. "
+ "Supported continuity hosts may reuse unchanged context across turns. "
"Completed Codex reads use an explicit native-hook continuity assumption. "
"A saved preference does not establish host readiness or actual delta use."
),
@@ -51,6 +48,5 @@ def context_delivery_machine_configuration_namespace() -> MachineConfigurationNa
"schema_version": CONTEXT_DELIVERY_MACHINE_SCHEMA,
"mode": "on",
"delta_delivery": "auto",
- "antigravity_mode": "on",
},
)
diff --git a/tests/control_plane/test_context_machine_configuration.py b/tests/control_plane/test_context_machine_configuration.py
index 8e0dd969e5..c633e15bc1 100644
--- a/tests/control_plane/test_context_machine_configuration.py
+++ b/tests/control_plane/test_context_machine_configuration.py
@@ -76,7 +76,7 @@ def test_machine_catalog_discovers_context_delivery_without_activation(tmp_path)
assert len(contexts) == 1
assert contexts[0]["schema_versions"] == [CONTEXT_DELIVERY_MACHINE_SCHEMA]
assert contexts[0]["configuration_template"] == {
- "schema_version": CONTEXT_DELIVERY_MACHINE_SCHEMA, "mode": "on", "delta_delivery": "auto", "antigravity_mode": "on",
+ "schema_version": CONTEXT_DELIVERY_MACHINE_SCHEMA, "mode": "on", "delta_delivery": "auto",
}
assert not registry.exists() and not (runtime / "machine/configuration.json").exists()
assert not (runtime / "context-delivery").exists()
diff --git a/tests/test_manager_native_context.py b/tests/test_manager_native_context.py
index 0ad0668888..6a36bc4c7f 100644
--- a/tests/test_manager_native_context.py
+++ b/tests/test_manager_native_context.py
@@ -159,7 +159,8 @@ def test_codex_and_antigravity_context_preferences_operate_independently(
assert stored["namespaces"]["context_delivery"] == {
"schema_version": "context_delivery_machine_defaults_v0",
"mode": codex_mode,
- "antigravity_mode": expected_antigravity,
+ "delta_delivery": "auto",
+ **({"antigravity_mode": antigravity_mode} if antigravity_mode is not None else {}),
}
args = argparse.Namespace(
@@ -168,12 +169,10 @@ def test_codex_and_antigravity_context_preferences_operate_independently(
format="json", codex_context_dir=None, codex_context_root=None,
decision_handoff_socket=None, decision_output_dir=None, decision_output_root=None,
)
+ apply_context_machine_options(args, registry_path=tmp_path / "absent.json", runtime_root_arg=str(tmp_path))
+ assert args.context_delivery == ("auto" if codex_mode == "on" else "off")
if codex_mode == "on" and os.name != "posix":
- with pytest.raises(ValueError, match="unavailable on this platform"):
- apply_context_machine_options(args, registry_path=tmp_path / "absent.json", runtime_root_arg=str(tmp_path))
- else:
- apply_context_machine_options(args, registry_path=tmp_path / "absent.json", runtime_root_arg=str(tmp_path))
- assert args.context_delivery == codex_mode
+ assert args.delta_delivery == "off"
capture_root = tmp_path / "captures"
capture_root.mkdir()
From e7fc3631c80cdd4425c0c2e871e054e47b5a7b31 Mon Sep 17 00:00:00 2001
From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Date: Thu, 5 Nov 2026 00:17:46 +0800
Subject: [PATCH 5/6] fix(context): retain typed array indices for
selected-read identity
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
---
loopx/control_plane/quota/progressive_context.ts | 12 +++++-------
loopx/control_plane/quota/turn_envelope.ts | 2 +-
.../test_progressive_context_entrypoints.py | 14 ++++++++------
3 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/loopx/control_plane/quota/progressive_context.ts b/loopx/control_plane/quota/progressive_context.ts
index 46ea700718..bc48d47140 100644
--- a/loopx/control_plane/quota/progressive_context.ts
+++ b/loopx/control_plane/quota/progressive_context.ts
@@ -18,19 +18,17 @@ const known = (row: JsonObject, fields: string[]): boolean => Object.keys(row).e
/** Digests stay in the private observed-read journal, never repeated to the model.
* The existing exact-source identity preserves non-JS numeric spellings. */
-export function contextReadSectionDigests(request: JsonObject, pointers: string[]): JsonObject {
+export function contextReadSectionDigests(request: JsonObject, paths: Path[]): JsonObject {
const context = requireJsonObject(request.context, "read section source");
const identity = contextSourceIdentity(request, request.source_number_tokens);
- return Object.fromEntries(pointers.map(address => {
- const path = address === "" ? [] : address.slice(1).split("/").map(key => key.replaceAll("~1", "/").replaceAll("~0", "~"));
- return [address, createHash("sha256").update(identity(at(context, path), ["context", ...path])).digest("hex")];
- }));
+ return Object.fromEntries(paths.map(path => [pointer(path),
+ createHash("sha256").update(identity(at(context, path), ["context", ...path])).digest("hex")]));
}
function inlineReadSections(request: JsonObject, required: JsonObject): JsonObject {
- const original = requireJsonObject(request.context, "inline source"), paths: string[] = [];
+ const original = requireJsonObject(request.context, "inline source"), paths: Path[] = [];
const visit = (source: unknown, shown: unknown, path: Path) => {
- if (source === shown) { paths.push(pointer(path)); return; }
+ if (source === shown) { paths.push(path); return; }
if (!source || !shown || typeof source !== "object" || typeof shown !== "object") return;
for (const key of Object.keys(source)) if (Object.hasOwn(shown, key)) visit(
(source as JsonObject)[key], (shown as JsonObject)[key], [...path, Array.isArray(source) ? Number(key) : key]);
diff --git a/loopx/control_plane/quota/turn_envelope.ts b/loopx/control_plane/quota/turn_envelope.ts
index 68b5ddadac..0aa8184507 100644
--- a/loopx/control_plane/quota/turn_envelope.ts
+++ b/loopx/control_plane/quota/turn_envelope.ts
@@ -1495,7 +1495,7 @@ export function evaluateTurnEnvelope(value: unknown): JsonObject {
if (operation === "context_read_sections") {
const selected = capturedContextSelection({...request, list_fields: false});
return {sections: contextReadSectionDigests(request,
- (selected.selections as JsonObject[]).map(row => String(row.pointer)))};
+ (selected.selections as {path: (string | number)[]}[]).map(row => row.path))};
}
if (operation === "progressive_context_delivery") return prepareProgressiveContext(request);
if (operation === "context_delivery") return request.native_projection === undefined
diff --git a/tests/control_plane/test_progressive_context_entrypoints.py b/tests/control_plane/test_progressive_context_entrypoints.py
index 37d1aed49f..380419f6d7 100644
--- a/tests/control_plane/test_progressive_context_entrypoints.py
+++ b/tests/control_plane/test_progressive_context_entrypoints.py
@@ -134,18 +134,20 @@ def test_damaged_or_forged_selected_delivery_never_acknowledges_a_section(tmp_pa
assert supporting in native._state(tmp_path)["consumed_pointers"]
-def test_selected_read_observation_preserves_exact_source_number_identity(tmp_path, monkeypatch):
+@pytest.mark.parametrize("address", ["/numbers", "/numbers/0", "/object/0"])
+def test_selected_read_observation_preserves_exact_source_number_identity(tmp_path, monkeypatch, address):
event = setup(tmp_path, monkeypatch)
source = payload()
source["numbers"] = [1.0, -0.0, 2**60 + 1]
+ source["object"] = {"0": 1.0}
_, first = project(tmp_path, payload=source)
- deliver(tmp_path, event, selected_pages(first["context"]["context_details"], "/numbers"))
- observed = native._state(tmp_path)["consumed_pointers"]["/numbers"]
+ deliver(tmp_path, event, selected_pages(first["context"]["context_details"], address))
+ observed = native._state(tmp_path)["consumed_pointers"][address]
changed = deepcopy(source)
- changed["numbers"][0] = 1
+ changed["numbers"][0] = changed["object"]["0"] = 1
_, second = project(tmp_path, "second", payload=changed)
- deliver(tmp_path, event, selected_pages(second["context"]["context_details"], "/numbers"))
- assert native._state(tmp_path)["consumed_pointers"]["/numbers"] != observed
+ deliver(tmp_path, event, selected_pages(second["context"]["context_details"], address))
+ assert native._state(tmp_path)["consumed_pointers"][address] != observed
def test_default_progressive_does_not_admit_conflicting_host_declarations(acceptance_goal):
From 6f4cbced5537404243ee2b2547e7714cc52c1773 Mon Sep 17 00:00:00 2001
From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Date: Thu, 5 Nov 2026 00:19:20 +0800
Subject: [PATCH 6/6] test(context): verify first-read navigation and exact
detail recovery
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
---
tests/control_plane/test_context_unread_reachability.py | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/tests/control_plane/test_context_unread_reachability.py b/tests/control_plane/test_context_unread_reachability.py
index b645662cb5..679871571b 100644
--- a/tests/control_plane/test_context_unread_reachability.py
+++ b/tests/control_plane/test_context_unread_reachability.py
@@ -9,6 +9,7 @@
from loopx.cli_commands.quota_capture import read_context_capture
from loopx.control_plane.turn_driver import codex_context as context
+from tests.control_plane.codex_checkpoint_fixture import selected_context_values
from test_codex_context_lifecycle import setup, project
from test_progressive_native_context import payload, outcome
from test_quota_settlement_cli import _run_cli
@@ -44,8 +45,9 @@ def test_unconfirmed_material_reaches_next_turn_work_from_current_capture(
argv = shlex.split(navigation["first_read_command"])
code, initial = _run_cli(registry, runtime, *argv[argv.index("quota"):], cwd=tmp_path)
assert code == 0 and initial["eof"], initial
- shown = {row["pointer"]: row["value"] for row in json.loads(initial["content"])["selections"]}
- assert shown["/context_details/unread_context_index"] == first_index
+ shown = selected_context_values(initial["content"])
+ for field in ("source", "coverage_confirmed", "read_before_dependent_work"):
+ assert shown[f"/context_details/unread_context_index/{field}"] == first_index[field]
def read_detail(source, pointer):
words = ["quota", "context-read", "--capture-file", source["path"],
@@ -62,6 +64,7 @@ def read_detail(source, pointer):
argv = shlex.split(page["next_command"])
words = argv[argv.index("quota"):]
+ assert read_detail(first["recovery"], "/context_details/unread_context_index") == first_index
if previous_detail_read:
previous_note = next(pointer for pointer in first_index["pointers"]
if pointer.endswith("/outcomes/0/requirements/0/agent_review/note"))