Skip to content

Commit 4d280ba

Browse files
committed
test(acceptance): complete and settle the restored managed Turn once
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
1 parent d32a5d1 commit 4d280ba

3 files changed

Lines changed: 35 additions & 4 deletions

File tree

‎docs/architecture/rfcs/ledger/shared-goal-authority-state-provider-v0/2026-09-24-exact-acceptance-restoration.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ This advances native long-horizon recovery, not provider default selection or
2020
D3 promotion. Real File/SQLite CLI regressions exercise acquire, stale edit,
2121
release, rejected reacquire, restoration and fresh acquire; provider tests also
2222
exercise a disposable PostgreSQL server. Managed frontier projection drops the
23-
stale hold after restoration. #5000 remains separately owned by Turn settlement
23+
stale hold after restoration. The original managed Turn then completes its Todo,
24+
writes back and settles; replaying restoration and spend consumes quota once.
25+
#5000 remains separately owned by Turn settlement
2426
and its retry policy; restoring acceptance does not settle a Turn.
2527

2628
See the [caller contract](../../../../reference/goal-acceptance-observations.md#restore-an-unintended-textwait-edit-after-lease-release).

‎docs/architecture/rfcs/ledger/shared-goal-authority-state-provider-v0/2026-09-24-exact-acceptance-restoration.zh-CN.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414

1515
此项推进原生长程恢复,不改变默认 provider 或 D3 晋升结论。真实 File/SQLite CLI
1616
覆盖获取租约、误改、释放、拒绝重取、恢复、再次获取;provider 用例还覆盖隔离的
17-
真实 PostgreSQL。恢复后 managed frontier 不再投影 stale hold。#5000 的 Turn
17+
真实 PostgreSQL。恢复后 managed frontier 不再投影 stale hold;原 managed Turn 随后完成 Todo、写回与结算,重复恢复和结算只消费一次
18+
配额。#5000 的 Turn
1819
结算及重试策略仍属独立边界;恢复验收声明不等于结算 Turn。
1920

2021
参见[调用方合同](../../../../reference/goal-acceptance-observations.md#restore-an-unintended-textwait-edit-after-lease-release)。

‎tests/control_plane/test_acceptance_restoration.py‎

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,19 @@ def test_cli_restore_then_reacquire_preserves_acceptance_and_exact_retry(tmp_pat
1919
isolate_sqlite_runtime(tmp_path, monkeypatch)
2020
runtime, state, registry = tmp_path / "runtime", tmp_path / "state.md", tmp_path / "registry.json"
2121
goal, target = "acceptance-restoration", "todo_artifact"
22-
state.write_text("# Goal\n\n## Agent Todo\n")
22+
state.write_text("---\nstatus: active-read-only\nowner_mode: goal\nobjective: Validate a bounded artifact\n---\n# Goal\n\n## Agent Todo\n")
2323
registry.write_text(json.dumps({"common_runtime_root": str(runtime), "goals": [{
2424
"id": goal, "repo": str(tmp_path), "state_file": state.name,
25+
"domain": "acceptance-restoration", "status": "active-read-only",
26+
"adapter": {"kind": "read_only_project_map_v0", "status": "connected-read-only"},
27+
"quota": {"compute": 1.0, "window_hours": 24, "allowed_slots": 2},
2528
"coordination": {"registered_agents": ["agent-a", "agent-b"]},
2629
}]}))
2730
wait = "resume_at:2020-01-01T00:00:00Z"
2831
todo = {"schema_version": "todo_item_v0", "todo_id": target, "role": "agent", "status": "open",
2932
"done": False, "text": "Deliver the artifact", "archive_state": "active",
3033
"source_section": "Agent Todo", "index": 1, "task_class": "advancement_task",
31-
"claimed_by": "agent-a", "resume_when": wait}
34+
"claimed_by": "agent-a", "resume_when": wait, "action_kind": "validate"}
3235
projection = build_todo_runtime_shadow_projection(goal_id=goal, handoff_mode="hard_lease", todos=[todo])
3336
initialize_canonical_authority(runtime, goal, projection, state_path=state, provider=provider)
3437
document = tmp_path / "acceptance.json"
@@ -56,6 +59,10 @@ def inspect():
5659
lease_args = ["--todo-id", target, "--owner", "agent-a", "--idempotency-key", "execution-one"]
5760
first = cli("task-lease", "acquire", *lease_args, "--expected-version", "0", "--ttl-seconds", "600")
5861
assert first["acquired"]
62+
turn_binding = ["--agent-id", "agent-a", "--todo-id", target,
63+
"--turn-instance-id", "turn-restore-acceptance"]
64+
guard = cli("quota", "should-run", "--codex-app", *turn_binding, "--scan-path", str(tmp_path))
65+
assert guard["heartbeat_receipt"]["settlement_identity"]["todo_id"] == target
5966
cli("todo", "update", "--todo-id", target, "--agent-id", "agent-a", "--clear-resume-when",
6067
"--task-lease-idempotency-key", "execution-one", "--task-lease-expected-version", "1")
6168
assert inspect()["goal_acceptance_contract"]["tasks"][0]["state"] == "stale"
@@ -97,3 +104,24 @@ def turn_holds():
97104
assert inspect() == after_acquire
98105
assert cli("task-lease", "inspect", "--todo-id", target)["lease"] == next_lease["lease"]
99106
assert cli("todo", "list")["todos"][0]["status"] == "open"
107+
108+
completed = cli("todo", "complete", *turn_binding, "--task-lease-idempotency-key", "execution-two",
109+
"--task-lease-expected-version", "2", "--evidence", "fixture:restoration-check",
110+
"--next-agent-todo", "Validate the next artifact", "--next-claimed-by", "agent-a",
111+
"--next-action-kind", "validate")
112+
assert completed["ok"]
113+
refresh = cli("refresh-state", *turn_binding, "--classification", "validated_recovery",
114+
"--delivery-batch-scale", "single_surface", "--delivery-outcome", "outcome_progress",
115+
"--no-global-sync", "--suppress-external-sinks")
116+
assert refresh["ok"]
117+
spend_args = ["quota", "spend-slot", *turn_binding, "--slots", "1", "--source", "heartbeat",
118+
"--execute", "--scan-path", str(tmp_path)]
119+
first_spend = cli(*spend_args)
120+
assert first_spend["settlement_result"]["ok"]
121+
assert cli(*restore)["status"] == "replayed"
122+
repeated_spend = cli(*spend_args)
123+
assert repeated_spend["settlement_result"]["ok"]
124+
runs = runtime / "goals" / goal / "runs/index.jsonl"
125+
assert sum(json.loads(line).get("classification") == "quota_slot_spent"
126+
for line in runs.read_text().splitlines()) == 1
127+
assert next(todo for todo in cli("todo", "list")["todos"] if todo["todo_id"] == target)["status"] == "done"

0 commit comments

Comments
 (0)