From ef6b1ac8717eae6debee3b13a35d7c24452e1b10 Mon Sep 17 00:00:00 2001 From: huangruiteng Date: Sat, 3 Oct 2026 04:49:15 +0800 Subject: [PATCH 1/2] test(delegation): isolate terminal authority-loss qualification Signed-off-by: huangruiteng --- .../2026-09-28-retirement-cadence.md | 41 +++++++++++++++---- .../2026-09-28-retirement-cadence.zh-CN.md | 33 +++++++++++---- tests/test_delegation_lease_lifetime.py | 4 +- 3 files changed, 62 insertions(+), 16 deletions(-) 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 7deda7c86d..b4a1811125 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 @@ -1,6 +1,6 @@ # Local authority: retirement cadence after integration -- Current plan: October 2, 2026, `9b0486dc1`; historical audit: `ce3862e33`; adoption follow-up: `71525ab90`, September 28, 2026; [中文](2026-09-28-retirement-cadence.zh-CN.md). +- Current plan: October 2, 2026, `9ac4efa90`; historical audit: `ce3862e33`; adoption follow-up: `71525ab90`, September 28, 2026; [中文](2026-09-28-retirement-cadence.zh-CN.md). - Owners: overall roadmap R3/R4/R5/R6; shared authority D1–D3; TS migration T0–T4. - This replaces the **current inventory/estimates** in the September 27 recovery and Host-supervision ledgers, not their historical validation results. @@ -74,7 +74,7 @@ contract readback. This does not certify every installed Host or D2. ## Current closeout: validation, migration and deletion (2026-10-02) -Rechecked against main `9b0486dc1` and the linked PR heads. This is the current +Rechecked against main `9ac4efa90` and the linked PR heads. This is the current execution plan for **R5 / D1–D3 / T0–T4**, replacing the previous A–D schedule; older measurements remain source-specific evidence. R6 is a separate successor. Storage format, authority selection and ownership policy are three distinct @@ -88,23 +88,48 @@ retirement of the `legacy` handoff policy. | Merged: #4931, #5251 | SQLite replay/proof and allocation improvements. Reuse these implementations and retain their matched evidence; D2 is not certified by their merge. | | Merged: #5395, #5417 | Unused Python lease/handoff crossings and duplicate settlement admission/recovery decisions retired. Continue deletion at actual last callers; do not count these again. | | Merged: #5436 | Original delegated Host lease renewal. Final Todo validation and stop acknowledgement remain distinct boundaries. | -| Review: [#5413](https://github.com/loopx-project/loopx/pull/5413), `2c99505c7` | Separate provider promotion from backed-up policy migration; reject fresh legacy configuration but recover historical operations. CLI recovery repair: 99 affected tests and actual old-to-new CLI experiments on File/SQLite pass; final-head independent review remains. Existing legacy Goals are not automatically migrated. | -| Review: [#5466](https://github.com/loopx-project/loopx/pull/5466), `60a052383` | Preserve the original lease through final acceptance. Merge after independent review, then validate the installed execution path. | -| Review: [#5283](https://github.com/loopx-project/loopx/pull/5283), `73d1fe663` | Reduce preflight projection cost without reducing decision inputs; final capture reports provider unavailability explicitly. Author reports 96 unchanged-source File/SQLite inspections and full projection parity; independent review and installed readback remain. Do not declare the historical transient open failure explained by a synthetic failure. | +| Merged: [#5413](https://github.com/loopx-project/loopx/pull/5413), `4ce894ca1` | Separate provider promotion from backed-up policy migration; reject fresh legacy configuration but recover historical operations. Retain the prior 99-test and old-to-new CLI evidence. Existing legacy Goals are not automatically migrated. | +| Merged: [#5466](https://github.com/loopx-project/loopx/pull/5466), `066b5bf26` | Preserve the original lease through final acceptance and retain the next controller replan. Installed candidate `9ac4efa90` passes the bounded File/SQLite matrix below; other Host lanes and stop acknowledgement retain their own exits. | +| Open: [#5283](https://github.com/loopx-project/loopx/pull/5283), `1012d37f3` | Reduce preflight projection cost without reducing decision inputs; final capture reports provider unavailability explicitly. The earlier `73d1fe663` author report covered 96 File/SQLite inspections and full projection parity; it does not qualify this newer head. Independent review and installed readback remain. A synthetic failure does not explain the historical transient open failure. | | Affected-lane dependencies | [#5308](https://github.com/loopx-project/loopx/pull/5308) must prove child stop before settled acknowledgement; [#5398](https://github.com/loopx-project/loopx/pull/5398) preserves complete UI history/inspector facts. Scope these to consumers actually included in the trial. They are not SQLite-engine prerequisites or permission to ship a known broken journey. | -There are **three prioritized open closeout PRs**, not three PRs to universal -completion. The remaining implementation packages are creation/default adoption, +Of these three closeout PRs, **#5413 and #5466 are merged; #5283 remains open**. +Do not keep counting merged work as pending. The remaining implementation +packages are creation/default adoption, policy migration plus legacy-policy retirement, and old-writer/capture retirement. They may combine only when caller ownership and rollback are coherent. Validation can expose concrete repairs; do not manufacture a fixed remaining-PR total or restart completed work to maintain one. +### 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. + +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; +#5490/#5494 remain review candidates for recovery observation and File decode cost. + ### Ordered delivery packages and exits | Package / existing owner | Work and decisive exit | Dependency / deletion / schedule | | --- | --- | --- | -| Close current heads; R3/R5 | Resolve exact-head findings in the three PRs above, inspect affected failures/conflicts, and present reviewed heads for maintainer merge. Record what is merged versus installed. | First target: 1–2 working days, subject to actual review/fix results. No unrelated optimization PR before closing these outcomes. | +| Close current heads; R3/R5 | Finish #5283 on its current head, inspect affected failures/conflicts, and present its reviewed head for maintainer merge. Continue installed acceptance for merged changes instead of reopening their implementation. | First target: 1–2 working days, subject to actual review/fix results. No unrelated optimization PR before closing these outcomes. | | Installed recovery candidate; D1/D3, existing whole-Goal promotion task | Pin one merged source and actual CLI/App/Effect Node/SQLite identity. Independently restore a verified backup, run the matrix below on detached real data plus synthetic negatives, and complete File→SQLite→new writes→File. Then perform authorized per-Goal adoption and ordinary readback. | Begin immediately after relevant merges; target 1–2 working days for the bounded matrix. Keep the compatible recovery binary and archives. No live corruption/crash injection. | | Bounded opt-in cohort; D2/D3 | When installed recovery and relevant execution controls pass, offer a reversible trial to at most 20 core developers. Publish workload/platform limits, backup/migration/disable instructions, known gaps, stop conditions and reporting route. Collect real daily use and failed cases. | Does not wait for every formal D2 axis or a new ten-day certificate. No invitation until rollback retains new writes. Does not certify a release default. | | Canonical creation/default adoption; D3/T3 | Reuse `machine_configuration/goal_storage.py` and `local_authority_defaults.ts`. Current setting only chooses the **post-promotion target** (`promotion_performed: false`). Complete new-Goal initialization, retry and upgrade, settings plus packaged App/CLI/Lark readback; explicit existing selectors stay pinned. | Implement after the bounded candidate is useful; activate the release default only at the decision below. Remove replaced creation/selection decisions in this package. Changing `file` to `sqlite` in one setting is insufficient. | 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 2be8a3f5a9..b061f4f970 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 @@ -1,6 +1,6 @@ # 合并后的本地权威退役节奏 -- 当前计划:2026-10-02,`9b0486dc1`;历史核对基线:`ce3862e33`;采用后续核对:`71525ab90`,2026-09-28;[English](2026-09-28-retirement-cadence.md)。 +- 当前计划:2026-10-02,`9ac4efa90`;历史核对基线:`ce3862e33`;采用后续核对:`71525ab90`,2026-09-28;[English](2026-09-28-retirement-cadence.md)。 - Owner:总 roadmap R3/R4/R5/R6、shared authority D1–D3、TS 迁移 T0–T4。 - 本记录替代 9 月 27 日 recovery、Host supervision 记录的**当前清单和估算**, 不替代其历史验证结果。 @@ -65,7 +65,7 @@ owner、持久兼容义务、正反例证据及回退方式,和不可变基线 ## 当前收尾:验证、迁移与删除(2026-10-02) -按 main `9b0486dc1` 和所列 PR head 重新核对。本节是 **R5 / D1–D3 / T0–T4** +按 main `9ac4efa90` 和所列 PR head 重新核对。本节是 **R5 / D1–D3 / T0–T4** 的当前执行计划,替代旧 A–D 排期;历史测量仍只适用于原源码和负载。R6 单独推进。 存储格式、权威选择、所有权策略是三种不同迁移:有 SQLite 数据库,不代表新 Goal 已经默认使用 canonical authority,也不代表 `legacy` handoff 策略已经退役。 @@ -77,21 +77,40 @@ owner、持久兼容义务、正反例证据及回退方式,和不可变基线 | 已合并:#4931、#5251 | SQLite 重放/证明和分配优化;复用实现及匹配证据,合并不等于 D2 已验收。 | | 已合并:#5395、#5417 | 无调用方的 Python lease/handoff 跨界、重复结算准入/恢复决策已退役。继续按最后调用方删除,不重复计账。 | | 已合并:#5436 | 委派 Host 原租约续期;最终 Todo 验收和停止确认仍是不同边界。 | -| 复审中:[#5413](https://github.com/loopx-project/loopx/pull/5413),`2c99505c7` | provider 晋升与带备份的策略迁移解耦;禁止新 legacy 配置,允许恢复历史操作。CLI 恢复修复的 99 项相关测试、File/SQLite 真实旧 CLI→新 CLI 演练通过,最终 head 独立复审待完成。没有自动迁移存量 legacy Goal。 | -| 待审:[#5466](https://github.com/loopx-project/loopx/pull/5466),`60a052383` | 原租约保持到最终验收;独立评审、维护者合并后验证安装态执行路径。 | -| 待审:[#5283](https://github.com/loopx-project/loopx/pull/5283),`73d1fe663` | 不缩减决策输入地降低 preflight 投影成本,末次 capture 显式报告 provider 不可用。作者报告固定源码下 96 次 File/SQLite 检查及完整投影等价;仍需独立复审和安装后读回。合成故障不证明历史瞬态打开失败的根因。 | +| 已合并:[#5413](https://github.com/loopx-project/loopx/pull/5413),`4ce894ca1` | provider 晋升与带备份的策略迁移解耦;禁止新 legacy 配置,允许恢复历史操作。保留先前 99 项测试和旧 CLI→新 CLI 的演练证据;没有自动迁移存量 legacy Goal。 | +| 已合并:[#5466](https://github.com/loopx-project/loopx/pull/5466),`066b5bf26` | 原租约保持到最终验收,并保留下一轮 controller replan。安装候选 `9ac4efa90` 通过下述有界 File/SQLite 矩阵;其他 Host 路径及停止确认仍有各自出口。 | +| 仍开放:[#5283](https://github.com/loopx-project/loopx/pull/5283),`1012d37f3` | 不缩减决策输入地降低 preflight 投影成本,末次 capture 显式报告 provider 不可用。此前 `73d1fe663` 的作者报告覆盖 96 次 File/SQLite 检查及完整投影等价,不能认证这个新 head;仍需独立复审和安装后读回。合成故障不证明历史瞬态打开失败的根因。 | | 按实际路径建立依赖 | [#5308](https://github.com/loopx-project/loopx/pull/5308) 要证明子进程停止后才报告已结算;[#5398](https://github.com/loopx-project/loopx/pull/5398) 保留 UI 历史和 inspector 完整事实。只对纳入试用的相关消费者建依赖,不将其说成 SQLite 引擎前置,也不能发布已知损坏的用户路径。 | -当前优先收尾的是 **3 个已存在的开放 PR**,不等于再合 3 个就全部结束。 +这三个收尾 PR 中,**#5413、#5466 已合并,#5283 仍开放**。不要继续把已合并的工作计为待实现。 剩余实现包是 canonical 创建/默认接入、策略迁移与 legacy 策略删除、旧 writer/ 捕获退役。仅当调用方归属和回退边界一致时才合并成同一个 PR。验证可能暴露具体修复, 不再制造固定“剩余 PR 数”,也不为维持这个数字重做已完成的工作。 +### `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 恢复不产生新效果。所有受影响场景已重跑, +不把初次失败算成产品成功。 + +该结果关闭 #5466 的这条有界安装路径,不认证真实模型 provider、中断 Host 停止确认、 +Windows、整 Goal 恢复、正式 D2、发布默认或最后 writer 退役。此次安装没有改变活跃 +Goal 的 provider 或所有权策略;继续保留这些已有出口。#5490/#5494 仍是恢复结果查询 +和 File 解码成本的待审候选。 + ### 有依赖顺序的交付包与出口 | 交付包/既有 owner | 要做什么、凭什么完成 | 依赖/删除机会/节奏 | | --- | --- | --- | -| 现有 head 收尾;R3/R5 | 修完上述 3 个 PR 的 exact-head finding,处理相关失败与冲突,提交已评审 head 给维护者合并;区分已合并和已安装。 | 第一目标为 1–2 个工作日,取决于真实评审/修复结果;收尾前不另开无关优化。 | +| 现有 head 收尾;R3/R5 | 在当前 head 收尾 #5283,处理相关失败与冲突,提交已评审 head 给维护者合并;已合并工作继续安装态验收,不重新实现。 | 第一目标为 1–2 个工作日,取决于真实评审/修复结果;收尾前不另开无关优化。 | | 安装态恢复候选;D1/D3、整 Goal 晋升任务 | 固定合并源码和 CLI/App/Effect 实际 Node/SQLite 身份;独立恢复并验证备份,用隔离真实快照及合成负例执行下表,完成 File→SQLite→新增写入→File。之后按授权逐 Goal 采用并日常回读。 | 相关 PR 合并后立即开始,有界矩阵目标 1–2 个工作日;保留兼容的恢复版本和 archive,不对活跃 Goal 注入崩溃/损坏。 | | 有界自愿试用;D2/D3 | 安装态恢复及相关执行控制通过后,邀请不超过 20 位核心开发者。公开负载/平台范围、备份迁移关闭步骤、已知缺口、停止条件与反馈入口;观察真实日常使用和失败。 | 不必等待全部正式 D2 轴或一份新的十天证书;携带新写入回退未通过前不邀请。试用不认证发布默认值。 | | Canonical 创建/默认接入;D3/T3 | 复用 `machine_configuration/goal_storage.py` 和 `local_authority_defaults.ts`。当前设置只选择**晋升后的目标**,返回 `promotion_performed: false`。补齐新建初始化/重试、升级、设置及打包 App/CLI/Lark 读回,已有显式 selector 保持固定。 | 有界候选可用后实现,发布默认启用仍服从下方决策;同包删除被替代的创建/选择决策。只把设置里的 file 改成 sqlite 不够。 | diff --git a/tests/test_delegation_lease_lifetime.py b/tests/test_delegation_lease_lifetime.py index e47deab6f9..591cf95488 100644 --- a/tests/test_delegation_lease_lifetime.py +++ b/tests/test_delegation_lease_lifetime.py @@ -167,7 +167,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 = [] From 333885ea6207ca5be0b69b6a36124ffdff5bae87 Mon Sep 17 00:00:00 2001 From: huangruiteng Date: Sat, 3 Oct 2026 14:59:19 +0800 Subject: [PATCH 2/2] test(delegation): start short leases at managed execution Signed-off-by: huangruiteng --- .../2026-09-28-retirement-cadence.md | 9 +++++- .../2026-09-28-retirement-cadence.zh-CN.md | 8 +++-- tests/test_delegation_lease_lifetime.py | 30 +++++++++++++++---- 3 files changed, 38 insertions(+), 9 deletions(-) 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 61623e0283..cca8742e0a 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 @@ -131,11 +131,18 @@ 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; -#5490/#5494 remain review candidates for recovery observation and File decode cost. +recovery observation and File decode measurements retain their separate evidence +below. ### Ordered delivery packages and exits 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 e4a712e29f..7cdc656010 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 @@ -110,10 +110,14 @@ Todo 完成→controller replan 场景均通过;加载的 LoopX 模块确实 权威、要求不同意图被拒绝,并验证原 Turn 恢复不产生新效果。所有受影响场景已重跑, 不把初次失败算成产品成功。 +相邻源码回归现在从受管执行发起时开始 20 秒 Host 租约计时。同样在准备完成后 +延迟 22 秒,旧夹具会在 Host 启动前拒绝执行;修正后进入真实续租、完成及丢响应 +重放。租约身份、过期拒绝以及既有运行/验收预算均保持不变。 + 该结果关闭 #5466 的这条有界安装路径,不认证真实模型 provider、中断 Host 停止确认、 Windows、整 Goal 恢复、正式 D2、发布默认或最后 writer 退役。此次安装没有改变活跃 -Goal 的 provider 或所有权策略;继续保留这些已有出口。#5490/#5494 仍是恢复结果查询 -和 File 解码成本的待审候选。 +Goal 的 provider 或所有权策略;继续保留这些已有出口。恢复结果查询和 File 解码 +测量仍按下方各自证据记录。 ### 有依赖顺序的交付包与出口 diff --git a/tests/test_delegation_lease_lifetime.py b/tests/test_delegation_lease_lifetime.py index 591cf95488..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):