diff --git a/docs/architecture/rfcs/ledger/shared-goal-authority-state-provider-v0/2026-09-28-retirement-cadence.md b/docs/architecture/rfcs/ledger/shared-goal-authority-state-provider-v0/2026-09-28-retirement-cadence.md index df8baf167d..e08476a4ad 100644 --- a/docs/architecture/rfcs/ledger/shared-goal-authority-state-provider-v0/2026-09-28-retirement-cadence.md +++ b/docs/architecture/rfcs/ledger/shared-goal-authority-state-provider-v0/2026-09-28-retirement-cadence.md @@ -113,6 +113,37 @@ policy editing remains outside this slice; existing Lark actions read canonical state. Next: qualified creation/upgrade callers and authorized Goal adoption, then delete live legacy branches at their last callers. +### Installed delegation boundary at `9ac4efa90` + +A macOS arm64 installation from that merged source aligns the CLI, rebuilt App +bundle and restarted Chat/Status services. The served HTML matches the installed +bundle; both current entry assets and all 14 assets from the preceding delivery +remain readable. This is process/HTTP readback, not a full GUI interaction test. + +An independently staged installation exercises real File/SQLite stores, actual +CLI subprocesses and a deterministic generic Host process: six final-acceptance +renewal/lost-reply cases, four expired/replaced-execution rejection cases, and +four last-Todo completion→controller-replan cases pass. Loaded LoopX modules are +checked against the installed snapshot. The first run had 9 passes and 5 failures: +a short setup lease preempted one intended negative case; an extension of the +Markdown fixture incorrectly expected a changed canonical completion intent to +replay. The corrected fixture loses authority at the tested boundary, requires +changed-intent rejection, and verifies original Turn resume without new effects. +All affected cases were rerun; the failures are not counted as product successes. + +The adjacent source regression now starts its 20-second Host lease at managed +execution dispatch. A matched 22-second delay after fixture preparation rejected +the old execution before Host start; the corrected fixture reaches real renewal, +completion and lost-reply replay. Lease identity, expiry rejection and the +existing runtime and validation budgets remain unchanged. + +This closes this bounded installed #5466 path. It does not qualify live model +providers, interrupted-Host stop acknowledgement, Windows, full Goal recovery, +formal D2, release defaults or last-writer retirement. No active Goal provider or +ownership mode changes are part of this installation. Keep those existing exits; +recovery observation and File decode measurements retain their separate evidence +below. + ### Ordered delivery packages and exits | Package / existing owner | Work and decisive exit | Dependency / deletion / schedule | diff --git a/docs/architecture/rfcs/ledger/shared-goal-authority-state-provider-v0/2026-09-28-retirement-cadence.zh-CN.md b/docs/architecture/rfcs/ledger/shared-goal-authority-state-provider-v0/2026-09-28-retirement-cadence.zh-CN.md index 8ec905adae..6f5f8b2855 100644 --- a/docs/architecture/rfcs/ledger/shared-goal-authority-state-provider-v0/2026-09-28-retirement-cadence.zh-CN.md +++ b/docs/architecture/rfcs/ledger/shared-goal-authority-state-provider-v0/2026-09-28-retirement-cadence.zh-CN.md @@ -96,6 +96,29 @@ HTTP 路径覆盖 metadata 保留、过期源、跨 Goal/摘要拒绝、过期 编辑不在本批,既有飞书操作仍读 canonical 状态。下一步验收创建/升级调用方并 逐 Goal 按授权采用,再按最后调用方删除活跃 legacy 分支。 +### `9ac4efa90` 的安装态委派边界 + +macOS arm64 上,以该合并源码对齐 CLI、重新构建的 App 和重启后的 Chat/Status +服务。实际返回的 HTML 与安装包一致,当前两个入口资源及上一份交付的 14 个资源 +均可读取。这是进程和 HTTP 读回,不是完整 GUI 交互验收。 + +独立安装副本通过真实 File/SQLite store、CLI 子进程和确定性的 generic Host 进程 +运行:6 个最终验收续租/回执丢失场景、4 个过期/替换执行拒绝场景,以及 4 个最后 +Todo 完成→controller replan 场景均通过;加载的 LoopX 模块确实来自安装快照。 +第一轮 9 通过、5 失败:一个负例被无关的短准备租约提前打断;从 Markdown 夹具扩展 +的检查错误地期待 canonical 完成请求改变意图后仍可重放。修正后在目标阶段主动撤销 +权威、要求不同意图被拒绝,并验证原 Turn 恢复不产生新效果。所有受影响场景已重跑, +不把初次失败算成产品成功。 + +相邻源码回归现在从受管执行发起时开始 20 秒 Host 租约计时。同样在准备完成后 +延迟 22 秒,旧夹具会在 Host 启动前拒绝执行;修正后进入真实续租、完成及丢响应 +重放。租约身份、过期拒绝以及既有运行/验收预算均保持不变。 + +该结果关闭 #5466 的这条有界安装路径,不认证真实模型 provider、中断 Host 停止确认、 +Windows、整 Goal 恢复、正式 D2、发布默认或最后 writer 退役。此次安装没有改变活跃 +Goal 的 provider 或所有权策略;继续保留这些已有出口。恢复结果查询和 File 解码 +测量仍按下方各自证据记录。 + ### 有依赖顺序的交付包与出口 | 交付包/既有 owner | 要做什么、凭什么完成 | 依赖/删除机会/节奏 | diff --git a/tests/test_delegation_lease_lifetime.py b/tests/test_delegation_lease_lifetime.py index e47deab6f9..09d48e6748 100644 --- a/tests/test_delegation_lease_lifetime.py +++ b/tests/test_delegation_lease_lifetime.py @@ -41,14 +41,32 @@ def prepare_lease(root, runner, monkeypatch, *, ttl=20): assert prepared.returncode == 0, prepared.stderr binding = runner.binding("analysis") runner._acquire_delegation_lease(runner.path("lease-lifetime"), row, binding) - lease = row["task_lease"]["lease"] + lease = dict(row["task_lease"]["lease"]) if ttl is None: return lease - renewed = runner._cli(binding, "task-lease", "renew", "--goal-id", runner.goal_id, - "--todo-id", binding["todo_id"], "--owner", binding["agent_id"], - "--idempotency-key", lease["idempotency_key"], "--expected-version", str(lease["version"]), - "--ttl-seconds", str(ttl)) - return renewed["lease"] + # Start the short lifetime at managed execution, not before acceptance + # preparation. Cold setup may outlast 20s without exercising Host renewal. + cli = runner._cli + shortened = False + + def at_launch(binding, *args, **kwargs): + nonlocal shortened + if args[:2] == ("turn", "run-once") and not shortened: + context = kwargs["delegated_lease"] + renewed = cli(binding, "task-lease", "renew", "--goal-id", runner.goal_id, + "--todo-id", binding["todo_id"], "--owner", binding["agent_id"], + "--idempotency-key", lease["idempotency_key"], + "--expected-version", str(context["lease"]["version"]), "--ttl-seconds", str(ttl)) + proof = renewed["lease"] + assert (proof["owner"], proof["idempotency_key"], proof["lease_epoch"]) == ( + lease["owner"], lease["idempotency_key"], lease["lease_epoch"]) + lease.update(proof) + kwargs["delegated_lease"] = {**context, "lease": proof} + shortened = True + return cli(binding, *args, **kwargs) + + monkeypatch.setattr(runner, "_cli", at_launch) + return lease def inspect(runner): @@ -167,7 +185,9 @@ def observe_reply(binding, *args, **kwargs): @pytest.mark.parametrize("authority_loss", ["expiry", "replacement"]) def test_completion_renewal_receipt_cannot_revive_lost_execution(service, monkeypatch, authority_loss): root, runner = service - prepare_lease(root, runner, monkeypatch) + # Lose authority explicitly after the completion-renewal reply below. + # A short Host startup lease could stop execution before that boundary. + prepare_lease(root, runner, monkeypatch, ttl=None) cli = runner._cli dropped = False completions = []