Repository navigation
Preserve same-Turn Todo selection after quota preflight #8275
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
1881122
abb6760
0b44811
3ade877
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -421,9 +421,11 @@ def test_preflight_instruction_pins_both_projection_and_full_fallback(tmp_path): | |
|
|
||
|
|
||
| @pytest.mark.parametrize("provider", ["file", "sqlite"]) | ||
| @pytest.mark.parametrize("enabled,compacted", [(False, False), (True, False), (True, True)], | ||
| ids=["off", "on", "on-after-compaction"]) | ||
| def test_checkpoint_preflight_selection_inherits_native_transport(tmp_path, monkeypatch, provider, enabled, compacted): | ||
| @pytest.mark.parametrize("enabled,compacted,placement", [ | ||
| (False, False, "physical"), (True, False, "physical"), (True, True, "physical"), | ||
| (True, False, "alias-before-session"), (True, False, "explicit-root"), | ||
| ], ids=["off", "on", "on-after-compaction", "alias-before-session", "explicit-root"]) | ||
| def test_checkpoint_preflight_selection_inherits_native_transport(tmp_path, monkeypatch, provider, enabled, compacted, placement): | ||
| """The saved guard is presented after SessionStart, then really bound once.""" | ||
| from benchmark.runtime.checkpoint import capture_before_replan | ||
| from canonical_authority_fixture import initialize_canonical_authority, isolate_sqlite_runtime, read_fixture_todos | ||
|
|
@@ -434,9 +436,18 @@ def test_checkpoint_preflight_selection_inherits_native_transport(tmp_path, monk | |
| _heartbeat_receipt_count, _spend_run_count, _write_fixture, | ||
| ) | ||
|
|
||
| import subprocess | ||
|
|
||
| tmp_path = tmp_path.resolve() | ||
| isolate_sqlite_runtime(tmp_path, monkeypatch) | ||
| project, runtime, registry = _write_fixture(tmp_path / "authority") | ||
| _configure_selectable_alternative(project) | ||
| if enabled and placement == "physical": | ||
| # Keep an actual delta positive: the bound view preserves 0.5's spelling. | ||
| # A 1.0 -> 1 transition requires full recovery even within the same epoch. | ||
| registry_data = json.loads(registry.read_bytes()) | ||
| registry_data["goals"][0]["quota"]["compute"] = 0.5 # The fixture still declares two slots. | ||
| registry.write_text(json.dumps(registry_data)) | ||
| state = project / f".codex/goals/{GOAL_ID}/ACTIVE_GOAL_STATE.md" | ||
| initialize_canonical_authority(runtime, GOAL_ID, | ||
| build_todo_runtime_shadow_projection(goal_id=GOAL_ID, todos=read_fixture_todos(state), handoff_mode="soft_claim"), | ||
|
|
@@ -462,24 +473,48 @@ def test_checkpoint_preflight_selection_inherits_native_transport(tmp_path, monk | |
| "LOOPX_CONTEXT_DELIVERY": "on" if enabled else "off", "LOOPX_CODEX_CONTEXT_DIR": str(native)} | ||
| env.pop("CODEX_THREAD_ID", None) | ||
| receipt = {"turn_id": turn, "mode": "heartbeat", "stage": "execute"} | ||
| body = capture_before_replan(env, receipt, "Current work.") | ||
| alias = tmp_path / "capture parent alias" | ||
| if placement != "physical": | ||
| run = subprocess.run | ||
|
|
||
| def through_alias(argv, **kwargs): | ||
| if "--prepared-capture-reference" in argv: | ||
| argv = list(argv) | ||
| i = argv.index("--decision-output-dir") + 1 | ||
| requested = Path(argv[i]) | ||
| alias.symlink_to(requested.parent, target_is_directory=True) | ||
| argv[i] = str(alias / requested.name) | ||
| return run(argv, **kwargs) | ||
|
|
||
| # Change only how the CLI reaches the directory already allocated by | ||
| # the checkpoint runner. Guard, capture, projection and selection are real. | ||
| with monkeypatch.context() as scoped: | ||
| scoped.setattr("benchmark.runtime.checkpoint.subprocess.run", through_alias) | ||
| body = capture_before_replan(env, receipt, "Current work.") | ||
| else: | ||
| body = capture_before_replan(env, receipt, "Current work.") | ||
| original_guard = (wake / "checkpoint-start-guard.json").read_bytes() | ||
| if enabled: | ||
| command = shlex.split(body.split("```sh\n", 1)[1].split("\n```", 1)[0]) | ||
| source = Path(command[command.index("--capture-file") + 1]) | ||
| assert source.parent != wake and source.is_relative_to(wake) | ||
| assert command[command.index("--capture-sha256") + 1] == hashlib.sha256(source.read_bytes()).hexdigest() | ||
| if placement != "physical": | ||
| command[command.index("--capture-file") + 1] = str(alias / source.relative_to(source.parent.parent)) | ||
| else: | ||
| source = wake / "checkpoint-start-view.json" | ||
| raw = source.read_bytes() | ||
| assert _heartbeat_receipt_count(runtime, turn) == 1 and _spend_run_count(runtime) == 0 | ||
| assert not list(native.iterdir()) # Host preflight must not publish before native SessionStart. | ||
|
|
||
| event = {"session_id": "native-session", "cwd": str(project), "hook_event_name": "SessionStart", "source": "startup"} | ||
| monkeypatch.setenv("CODEX_THREAD_ID", event["session_id"]) | ||
| lifecycle = enabled and placement != "alias-before-session" | ||
| monkeypatch.chdir(project) | ||
| if enabled: | ||
| if lifecycle: | ||
| monkeypatch.setenv("CODEX_THREAD_ID", event["session_id"]) | ||
| codex_context_hook(str(native), event) | ||
| else: | ||
| monkeypatch.delenv("CODEX_THREAD_ID", raising=False) | ||
|
|
||
| def consume(wire): | ||
| data = bytearray() | ||
|
|
@@ -489,7 +524,8 @@ def consume(wire): | |
| while True: | ||
| assert page["ok"] and page["offset"] == len(data) | ||
| data.extend(page["content"].encode()) | ||
| codex_context_hook(str(native), {**event, "hook_event_name": "PostToolUse", "tool_response": json.dumps(page)}) | ||
| if lifecycle: | ||
| codex_context_hook(str(native), {**event, "hook_event_name": "PostToolUse", "tool_response": json.dumps(page)}) | ||
| if page["eof"]: | ||
| assert hashlib.sha256(data).hexdigest() == machine_reference_oracle(wire)["sha256"] | ||
| return json.loads(data) | ||
|
|
@@ -499,6 +535,11 @@ def consume(wire): | |
|
|
||
| if enabled: | ||
| command.extend(("--max-page-output-bytes", "32000")) | ||
| expected_root = source.parent.parent | ||
| if placement == "explicit-root": | ||
| expected_root = tmp_path / "explicit capture root" | ||
| expected_root.mkdir(mode=0o700) | ||
| command.extend(("--decision-output-root", str(expected_root))) | ||
| rc, cold = _run_cli(registry, runtime, *command[command.index("quota"):], cwd=project) | ||
| assert rc == 0 and cold["navigation"]["mode"] == "full" and cold["offset"] == 0, cold | ||
| assert len(json.dumps(cold, ensure_ascii=False, separators=(",", ":")).encode()) + 1 <= 32000 | ||
|
|
@@ -513,16 +554,41 @@ def consume(wire): | |
| parsed = build_parser().parse_args(argv[1:]) | ||
| assert (parsed.context_delivery == "on") is enabled | ||
| assert parsed.codex_context_dir == (str(native) if enabled else None) | ||
| assert parsed.max_page_output_bytes == (32000 if enabled else None) | ||
| assert parsed.max_page_output_bytes == (32000 if lifecycle else None) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P2] Preserve explicit selection transport before SessionStart SessionStart 前,给 context-project 一个不同且已存在的私有 --decision-output-root 和 8,000 字节上限。File 和 SQLite 的当前 head 都把新捕获写到了原捕获旁,指定目录没有生成捕获。实际首读返回 12,000 字节。上一个 PR head 写到指定目录并返回 8,000 字节;当前主干已丢失两个参数,但不会在原捕获旁落盘。 通过现有选择命令合成路径,在 SessionStart 前的 full 结果也绑定当前显式根和输出上限。已保存的物理根仅作默认值,原文件和 SHA 保持可读。如果当前投递无法兑现显式选项,返回清楚的恢复状态。补上两种后端在 SessionStart 前的显式选项用例,实际运行选择和首读,断言落盘位置、字节、回执与原身份。 |
||
| assert argv.count("--decision-output-root") == 1 | ||
| if placement == "alias-before-session": | ||
| rejected_argv = argv.copy() | ||
| rejected_argv[rejected_argv.index("--decision-output-root") + 1] = str(alias) | ||
| rc, rejected = _run_cli(registry, runtime, *rejected_argv[1:], cwd=project) | ||
| assert rc == 1 and "no guard was run" in rejected["reason"], rejected | ||
| assert list(expected_root.glob("*/decision.json")) == [source] | ||
| assert _heartbeat_receipt_count(runtime, turn) == 1 | ||
| rc, bound = _run_cli(registry, runtime, *argv[1:], cwd=project) | ||
| assert rc == 0, bound | ||
| if enabled: | ||
| assert bound["mode"] == ("full" if compacted else "delta"), bound | ||
| assert len(json.dumps(bound, ensure_ascii=False, separators=(",", ":")).encode()) + 1 <= 32000 | ||
| delivered = consume(bound) | ||
| if not compacted: | ||
| assert delivered["base"]["capture_id"] == machine_reference_oracle(cold["navigation"])["target"]["capture_id"] | ||
| assert Path(parsed.decision_output_root) == expected_root | ||
| [selected_capture] = set(expected_root.glob("*/decision.json")) - {source} | ||
| digest = machine_reference_oracle(bound)["capture_sha256"] | ||
| rc, page = _run_cli(registry, runtime, "quota", "context-read", "--capture-file", str(selected_capture), | ||
| "--capture-sha256", digest, "--select", "/heartbeat_receipt/settlement_identity", cwd=project) | ||
| assert rc == 0 and page["eof"], page | ||
| [identity] = json.loads(page["content"])["selections"] | ||
| selected_receipt = identity["value"] | ||
| assert (selected_receipt["goal_id"], selected_receipt["agent_id"], selected_receipt["turn_instance_id"], | ||
| selected_receipt["todo_id"]) == (GOAL_ID, AGENT_ID, turn, TODO_ID) | ||
| if placement == "explicit-root": | ||
| assert list(source.parent.parent.glob("*/decision.json")) == [source] | ||
| if lifecycle: | ||
| expected_mode = "full" if compacted or placement == "explicit-root" else "delta" | ||
| assert bound["mode"] == expected_mode, bound | ||
| assert len(json.dumps(bound, ensure_ascii=False, separators=(",", ":")).encode()) + 1 <= 32000 | ||
| delivered = consume(bound) | ||
| if expected_mode == "delta": | ||
| assert delivered["base"]["capture_id"] == machine_reference_oracle(cold["navigation"])["target"]["capture_id"] | ||
| if placement == "explicit-root": | ||
| assert type(presented["quota"]["compute"]) is float | ||
| assert type(delivered["quota"]["compute"]) is int | ||
| assert delivered["quota"]["compute"] == presented["quota"]["compute"] == 1 | ||
| else: | ||
| assert bound["mode"] == "should-run" and not list(native.iterdir()) | ||
| assert _heartbeat_receipt_count(runtime, turn) == 2 and _spend_run_count(runtime) == 0 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P2] 原 prepared capture 接受父目录别名,但这里把逻辑路径转成 --decision-output-root。File 和 SQLite 中,同一 context-project 在基线可继续选择,当前 head 返回 1 且 guard 未运行,新 capture 为零。请保留原选择与不可变文件,传经验证的物理父目录,再跑物理目录和别名对照。