Skip to content
28 changes: 22 additions & 6 deletions benchmark/runtime/checkpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import json
import math
import subprocess
import tempfile
import time
from contextlib import ExitStack, contextmanager
from pathlib import Path, PurePosixPath
Expand Down Expand Up @@ -137,24 +138,39 @@ def capture_before_replan(env: dict[str, str], receipt: dict[str, Any], body: st
raise ValueError("fresh_replan checkpoint trigger requires a heartbeat execute wake")
started = time.monotonic()
guard_path = Path(env["LOOPX_WAKE_LOG_DIR"]) / receipt["turn_id"] / "checkpoint-start-guard.json"
command = [env["LOOPX_CLI"], "--format", "json", "--registry", env["LOOPX_REGISTRY"],
# Use the CLI's original-decision capture, including with TurnEnvelope off.
# The checkpoint selector needs the full source; the model consumes the
# ordinary CLI projection of those same bytes, never a second guard.
capture_root = Path(tempfile.mkdtemp(prefix="checkpoint-start-", dir=guard_path.parent))
command = [env["LOOPX_CLI"], "--cli-bin", env["LOOPX_CLI"], "--format", "json", "--registry", env["LOOPX_REGISTRY"],
"--runtime-root", env["LOOPX_RUNTIME_ROOT"], "quota", "should-run",
"--goal-id", env["LOOPX_GOAL_ID"], "--agent-id", env["LOOPX_AGENT_ID"],
"--runtime-profile", "generic_cli", "--turn-instance-id", receipt["turn_id"],
"--available-capability", "shell", "--available-capability", "filesystem_write"]
"--available-capability", "shell", "--available-capability", "filesystem_write",
"--decision-output-root", str(capture_root)]
guard_run = subprocess.run(command, cwd=env["LOOPX_PROJECT"], env=env, capture_output=True,
text=True, timeout=120, check=True)
guard = json.loads(guard_run.stdout)
if not isinstance(guard, dict) or guard.get("ok") is not True:
projected = json.loads(guard_run.stdout)
captures = list(capture_root.glob("decision-*/decision.json"))
if len(captures) != 1:
raise ValueError("checkpoint requires exactly one captured original quota decision; do not replay the guard")
raw_guard = captures[0].read_bytes()
guard = json.loads(raw_guard)
if (not isinstance(guard, dict) or guard.get("ok") is not True or
not isinstance(projected, dict) or projected.get("ok") is not True):
raise ValueError("checkpoint requires a successful original quota guard")
# A previous preflight on this wake may already have allowed model work,
# even if its optional attempt marker (or final receipt) could not be saved.
# Such reentry can verify an existing point, but cannot capture a later one.
preflight_seen = guard_path.exists()
guard_path.write_text(guard_run.stdout, encoding="utf-8")
guard_path.write_bytes(raw_guard)
guard_path.chmod(0o600)
view_path = guard_path.with_name("checkpoint-start-view.json")
view_path.write_text(guard_run.stdout, encoding="utf-8")
view_path.chmod(0o600)
preloaded_body = (f"Host checkpoint preflight has already executed this wake's original quota guard once. "
f"Read the complete packet at {guard_path} before work, then follow its interaction_contract. "
f"Read the complete CLI view at {view_path} before work, then follow its interaction_contract "
"and replan review/writeback reads when present. "
"Do not repeat the initial guard below; use its selection or recovery command when required.\n\n" + body)
receipt["checkpoint"] = {"captured": False, "research_point_qualified": False, "phase": "before_replan"}
try:
Expand Down
8 changes: 7 additions & 1 deletion benchmark/tests/test_checkpoint_handoff.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,13 @@ def test_preflight_defers_history_only_when_capture_will_verify_it(tmp_path, mon
request.write_text(json.dumps({"destination": str(tmp_path / "checkpoints"),
"trigger": "fresh_replan", "native_session": native_participant,
"components": [{"id": "code", "source_path": str(tmp_path / "code")}], "point_metadata": {}}))
monkeypatch.setattr(checkpoint.subprocess, "run", lambda *a, **k: SimpleNamespace(stdout=json.dumps({"ok": True})))
def guard(command, **kwargs):
from pathlib import Path
captured = Path(command[command.index("--decision-output-root") + 1]) / "decision-original"
captured.mkdir()
(captured / "decision.json").write_text(json.dumps({"ok": True}))
return SimpleNamespace(stdout=json.dumps({"ok": True}))
monkeypatch.setattr(checkpoint.subprocess, "run", guard)
monkeypatch.setattr(checkpoint, "effect_runtime_result", lambda *a, **k: {"capture": False, "reason": "no_fresh_replan"})
observed = []
def gate(*args, full_history):
Expand Down
24 changes: 20 additions & 4 deletions docs/architecture/rfcs/hierarchical-agent-stride-control-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -762,17 +762,33 @@ these facts do not change the admitted context/basis identity. Changed source
requires rereading within the original Turn. Page coordinates persist with the
decision into subsequent review; node-filtered/planner detail routes remain
outside this bounded citation path. No separate receipt store is introduced.
The enabled review also carries the prior decision's existing `todo_delta`
The replan context also carries the prior decision's existing `todo_delta`
targets in `decision_followthrough.planned_work`: current canonical status and
claim, plus references to causally later observations of that exact work item.
Legacy descriptive Todo deltas remain readable with unresolved linkage; an
overlong reference is never truncated into a different Todo identity.
Missing Todo sources and omitted work remain explicit; a missing observation
does not prove non-execution, and Todo completion does not prove objective gain.
Related observations survive unrelated recent activity in the bounded window.
The same bounded followthrough is included in `stride_control` so compact Host
envelopes expose it without requiring another full-context read. Historical
decision identities and off-mode output remain unchanged.
Generic followthrough is available with stride off as well: `result_counts`
separates advanced, unchanged, blocked and terminal observations, while visible
rows retain their result class and delivery outcome. The compatibility
`recorded_progress_count` is an observation count, never successful work.
Historical decision identities and stride admission/settlement gates remain
unchanged; off-mode context now includes this feedback without enabling stride.

The [captured replan reader](../../reference/protocols/turn-envelope-v0.md#captured-replan-reads--捕获后的重规划读取)
separates state review from authoring on one immutable decision snapshot.
Cumulative acceptance uses lossless content-bound detail reads, and Explore
receives a separate context increment. Existing uncaptured callers retain their
full delivery. File/SQLite source tests and populated packet budgets qualify
transport and writer continuity; installed adoption, real model decisions and
matched outcome/cost benefit remain unqualified. This introduces no new planning
receipt, model checkpoint or requirement to change direction.
The reader replaces repeated method guidance with compact semantic boundaries
and the existing stride format. Benchmark preflight captures the original
decision through the CLI and delivers its staged view even with TurnEnvelope
off; retaining a full checkpoint packet alone does not qualify model exposure.

The next-review input also exposes causally later ordinary writebacks for the
declared work in `ordinary_work`, with per-Todo `ordinary_evidence_refs`. Its
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -632,14 +632,25 @@ revision、考虑的 finding 与适用/暂缓等理由,不建新图或第二
拒绝缺少复盘、错误引用以及过期或不可用依据的错误声明,校验提案结构和来源,
不能证明研究已执行或有收益。

启用策略后,`decision_followthrough.planned_work` 将上次决定中既有 `todo_delta`
replan context 中的 `decision_followthrough.planned_work` 将上次决定中既有 `todo_delta`
指向的 Todo 与当前规范状态、认领人和该工作项在决定之后的观测引用一起返回。
Todo 来源缺失和省略数量明确保留;缺少观测不等于没有执行,Todo 完成也不等于
目标收益。历史描述性 Todo delta 保持可读并注明关联未解析;过长引用不会截断成
另一个 Todo 的身份。相关观测不会被大量较新的无关活动挤出有限窗口。
同一份有界反馈进入
`stride_control`,紧凑 Host envelope 可直接消费,避免为这些信息再读完整上下文。
历史决定的引用身份及 off 模式输出不变。
通用执行回顾在 stride 关闭时也可读取:`result_counts` 区分推进、未变、阻塞和
终态观测,明细保留结果分类及交付结果。兼容字段 `recorded_progress_count` 表示
观测数量,不表示成功工作。历史决定引用及 stride 准入/结算门禁不变;off 模式
新增反馈上下文,但不启用 stride。

[捕获后的重规划读取](../../reference/protocols/turn-envelope-v0.md#captured-replan-reads--捕获后的重规划读取)
把状态审视和写回格式分开,复用同一不可变决策快照。累计验收通过内容绑定的明细
读取完整保留,Explore 使用独立的上下文增量预算;未捕获快照的调用仍完整投递。
File/SQLite 源码测试和真实规模 packet 预算验证传输与写回连续性;已安装采用、真实
模型决策及可比成果/成本收益仍待资格化。不新增规划回执、模型 checkpoint 或强制
改变方向的要求。
读取入口用精简的语义边界和既有 stride 格式替换重复方法指导。benchmark 前置检查
通过 CLI 捕获原决定,在 TurnEnvelope 关闭时也交付分段视图;仅保留完整 checkpoint
源包不能证明模型实际收到了实验处理。

下一轮输入还通过 `ordinary_work` 与各 Todo 的 `ordinary_evidence_refs` 返回已
声明工作在决定之后的普通回写。详情最多六项,保留总数、省略数和稳定 history
Expand Down
107 changes: 107 additions & 0 deletions docs/reference/protocols/turn-envelope-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,113 @@ CLI from becoming another reader of the legacy guidance field.
事实仍在当前包内,不需再次执行 guard。不同副本和既有详细视图保留;原始决定与
capture 不变。动作维度等价不意味着不同渲染可以共用原始 source hash。

### Captured replan reads / 捕获后的重规划读取

For a successful replan with `--decision-output-dir` or `--decision-output-root`,
the CLI and TurnEnvelope expose `replan_action_packet.review` followed by
`writeback`. Both are executable `quota replan-view` commands bound to the same
captured JSON value and source hash. The first read supplies goal context,
previous decision/results, planning dependencies and evidence references; the
second supplies the existing authoring shape and settlement commands. No read
runs another guard, writes a receipt or authorizes work. There is no additional
read acknowledgement, mandatory model call or prescribed route change.

Captured reads retain the caller's explicit `--cli-bin` route, including later
acceptance and Explore reads; an ambient executable cannot silently replace it.
The review stage provides structured facts without a prescribed diagnostic
method. Writeback omits filled-in Vision/stride examples while retaining field
limits, legal options, source bindings and settlement rules. Stride exposes its
required field names and basis options independently of examples. The unchanged
full capture remains available for optional examples and source inspection.
This intentionally reduces advisory prompting; it does not remove acceptance,
authority or stop obligations, nor demonstrate better autonomous decisions.

Cumulative outcome requirements are indexed by exact content hash. Every
objective, revision and requirement count remains visible; the acceptance read
returns the complete original outcome. Identical IDs with different revisions
or evidence remain distinct. Equal context/horizon copies share references;
differing goal scopes remain separate. The full capture retains all evidence,
original guidance and authoring examples. Explore has an optional, separately
readable basis; unavailable evidence remains unavailable. These views do not
assess acceptance, infer execution from counts or make a dependency global.

`quota replan-view --decision-file <file> --source-hash <hash>` defaults to
`--replan-stage review`; `writeback`, `acceptance --outcome-ref <ref>` and
`explore` read the corresponding original-source detail. Missing/mutated sources
fail without guard replay. Existing uncaptured calls and native journal captures
without the CLI read route retain their prior delivery. The existing generic
followthrough is now available with stride off; its result-class counts and
observations remain evidence, not successful-work or goal-gain verdicts.

Live decisions replace the previous method checklist and duplicate stride
planning advice with compact goal, evidence and authority boundaries. Review
delivers those boundaries once, with the facts; writeback delivers the existing
format. Eligible Todo order and agent-proposed candidate rules remain revisable
planning choices, while original priorities, constraints, budgets and stops
remain binding. Old captures retain their original text. This is an intentional
change to advisory prompting, not a lossless claim about model behavior.

The benchmark checkpoint preflight uses the same CLI decision capture with
TurnEnvelope off. It retains the complete captured source for checkpoint
selection and verification, and sends the projected CLI view to the model.
The view's review/writeback commands read that exact observation; capture does
not rerun admission, change evaluation opportunities or select a strategy.
Identical work-context acceptance copies use that same read; other revisions
stay inline. A source exceeding the RPC request bound uses the existing bounded
local-snapshot transport for pure projection, preserving both transport limits.

对使用 `--decision-output-dir` 或 `--decision-output-root` 的成功 replan,CLI 和
TurnEnvelope 先给出 `review` 状态读取,再给出 `writeback` 格式读取。两步绑定同一
快照和来源哈希,不重新准入、不新增回执或授权,也不强制换路线。累计验收按完整
内容哈希建立索引:每个目标、版本及要求数量可见,明细完整读回;相同 ID 的不同
版本不会覆盖。相同的目标上下文副本共享引用,不同范围保留。Explore 明细单独按需
读取;不可用保持不可用。完整快照仍保存原指导、示例和证据。没有捕获或没有 CLI
读取路径的原生 journal 保持原交付方式。通用执行回顾不再依赖 stride 开关;分类
计数只表示观测,不等于工作成功或目标收益。

捕获后的读取沿用调用方显式选择的 `--cli-bin`,后续验收和 Explore 读取也不会
悄悄切换到环境中的其他版本。复盘视图提供结构化事实,不预设诊断方法;写回视图
移除预填的 Vision/stride 答案示例,保留字段限制、合法选项、来源绑定和结算规则。
stride 的必需字段与 basis 选项独立展示,完整快照仍可用于按需查看示例与源材料。
这是有意减少建议性提示,不删除验收、权限或停止义务,也不证明自主决策质量提升。

新决定用精简的目标、证据和权限边界替换原方法清单及重复的 stride 规划建议:复盘
一次交付这些边界与事实,写回提供既有格式。可执行 Todo 的次序和 agent 自拟候选
规则可以调整,原有优先目标、硬约束、预算与停止仍须保留。旧快照保留原文;这是
有意改变建议性提示,不能称为对模型行为无损。benchmark checkpoint 前置检查也
使用同一 CLI 捕获入口,TurnEnvelope 关闭仍生效:完整源包供 checkpoint 选择和
校验,模型读取投影视图,再从同一观察分段读取。不重复准入、不改变评测机会,
也不替 agent 选择策略。
work context 中完全相同的验收副本复用该读取,不同版本保留。超过 RPC 请求限额的
完整源包用既有有界本地快照传输做纯投影;两种传输限额均不放宽。

Regression budgets use compact UTF-8 JSON, separately from compute quota and
provider tokens. The synthetic workload uses a real append index with 1,500
records, 21 later observations, 24 cumulative outcomes and a populated Explore
log. Limits protect default input while exact details remain readable:

| View | Regression allocation |
| --- | --- |
| Replan entry packet | 2 KiB |
| Populated history review | 16 KiB |
| Planning inventory increment | 8 KiB |
| Cumulative acceptance index increment | 12 KiB |
| Explore increment in entry / review | 128 B / 768 B |
| Explore detail / writeback | 8 KiB / 16 KiB |

The whole-envelope differential also prevents a large acceptance copy moving to
another hot carrier. These are fixture regression allocations, not runtime
truncation or refusal limits; the existing 8 KiB envelope warning remains.
File/SQLite CLI tests cover capture → reads → existing writeback, hash rejection
and unchanged state during reads. They do not establish model choice quality,
installed adoption, token savings or matched long-horizon benefit.

大小回归使用紧凑 UTF-8 JSON,与算力 quota 和 provider token 分开。通用 review、
累计验收索引和 Explore 分别约束增量,同时检查整个 envelope,防止把大副本挪到
另一处热输入。预算不在运行时截断或拒绝合法内容,原 8 KiB envelope 警告保留。
File/SQLite CLI 验证快照、分步读取、既有写回和哈希拒绝,不据此宣称模型决策、
已安装采用、token 节省或长程收益改善。

### Native Turn Host capture

Executing `turn run-once --execute` now saves the original full decision before
Expand Down
Loading
Loading