From c5f151b6329d0c4d6a727369b6eb022ba7249fbf Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Sat, 7 Nov 2026 22:43:44 +0800 Subject: [PATCH 1/4] Stage saved replans in stateless progressive context Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- loopx/cli_commands/quota_capture.py | 10 ++-- .../quota/progressive_context.ts | 4 +- loopx/control_plane/quota/turn_envelope.ts | 3 +- .../turn_driver/decision_capture.py | 8 ++- .../test_replan_progress_native_cli.py | 55 +++++++++++++++++++ 5 files changed, 72 insertions(+), 8 deletions(-) diff --git a/loopx/cli_commands/quota_capture.py b/loopx/cli_commands/quota_capture.py index c812f619a4..cb299ad079 100644 --- a/loopx/cli_commands/quota_capture.py +++ b/loopx/cli_commands/quota_capture.py @@ -668,7 +668,8 @@ def progressive_context_or_current(payload: dict[str, Any], args: argparse.Names 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]: + reader_argv: list[str] | None = None, + captured_decision_path: 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 @@ -680,8 +681,9 @@ def progressive_context_capture_view(payload: dict[str, Any], args: argparse.Nam 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) + transport = _capture_selection_transport_template(payload, args, capture_root=directory.parent) + required, reference = capture_progressive_context(payload, directory=directory, surface=surface, + selection_command_args_template=transport, captured_decision_path=captured_decision_path) 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 {})}, @@ -763,7 +765,7 @@ def project_saved_context_capture(args: argparse.Namespace, *, hook_session: str 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) + directory=None, reader_argv=reader_argv, captured_decision_path=str(path)) except (QuotaDecisionTransportError, OSError, ValueError, EffectRuntimeRemoteError, EffectRuntimeStartupError): pass # The complete original reference remains the fallback below. try: diff --git a/loopx/control_plane/quota/progressive_context.ts b/loopx/control_plane/quota/progressive_context.ts index 38a97d03dc..b52eddc977 100644 --- a/loopx/control_plane/quota/progressive_context.ts +++ b/loopx/control_plane/quota/progressive_context.ts @@ -415,9 +415,9 @@ export function prepareProgressiveContextDelivery(request: JsonObject, legacyFie /** 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 { +export function prepareProgressiveContext(request: JsonObject, plan?: JsonObject): JsonObject { const values: ProjectionSourceValues = new WeakMap(); - const required = requiredNativeContext(request, values); + const required = requiredNativeContext(request, values, plan); const {operation: _operation, source_edits: _edits, source_number_tokens: _numbers, ...source} = request; return contextProjectionChanges(source, {context: required.context, projected: required.projected}, values); } diff --git a/loopx/control_plane/quota/turn_envelope.ts b/loopx/control_plane/quota/turn_envelope.ts index a0f982cbf3..1fe3123eea 100644 --- a/loopx/control_plane/quota/turn_envelope.ts +++ b/loopx/control_plane/quota/turn_envelope.ts @@ -1755,7 +1755,8 @@ export function evaluateTurnEnvelope(value: unknown): JsonObject { return {sections: contextReadSectionDigests(request, (selected.selections as {path: (string | number)[]}[]).map(row => row.path))}; } - if (operation === "progressive_context_delivery") return prepareProgressiveContext(request); + if (operation === "progressive_context_delivery") + return prepareProgressiveContext(request, nativeReplanPresentation(request)); if (operation === "context_delivery") return request.native_projection === undefined ? prepareContextDelivery(request, LEGACY_QUOTA_CONTEXT_FIELDS) : prepareProgressiveContextDelivery(request, LEGACY_QUOTA_CONTEXT_FIELDS, INITIAL_CONTEXT_DECISION_FIELDS, diff --git a/loopx/control_plane/turn_driver/decision_capture.py b/loopx/control_plane/turn_driver/decision_capture.py index 42db430ed4..05b113b416 100644 --- a/loopx/control_plane/turn_driver/decision_capture.py +++ b/loopx/control_plane/turn_driver/decision_capture.py @@ -425,17 +425,23 @@ 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]]: + surface: str = "quota_packet", + selection_command_args_template: str | None = None, + captured_decision_path: str | None = None) -> 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. + A caller may supply the exact decision it just verified for staged reads. """ 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")}, + **({"selection_command_args_template": selection_command_args_template} + if selection_command_args_template is not None else {}), + **({"captured_decision_path": captured_decision_path} if captured_decision_path is not None else {}), "source_path": source["path"], "command_template": source["command"] + " --select ''", }) diff --git a/tests/control_plane/test_replan_progress_native_cli.py b/tests/control_plane/test_replan_progress_native_cli.py index 6faa860cec..8afeb76e71 100644 --- a/tests/control_plane/test_replan_progress_native_cli.py +++ b/tests/control_plane/test_replan_progress_native_cli.py @@ -4,6 +4,7 @@ import hashlib import json import os +import shlex import subprocess import sys from pathlib import Path @@ -167,6 +168,60 @@ def test_progress_cli_reads_policy_with_context_delivery( restart_effect_runtime(wait_for_exit=True) +@pytest.mark.parametrize("provider", ["file", "sqlite"]) +def test_stateless_progressive_replan_uses_the_saved_decision(tmp_path, monkeypatch, provider): + isolate_sqlite_runtime(tmp_path, monkeypatch) + fixture = make_progress_cli_fixture(tmp_path, provider, "advanced") + capture = tmp_path / "capture" + scope = ("--codex-app", "--goal-id", GOAL, "--agent-id", AGENT, "--turn-instance-id", TURN) + delivery = ("--context-delivery", "on", "--delta-delivery", "off") + + def first_review(view): + page = read_stage(shlex.split(view["first_read_command"])) + assert page["ok"] and page["offset"] == 0 and page["eof"] + assert len(page["content"].encode()) == page["total_bytes"] + fields = {row["pointer"]: row["value"] for row in json.loads(page["content"])["selections"]} + assert fields["/heartbeat_receipt"] == source["heartbeat_receipt"] + assert "/replan_action_packet/planning_guidance" not in fields + return shlex.split(fields["/replan_action_packet/review"]) + + def read_stage(command, status=0): + result = subprocess.run(command, capture_output=True, text=True, timeout=30) + assert result.returncode == status, result.stdout + result.stderr + return json.loads(result.stdout) + + try: + initial = call_progress_cli(fixture, "quota", "should-run", *scope, "--todo-id", TODO, + "--decision-output-dir", str(capture), *delivery) + original = capture / "decision.json" + raw = original.read_bytes() + source = json.loads(raw) + receipt = source["heartbeat_receipt"] + authority = _authority(fixture) + review_command = first_review(initial) + assert review_command[review_command.index("--decision-file") + 1] == str(original) + review = read_stage(review_command) + assert review["planning_guidance"] == source["replan_action_packet"]["planning_guidance"] + writer = read_stage(shlex.split(review["next"]["writeback"])) + assert writer["writeback"]["settlement_plan"]["identity"] == receipt["settlement_identity"] + assert writer["required_outcome"] == source["replan_action_packet"]["required_outcome"] + + recovered_path = original.with_name("recovered.json") + original.rename(recovered_path) + projected = call_progress_cli(fixture, "quota", "context-project", *scope, *delivery, + "--capture-file", str(recovered_path), "--capture-sha256", hashlib.sha256(raw).hexdigest()) + recovered_review = first_review(projected) + assert recovered_review[recovered_review.index("--decision-file") + 1] == str(recovered_path) + assert read_stage(recovered_review)["source_hash"] == review["source_hash"] + recovered_review[recovered_review.index("--source-hash") + 1] = "sha256:" + "0" * 64 + refused = read_stage(recovered_review, status=1) + assert refused["ok"] is False and "matching source hash" in refused["reason"] + assert recovered_path.read_bytes() == raw + assert _authority(fixture) == authority + finally: + restart_effect_runtime(wait_for_exit=True) + + @pytest.mark.parametrize("provider", ["file", "sqlite"]) @pytest.mark.parametrize("context_args,navigation", [ ((), False), From 89c6cb106ad456a67a1c0394322a2516cb71c2b1 Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Sat, 7 Nov 2026 23:15:06 +0800 Subject: [PATCH 2/4] Attach saved progressive first pages with Delta off Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- loopx/cli_commands/quota_capture.py | 33 ++++++++----- loopx/cli_commands/quota_registration.py | 5 +- .../test_replan_progress_native_cli.py | 47 ++++++++++++++----- 3 files changed, 59 insertions(+), 26 deletions(-) diff --git a/loopx/cli_commands/quota_capture.py b/loopx/cli_commands/quota_capture.py index cb299ad079..b6d9fa9545 100644 --- a/loopx/cli_commands/quota_capture.py +++ b/loopx/cli_commands/quota_capture.py @@ -669,7 +669,8 @@ def progressive_context_capture_view(payload: dict[str, Any], args: argparse.Nam runtime_root: Path, directory: Path | None, surface: str = "quota_packet", reader_argv: list[str] | None = None, - captured_decision_path: str | None = None) -> dict[str, Any]: + captured_decision_path: str | None = None, + page_attached: bool = False) -> 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 @@ -687,11 +688,11 @@ def progressive_context_capture_view(payload: dict[str, Any], args: argparse.Nam 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) + max_page_output_bytes=getattr(args, "max_page_output_bytes", None), page_attached=page_attached, 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 + return readable if page_attached or len(_native_output_bytes(readable)) < len(_native_output_bytes(required)) else required def _saved_context_read_page(args: argparse.Namespace, navigation: dict[str, Any], *, @@ -713,6 +714,12 @@ def _saved_context_read_page(args: argparse.Namespace, navigation: dict[str, Any return page +def _context_page_output_enabled(args: argparse.Namespace, activation: dict[str, Any]) -> bool: + return activation["enabled"] or ( + args.quota_command == "context-project" and getattr(args, "initial_read", False) + and activation["progressive_enabled"]) + + def project_saved_context_capture(args: argparse.Namespace, *, hook_session: str | None = None) -> dict[str, Any]: """Present an immutable already-decided quota capture, without authority IO. @@ -729,11 +736,11 @@ def project_saved_context_capture(args: argparse.Namespace, *, hook_session: str try: activation = native_context_activation(args) saved_page = bool(getattr(args, "initial_read", False) or getattr(args, "select", None)) - if saved_page and (args.format != "json" or not activation["enabled"] or args.offset != 0 + if saved_page and (args.format != "json" or not _context_page_output_enabled(args, activation) or args.offset != 0 or args.reference_file or args.selection_sha256 or args.page_bytes is not None or (args.initial_read and args.select)): - raise ValueError("Use an enabled native JSON context-project with either --initial-read or --select " - "at offset zero. Use context-read for replay or continuation.") + raise ValueError("Use JSON context-project at offset zero with native delivery or progressive --initial-read. " + "Choose either --initial-read or --select. Use context-read for replay or continuation.") path, raw, payload = _read_capture(args.capture_file, args.capture_sha256, private=hook_session is not None) identity = payload.get("agent_identity") @@ -763,9 +770,12 @@ def project_saved_context_capture(args: argparse.Namespace, *, hook_session: str # 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, + navigation = progressive_context_capture_view(payload, args, runtime_root=Path(getattr(args, "_context_delivery_machine_runtime", path.parent)), - directory=None, reader_argv=reader_argv, captured_decision_path=str(path)) + directory=None, reader_argv=reader_argv, captured_decision_path=str(path), page_attached=saved_page) + if saved_page: + return _saved_context_read_page(args, navigation, initial_reference=None, reader_argv=reader_argv) + return navigation except (QuotaDecisionTransportError, OSError, ValueError, EffectRuntimeRemoteError, EffectRuntimeStartupError): pass # The complete original reference remains the fallback below. try: @@ -1173,7 +1183,7 @@ def handle_native_context_command(args: argparse.Namespace, *, print_payload: Ca registry_path: Path | None = None, runtime_root_arg: str | None = None) -> int | None: """Dispatch native presentation/lifecycle IO before any quota authority read.""" if getattr(args, "initial_read", False) and args.quota_command not in ("context-read", "context-project"): - print_payload({"ok": False, "reason": "--initial-read is only supported by context-read or enabled native JSON context-project"}, args.format, str) + print_payload({"ok": False, "reason": "--initial-read requires context-read or JSON context-project"}, args.format, str) return 1 list_depth = getattr(args, "list_depth", None) if list_depth is not None and (args.quota_command != "context-read" or not getattr(args, "list_fields", False) @@ -1187,7 +1197,8 @@ def handle_native_context_command(args: argparse.Namespace, *, print_payload: Ca settlement_output = (args.quota_command == "spend-slot" and args.format == "json" and bool(getattr(args, "turn_instance_id", None)) and bool(getattr(args, "agent_id", None))) budget_scope_error = ("max-page-output-bytes is only supported by JSON context-read " - "or enabled native should-run/context-project, or Turn-bound JSON spend-slot") + "or enabled native should-run/context-project, progressive context-project --initial-read, " + "or Turn-bound JSON spend-slot") if has_output_limit and args.quota_command != "context-read" and not settlement_output and ( args.quota_command not in ("should-run", "context-project") or args.format != "json" or (getattr(args, "context_delivery", None) == "off" and getattr(args, "delta_delivery", None) != "auto")): @@ -1215,7 +1226,7 @@ def handle_native_context_command(args: argparse.Namespace, *, print_payload: Ca return 1 if has_output_limit and args.quota_command != "context-read" and not settlement_output: try: - if not native_context_activation(args)["enabled"]: + if not _context_page_output_enabled(args, native_context_activation(args)): raise QuotaCommandValidationError(budget_scope_error) if args.max_page_output_bytes <= 0: raise QuotaCommandValidationError("max-page-output-bytes must be positive") diff --git a/loopx/cli_commands/quota_registration.py b/loopx/cli_commands/quota_registration.py index 8cced17797..404fac2179 100644 --- a/loopx/cli_commands/quota_registration.py +++ b/loopx/cli_commands/quota_registration.py @@ -239,7 +239,7 @@ def register_quota_command( "context-config renders native configuration for the exact Goal/Agent; no host configuration, trust, guard or spend are changed.") quota_parser.add_argument("--capture-sha256", help="For context-read/context-project: exact SHA-256 supplied with the capture reference.") quota_parser.add_argument("--initial-read", action="store_true", - help="For JSON context-read or enabled native context-project: read current controls, task text and source navigation from a recognized capture. " + help="For JSON context-read or enabled context-project: read current controls, task text and source navigation from a recognized capture. " "Detailed criteria and operation contracts remain required before dependent work. Start at offset zero; follow next_command for continuation.") quota_parser.add_argument("--select", action="append", help="For context-read or enabled native JSON context-project: repeat an exact RFC 6901 JSON pointer to read a batch from the original capture. " @@ -258,7 +258,8 @@ def register_quota_command( "Larger pages require a sufficient --max-page-output-bytes within the capture limit; " "use only with known sufficient direct and retained-history output budgets.") quota_parser.add_argument("--max-page-output-bytes", type=int, - help="For JSON context-read, enabled native should-run/context-project, or Turn-bound JSON spend-slot: optional positive output byte limit. " + help="For JSON context-read, native should-run/context-project, progressive context-project --initial-read, " + "or Turn-bound JSON spend-slot: optional positive output byte limit. " "Reader pages shrink at UTF-8 boundaries; oversized settlement diagnostics remain complete in a private immutable result with reader references. " "An insufficient metadata budget returns an error; this option does not enable native context continuity.") quota_parser.add_argument( diff --git a/tests/control_plane/test_replan_progress_native_cli.py b/tests/control_plane/test_replan_progress_native_cli.py index 8afeb76e71..bfc7014006 100644 --- a/tests/control_plane/test_replan_progress_native_cli.py +++ b/tests/control_plane/test_replan_progress_native_cli.py @@ -176,20 +176,29 @@ def test_stateless_progressive_replan_uses_the_saved_decision(tmp_path, monkeypa scope = ("--codex-app", "--goal-id", GOAL, "--agent-id", AGENT, "--turn-instance-id", TURN) delivery = ("--context-delivery", "on", "--delta-delivery", "off") - def first_review(view): - page = read_stage(shlex.split(view["first_read_command"])) - assert page["ok"] and page["offset"] == 0 and page["eof"] - assert len(page["content"].encode()) == page["total_bytes"] - fields = {row["pointer"]: row["value"] for row in json.loads(page["content"])["selections"]} - assert fields["/heartbeat_receipt"] == source["heartbeat_receipt"] - assert "/replan_action_packet/planning_guidance" not in fields - return shlex.split(fields["/replan_action_packet/review"]) - def read_stage(command, status=0): result = subprocess.run(command, capture_output=True, text=True, timeout=30) assert result.returncode == status, result.stdout + result.stderr return json.loads(result.stdout) + def read_pages(page, limit=64_000): + body = bytearray() + while True: + assert page["ok"] and page["offset"] == len(body) + assert len(json.dumps(page, ensure_ascii=False, separators=(",", ":")).encode()) + 1 <= limit + body.extend(page["content"].encode()) + if page["eof"]: + assert len(body) == page["total_bytes"] + return bytes(body) + assert page["next_offset"] == len(body) + page = read_stage(shlex.split(page["next_command"])) + + def review_for(body): + fields = {row["pointer"]: row["value"] for row in json.loads(body)["selections"]} + assert fields["/heartbeat_receipt"] == source["heartbeat_receipt"] + assert "/replan_action_packet/planning_guidance" not in fields + return shlex.split(fields["/replan_action_packet/review"]) + try: initial = call_progress_cli(fixture, "quota", "should-run", *scope, "--todo-id", TODO, "--decision-output-dir", str(capture), *delivery) @@ -198,7 +207,7 @@ def read_stage(command, status=0): source = json.loads(raw) receipt = source["heartbeat_receipt"] authority = _authority(fixture) - review_command = first_review(initial) + review_command = review_for(read_pages(read_stage(shlex.split(initial["first_read_command"])))) assert review_command[review_command.index("--decision-file") + 1] == str(original) review = read_stage(review_command) assert review["planning_guidance"] == source["replan_action_packet"]["planning_guidance"] @@ -208,14 +217,26 @@ def read_stage(command, status=0): recovered_path = original.with_name("recovered.json") original.rename(recovered_path) - projected = call_progress_cli(fixture, "quota", "context-project", *scope, *delivery, - "--capture-file", str(recovered_path), "--capture-sha256", hashlib.sha256(raw).hexdigest()) - recovered_review = first_review(projected) + saved = ("quota", "context-project", *scope, "--capture-file", str(recovered_path), "--initial-read") + digest = hashlib.sha256(raw).hexdigest() + first = call_progress_cli(fixture, *saved, *delivery, "--capture-sha256", digest, + "--max-page-output-bytes", "8192") + assert not first["eof"] and list(first).index("content") < list(first).index("navigation") + nav = first["navigation"] + assert nav["mode"] == "full" and "top-level content" in nav["instruction"] + body = read_pages(first, 8192) + assert read_pages(read_stage(shlex.split(nav["first_read_command"])), 8192) == body + recovered_review = review_for(body) assert recovered_review[recovered_review.index("--decision-file") + 1] == str(recovered_path) assert read_stage(recovered_review)["source_hash"] == review["source_hash"] recovered_review[recovered_review.index("--source-hash") + 1] = "sha256:" + "0" * 64 refused = read_stage(recovered_review, status=1) assert refused["ok"] is False and "matching source hash" in refused["reason"] + wrong_capture = call_progress_cli(fixture, *saved, *delivery, "--capture-sha256", "0" * 64, expected_code=1) + assert not wrong_capture["ok"] and "content" not in wrong_capture + disabled = call_progress_cli(fixture, *saved, "--context-delivery", "off", "--delta-delivery", "off", + "--capture-sha256", digest, expected_code=1) + assert not disabled["ok"] and "content" not in disabled assert recovered_path.read_bytes() == raw assert _authority(fixture) == authority finally: From 92d10e2d5a7f2600c9a98a659053acf8a997bbd1 Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Sat, 7 Nov 2026 23:25:19 +0800 Subject: [PATCH 3/4] Skip the root index before an attached progressive page Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- loopx/cli_commands/quota_capture.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/loopx/cli_commands/quota_capture.py b/loopx/cli_commands/quota_capture.py index b6d9fa9545..f98502c622 100644 --- a/loopx/cli_commands/quota_capture.py +++ b/loopx/cli_commands/quota_capture.py @@ -378,6 +378,7 @@ def _native_context_reference(projected: dict[str, Any], reference: dict[str, An initial_read_reference: Path | None, page_bytes: int, output_bytes: int, page_attached: bool = False, + first_read_requested: bool = False, reader_argv: list[str] | None = None) -> dict[str, Any]: """Build the bounded native reference without publishing or registering it.""" target = projected.get("target") if projected.get("schema_version") == "context_delivery_v1" else None @@ -413,10 +414,13 @@ def _native_context_reference(projected: dict[str, Any], reference: dict[str, An # The reference must fit even under an explicit small caller ceiling. def fits() -> bool: return len(json.dumps(result, ensure_ascii=False, separators=(",", ":")).encode()) + 1 <= min(output_bytes, 7900) - if initial_read_pointers: + if first_read_requested or initial_read_pointers: overview = result.pop("overview") instruction = result["instruction"] - if any(pointer.endswith("/vision_authoring/rule") for pointer in initial_read_pointers): + if first_read_requested: + instruction = ("If the initial selection names a Vision authoring step, select the complete vision_authoring object " + "at that step before composing a Vision. " + instruction) + elif any(pointer.endswith("/vision_authoring/rule") for pointer in (initial_read_pointers or ())): instruction = ("Before composing a Vision, select the complete vision_authoring object " "at the displayed step in this capture. " + instruction) first_read = ("Read the top-level content and follow next_command if eof is false. " @@ -541,6 +545,9 @@ def native_context_capture_view(projected: dict[str, Any], directory: Path, *, field_index = None initial_read_pointers = None initial_read_reference = None + # A stateless attached page uses the ordinary verified selector below. + # Its recovery recipe does not require an extra root index to be planned. + stateless_first_read = progressive_enabled and page_attached and captured_recovery is not None def pin_initial_selection(plan: dict[str, Any]) -> None: nonlocal initial_read_pointers, initial_read_reference @@ -566,7 +573,7 @@ def pin_initial_selection(plan: dict[str, Any]) -> None: except (EffectRuntimeRemoteError, EffectRuntimeStartupError): # Optional discovery cannot invalidate the immutable file reference. pass - elif progressive_enabled: + elif progressive_enabled and not stateless_first_read: try: plan = _turn_envelope_result("context_select", context=current_document, select=[""], list_fields=True) except (EffectRuntimeRemoteError, EffectRuntimeStartupError): @@ -581,7 +588,8 @@ def view(kind: str, ref: dict[str, Any], body: bytes) -> dict[str, Any]: field_index=field_index, initial_read_pointers=initial_read_pointers, progressive_enabled=progressive_enabled, initial_read_reference=initial_read_reference, - page_bytes=page_bytes, output_bytes=output_bytes, page_attached=page_attached, reader_argv=reader_argv) + page_bytes=page_bytes, output_bytes=output_bytes, page_attached=page_attached, + first_read_requested=stateless_first_read, reader_argv=reader_argv) if typed and mode == "delta": result = None From 775394bd8d9f164ff9a2283044a4c9d3ab158732 Mon Sep 17 00:00:00 2001 From: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> Date: Sun, 8 Nov 2026 00:10:47 +0800 Subject: [PATCH 4/4] Preserve the early initial-read command diagnostic Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com> --- loopx/cli_commands/quota_capture.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/loopx/cli_commands/quota_capture.py b/loopx/cli_commands/quota_capture.py index f98502c622..6bf05bd3e1 100644 --- a/loopx/cli_commands/quota_capture.py +++ b/loopx/cli_commands/quota_capture.py @@ -1191,7 +1191,8 @@ def handle_native_context_command(args: argparse.Namespace, *, print_payload: Ca registry_path: Path | None = None, runtime_root_arg: str | None = None) -> int | None: """Dispatch native presentation/lifecycle IO before any quota authority read.""" if getattr(args, "initial_read", False) and args.quota_command not in ("context-read", "context-project"): - print_payload({"ok": False, "reason": "--initial-read requires context-read or JSON context-project"}, args.format, str) + print_payload({"ok": False, "reason": "--initial-read is only supported by context-read or JSON context-project"}, + args.format, str) return 1 list_depth = getattr(args, "list_depth", None) if list_depth is not None and (args.quota_command != "context-read" or not getattr(args, "list_fields", False)