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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/reference/protocols/goal-vision-replan-contract-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -1086,6 +1086,12 @@ in its durable-writeback step, the replan contract uses a same-response
Different schemas remain separate, and progress-only replan does not acquire a
Vision requirement. TurnEnvelope preserves the ordinary plan's guidance.

`checkpoint_context_not_missing` is an inapplicable recovery, not a request to
repeat that read. Its `reread_required` is false. Preserve the committed writeback
and quota receipt; inspect later authorized work through the normal guard with
a fresh Turn identity. A stale, missing or replaced read receipt still requires
the original scoped reread. Neither rejection grants execution or completion.

Shared `todo plan` and guided-start authoring steps also provide a routed exact
readback command for each authored or reused Todo id. Inventory text is a bounded
excerpt. Verify `todo_detail_projection.source_complete=true`, compare `.todo.text`
Expand All @@ -1103,6 +1109,11 @@ Turn 写回后的恢复。规划与接续指引提供逐条精确读回命令,
需求和当前状态,不能拿列表摘要判断正文丢失。读取不授予执行权限;准入、租约、
恢复和单次记账规则保持不变。包体增量与模型效率、效果收益须分别测量。

`checkpoint_context_not_missing` 表示这条恢复路径不适用,`reread_required=false`,
不应重复同一读取。保留已提交写回与记账回执;后续获授权的工作通过正常 guard 和新
Turn 身份检查。陈旧、缺失或被替换的读取回执仍须按原范围重读。拒绝不授予执行或
完成权限。

A satisfied checkpoint is protocol-complete, but a material closeout also has
to qualify its relationship to the final outcome. A patched checkpoint must
name the active `acceptance_summary`, attach public-safe
Expand Down
9 changes: 7 additions & 2 deletions loopx/control_plane/goals/checkpoint_read_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,13 @@ function snapshot(request: JsonObject): JsonObject {
}

const rejected = (code: string, changed: string[] = []): JsonObject => ({
ok: false, error_code: code, reread_required: true, changed_components: changed,
error: `${code}: run checkpoint-context for the same Goal/Agent/Todo or obligation/Turn, ` +
ok: false, error_code: code, reread_required: code !== "checkpoint_context_not_missing", changed_components: changed,
error: code === "checkpoint_context_not_missing"
? `${code}: this committed writeback has no missing checkpoint for this recovery. ` +
"Preserve the committed writeback and quota receipt; do not repeat this recovery or quota spend. " +
"For later authorized work, inspect current state through the normal guard with a fresh Turn identity. " +
"This rejection grants no work or completion authority."
: `${code}: run checkpoint-context for the same Goal/Agent/Todo or obligation/Turn, ` +
"read the returned state and judge again; submit its --checkpoint-read-context with only the vision decision. " +
"Do not repeat implementation, state mutations, or quota spend.",
});
Expand Down
5 changes: 5 additions & 0 deletions tests/control_plane/test_checkpoint_read_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ def test_missing_replaced_stale_context_requires_reread_and_preserves_delivery(t
assert rc == 0 and result["appended"] and result["vision_checkpoint"]["satisfied"], result
assert result["vision_checkpoint"]["read_context"]["read_context_id"] == fresh["read_context_id"]
after = index.read_bytes()
rc, inapplicable = _run_cli(registry, runtime, "checkpoint-context", *binding, cwd=project)
assert rc == 1 and inapplicable["error_code"] == "checkpoint_context_not_missing", inapplicable
assert inapplicable["checkpoint_read_context"]["reread_required"] is False
assert "normal guard" in inapplicable["error"]
assert index.read_bytes() == after, "an inapplicable recovery must not append another receipt"
state.write_text(state.read_text(encoding="utf-8") + "\n## Acceptance\n\nNew acceptance after commit.\n", encoding="utf-8")
rc, replay = _run_cli(registry, runtime, *supplement, cwd=project)
assert rc == 0 and replay["idempotent_replay"] and not replay["appended"], replay
Expand Down
13 changes: 13 additions & 0 deletions tests/control_plane_ts/checkpoint_read_context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ test("read captures the exact task, transitive upstream results and goal accepta
assert.equal(check(result.receipt).ok, true);
});

test("an inapplicable recovery does not direct the caller to repeat the same read", () => {
const result = read({prior: {vision_checkpoint: {
decision: "unchanged_with_reason", satisfied: true, delivery_boundary: "in_flight_continuation",
}}, writeback_committed: true, quota_spend_committed: true});
assert.equal(result.ok, false);
assert.equal(result.error_code, "checkpoint_context_not_missing");
assert.equal(result.reread_required, false);
assert.doesNotMatch(String(result.error), /run checkpoint-context/);
assert.match(String(result.error), /normal guard/);
const missing = check(undefined);
assert.equal(missing.reread_required, true, "a genuinely missing receipt still requires reread");
});

test("an unqualified blocked replan needs the exact committed source and no debit before reread", () => {
const bound = settlementIdentity({goal_id: "goal", agent_id: "agent", turn_instance_id: "turn",
replan_obligation_id: "replan-1111111111111111"});
Expand Down
Loading