feat(goals): opt in to canonical creation with frozen execution policy - #5569
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning effort xhigh.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
Reviewed exact head: 8a0763124bc4f9194e9b200c03df5fc26147058e; immutable base: 30efccd6c7d4e2300c2ac87ddc6ddb1dfb855a40.
阻塞发现:[P1] 原生创建已经完成后,实际 bootstrap CLI 仍依赖兼容 Markdown,合法的原操作恢复会提前失败。 四种 File/SQLite × soft_claim/hard_lease 组合均复现。下面包含全 PR 评审、最小修复和独立验证。
动机
创建新 Goal、希望直接使用原生存储的 CLI 和 App 用户会遇到这个问题。原生存储指 Todo、租约和操作回执由 File 或 SQLite 的同一个权威事务保存。
此前选择 SQLite 只固定将来迁移的目标,新 Goal 仍需另外准备并执行迁移;本 PR 希望用户显式开启一次后,新 Goal 创建即完成原生初始化,并固定执行策略。
预期改善是减少新 Goal 的迁移步骤,并让重试返回原创建结果、保留之后的写入。实测新建和 App 重试确有这个改善,但 CLI 在兼容 Markdown 缺失或无法解码时仍无法恢复。
本次边界是显式开启的新 Goal 创建,不包括旧 Goal 自动迁移、发布默认切换、完整灾备或持续运行资格。
改动思路
方案复用现有机器配置的 goal_storage namespace,把存储 provider 与执行策略分开选择。配置 v1 的 canonical_creation 默认为 false;启用时冻结原操作、目标 provider 和策略,创建后改变机器默认值不能重新解释已经存在的 Goal。Python 负责入口和源证据传输,新的 TS initializeNewGoalAuthority 复用已有锁、provider、源验证、writer fence 和提交/回读 owner。writer fence 是阻止旧 Markdown 写入的持久屏障,不是新的 Agent 权限。
正常路径是登记冻结意图、验证完整空源、建立旧写入屏障、原子提交权威状态和创建回执,再确认屏障完成。完成后的原回执恢复应当只依赖原生存储和登记绑定,不能从陈旧 Markdown 推断权威状态。这个分工有价值:避免第二个 Python 决策源,也避免把旧数据迁移冒充新建。不过 CLI 在到达此 owner 之前仍执行旧的读取/重建逻辑,导致同一恢复能力在 helper 与实际入口表现不同。
具体改动
全量 24 个路径、+560/-91:机器配置及配置目录增加显式创建与策略字段;bootstrap 和 App action 接入登记绑定;TS 初始化、冻结目标解析、屏障解码和完成标记承担运行行为;共享合同、生成器及两种语言生成结果登记新 fence schema;registry IO manifest 仅校正行号。两个前端文件复用现有编辑器、升级 v0 草稿并保留关闭状态。参考文档替换旧说明,两个 RFC 记录有界检查点,四张合成 UI 图说明操作;Python/TS 测试及 digest consumer inventory 覆盖新路径,没有新增账户、调度器或独立权限入口。
关键代码讲解
manageNewGoalStorage:v0 和 v1 关闭态继续返回原目标合同;只有显式开启才冻结 soft_claim 或 hard_lease,新建不接受 legacy。initialize_goal_storage_target:先提交最小登记 witness;只有 TS 明确要求时才完整捕获源。直接调用此桥接,在 Markdown 缺失或无法解码时均能返回原回执。initializeNewGoalAuthority:在锁内核对原操作、源路径及冻结目标,拒绝非空源、异主屏障和已有不同权威;原回执在后续提交后仍有效。已完成但丢失的权威要求完整备份恢复,不能重新创建空库。bootstrap_project:冻结意图、阻止强制重建、绕开新建路径的旧 shadow producer;但 420–422 和 567 行仍读取 Markdown,568–570 行仍把缺失 Markdown 当旧源重建,直到 610 行才进入原生回执 owner。这是当前阻塞所在。
规范依据是本改动前已接受的 docs/architecture/rfcs/ledger/shared-goal-authority-state-provider-v0/2026-09-28-retirement-cadence.md,spec_revision 30efccd6c7d4e2300c2ac87ddc6ddb1dfb855a40(固定版本)。其 Canonical creation/default adoption; D3/T3 行要求复用现有 owner、完成新建及 retry/upgrade、设置与打包客户端回读,并保留既有选择。此 head 的显式新建、冻结策略、设置与正常重试已实现;CLI 原回执恢复 not_met,最低修复见下一节。完整 upgrade、Lark、正式默认与旧写入者退出仍属于该既有 package 的剩余范围,此 PR 不关闭它。两个 RFC 新增检查点不能替代独立验收依据。
对主干的风险
[P1] 恢复入口错误地受兼容源控制。 可复现步骤:在可丢弃工作区启用 canonical_creation,执行 bootstrap,通过真实 todo add 写入一个后续 Todo,然后删除创建返回的 state_file,用原参数重新 bootstrap。四种组合全部退出 1,报旧 writer 已被 fence,未返回原创建回执。换成无法解码的 UTF-8 字节后,四种组合全部在 Python 读文件时退出 1。原生 todo list 仍看到后续 Todo,没有 fallback 或数据丢失;同一工作区、同一登记的原生 initializer 两种情况下都能回读原创建操作。问题因此在调用顺序,而不是 store 或回执损坏。现有 TS 删除 Markdown 测试通过,正好说明 helper 成功没有覆盖 CLI。
最低修复是让已登记的 canonical creation 原操作在任何兼容 Markdown 读取和旧源重建判定之前进入原生恢复 owner;仅未完成且 owner 要求捕获源时才读取完整 Markdown。必须保留原操作/目标/源路径绑定、非空源拒绝、--force 拒绝和已丢权威的灾备边界,不能整体跳过 fence 检查。把上述 File/SQLite × 两种策略的真实 CLI 回归补入 tests/control_plane/test_new_goal_storage_defaults.py,断言退出成功、返回同一原回执、后续 Todo 不变、没有重建或 legacy fallback。重跑 uv run --extra test python -m pytest -q tests/control_plane/test_new_goal_storage_defaults.py 和 node --experimental-strip-types --experimental-sqlite --test tests/control_plane_ts/new_goal_initialization.test.ts。
关闭态已有独立 base/head 真实 CLI 对照:缺省配置及 v0 File/SQLite 各执行 bootstrap→重连→Todo 读取,冻结目标、完整 selection、legacy 策略、无 writer fence、无 creation operation 及 Todo 数量一致。head 的 v1 false 也与相同 provider 的 v0 路径一致。另在同一 registry 中,四种组合逐一验证:启用前已有 Goal 重连不改原目标,启用后新 Goal 按配置建立原生权威。配置目录现在展示可用的新字段并显式升级编辑草稿,这是可发现性变化,未开启的普通创建没有新义务、原生提交或自动迁移。
打包 frontend 使用实际 HTTP/backend、隔离合成 Goal 验证:设置→能力中心→设备默认→新 Goal 权威存储,旧 v0 SQLite 保持关闭;显式开启→预览→应用→原生机器文件回读成功。预览绑定当前 revision,应用确认提供配置写入授权;非法 legacy 输入被拒绝且已保存配置保持 hard_lease,修正为 soft_claim 后能继续应用,页面刷新并重新进入设置仍读回 soft_claim。检查了桌面与 390px viewport,目标、设备来源和未来 Goal 边界可见;没有调用真实模型或迁移活跃 Goal。
语义与 CI 对齐
soft_claim/hard_lease 复用现有执行策略词汇;本 PR 扩展登记的 fence/创建回执合同,creation_completed 由提交回读 owner 维护,不能由文案或机器默认值充当权威。名称不授予工具、账户、租约或旧 Goal 迁移权限,控制面文案保持领域中立。新的缺省关闭与历史输入保留已披露,但 helper 的“无需 Markdown 恢复”尚未覆盖实际 CLI,这是当前合同与调用语义的具体缺口。
独立通过:30 项新建/App Python 测试、46 项配置/备份/Host bootstrap 相关 Python 测试、51 项 TS 初始化/fence/digest 检查;typecheck、semantic advisory 后的全树 semantic smoke、生成合同检查和打包构建通过。初次 TS 验证因未安装 TypeScript 依赖未完成,npm ci 后同组重新执行通过;最初两个验证命令路径选错,纠正后才计入上述结果。真实 CLI 恢复 oracle 在当前 head 仍失败,不能被这些绿色项抵消。当前 review 配置 wait_for_ci=false,未获取/轮询 CI,不证明远端检查全绿;作者披露的其他历史失败也未据此自动归因给本 PR。未做持续运行、发布安装或当前 main 集成资格;本 PR 未改 PostgreSQL store,实现和验证范围是本地 File/SQLite。
我的整体评价
结论 REQUEST_CHANGES。long_horizon 判定 not_yet_proven:正常新建及 App 恢复体现了减少迁移和重复初始化的价值,原生后续写入也保留,但 CLI 合法恢复不能继续,无法确认此有界交付支持持续工作。user_experience 判定 regression:新增合法创建路径的恢复依赖本应无关的文件,错误提示把用户引向 canonical authority,却没有完成已经存在的原生回执恢复;重复尝试增加干预与无效工作。
+560/-91 的全量改动对显式创建这个完整场景总体成比例。新的 100 行 TS 模块复用现有事务、provider 和锁,不是第二个存储框架;v0 配置和旧 fence 有真实持久消费者,应保留。相关的有界收敛点就是把 CLI 的完成态恢复统一到既有 TS owner,撤掉这条路径上的兼容源读取/重建依赖;无需扩成全量语言迁移或新的恢复命令。修复并通过真实 CLI 反例后再评新 head。当前结果仅评审该 head,未修复或合并该 PR,也不将这个前置能力记为 D1–D3、正式默认或长程效果验收完成。
English verdict: REQUEST_CHANGES - 8a07631. Completed canonical creation replay still fails through the real bootstrap CLI before native receipt recovery when compatibility Markdown is missing or unreadable, across File/SQLite and both execution policies. Later Todos survive and the native owner replays successfully. 76 Python and 51 TS checks plus packaged settings, typecheck and semantic checks passed; add and pass the real CLI recovery regression before re-review.
…hip-defaults Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; model=gpt-6.1-sol; provider=OpenAI; declaration_source=runtime_reported; reasoning_effort=xhigh
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
当前 exact head 7f1b231fb33a5843ae0cc87fcb13de9e792949ad 未发现未解决的阻塞项。旧评审的 P1 已通过真实 CLI 红绿回归修复;以下是整个当前 PR 的独立判断,而非仅确认最后一次修补。
动机
创建新 Goal、希望直接使用原生存储的 CLI 和 App 用户会遇到这个问题。此前选择 SQLite 只固定将来迁移的目标,新 Goal 仍需另外准备并执行迁移;显式开启后,新 Goal 创建即建立原生权威,并固定执行策略。实测创建后可继续添加 Todo,再删除或损坏兼容 Markdown,CLI 重试仍返回原创建回执并保留全部原生状态;设置页面也能拒绝错误策略、修正并回读。本次边界是显式开启的新 Goal 创建,不包括旧 Goal 自动迁移、发布默认切换、完整灾备或持续运行资格。完整升级、Lark 读回、核心开发者试用和正式发布默认仍由现有 D3/T3 采用工作包推进,D2 的固定验收没有降级。
改动思路
复用现有机器配置、原生存储 provider、writer fence 和创建回执 owner。机器是否允许新建 canonical 权威是显式意图,不能从 SQLite 可用或 provider 目标反推。CLI/App 先固定原创建操作、源路径与目标,再由 TypeScript 在已有锁内验证空源、提交并读回。完成后的重试先读原生回执;只有未完成创建才由 owner 请求完整源捕获。配置只影响未来新 Goal,已有 Goal 保留原选择,Agent 继承 Goal 的策略,不额外获得工具权限。
具体改动
当前整个 PR 共24个路径,文本 +659/-97,另有4张合成公开截图:设置表单和双语说明、配置适配、CLI/App 创建调用、TS 默认/初始化/fence、注册词汇及生成文件、聚焦测试和参考文档。相对旧评审的 PR 自身修复为4路径 +115/-22;合入的主线历史不算本 PR 交付。新初始化模块106行,组合已有存储与锁,无新后台任务或第二 Python 决策源。专门的公开入口回归保留,因为之前 helper 测试通过仍不能发现真实 CLI 被旧源读取截断。
关键代码讲解
manageNewGoalStorage:v0/关闭态仍只固定目标;显式 v1 开启才调用初始化,所选策略来自既有 soft/hard 类型词汇。initialize_goal_storage_target:先传原注册绑定给 typed owner;收到 source_capture_required 才捕获完整 Markdown/lease 源,完成的回执重试无需解析它。initializeNewGoalAuthority:在已有源与维护锁内重验注册身份,原回执在后续 Todo 写入后仍有效;非空源、外国 fence、已完成但丢失权威均拒绝。现有类型化 request/conflict 错误保留备份恢复诊断,不用 broad catch 隐藏 IO 异常。bootstrap_project:既有 canonical 重连先进入同一回执 owner,再决定跳过兼容源读取/重建;即使 Markdown 缺失,force 仍拒绝,显式改变源路径也不能绕过绑定。输出 state action 正确为 kept-existing。
规格依据:docs/architecture/rfcs/ledger/shared-goal-authority-state-provider-v0/2026-09-28-retirement-cadence.md,不可变 spec_revision=30efccd6c7d4e2300c2ac87ddc6ddb1dfb855a40(原文)。逐项判断:Canonical creation/default adoption; D3/T3 — initialization/retry/settings 已实现并通过真实 CLI/App 与打包设置验证;Canonical creation/default adoption; D3/T3 — explicit existing selectors 已实现,同 registry 的旧 Goal 保留目标;Canonical creation/default adoption; D3/T3 — upgrade/Lark/release adoption 延后到现有采用工作包,不能因此宣称整个 D3/T3 或 D2 已完成。
对主干的风险
风险主要在创建与恢复边界。旧 P1 的8个 CLI 场景在修复前失败,当前 File/SQLite×soft/hard×缺失/坏编码全部成功,原回执和全部原生 head 保持;相反方向的 force、改操作、改源和真实权威缺失均拒绝,未发生重建或 fallback。共享关闭态用同一真实 CLI harness 对比当前不可变基准 745e2fdae55db5ce79b03d44af35ff94aff543e9:absent/v0 结果完全相同,v1 false 也匹配同 provider 的 v0;设置发现本身不激活。开启之后旧 Goal 不被自动覆盖,之后的新 Goal 刻意受机器范围覆盖。
当前验证:69项 Python bootstrap/创建/fence、51项 TS 初始化/digest/fence,通过类型检查、契约生成校验、语义 advisory 后完整检查、打包前端构建和真实后端设置的错误修正及 reload。45项机器配置、配置备份及 ChatHTTP companion 检查也通过。预合并5项直接检查、17项选中检查,无新增失败或 manual hold;维护性检查保留1项既有 Lark 模块预算告警,同完整基准索引与 head 都失败于相同模块,源码和预算文件 hash 相同、无 magnitude regression,不在本 PR 偷改预算。桌面及390px视口经过观察;界面状态保存由实际后端读回证明,截图本身不证明持久化。原公开图和旧 narrow 控件检查可复用,因为相应前端文件未变。未测试安装态 App/Lark、Windows、付费模型意图、长时 D2 或正式默认采用;本次不改 PostgreSQL provider,不能把本地测试称为 PG 验收。
语义与 CI 对齐
创建 fence 词汇扩展进入既有注册契约并生成双语言投影;handoff 模式和 request/conflict 错误复用既有类型 owner。没有 substring 状态分类或领域专用的通用义务文字。关闭态与显式开启的行为变化已在设置、双语 RFC checkpoint、文档和测试中说明;机器拒绝是强制边界,帮助说明是 guidance。当前 wait_for_ci=false,未查询、轮询或等待远端 CI;本结论基于已执行的本地原生验证,不宣称 CI 全绿。
我的整体评价
交付判断 justified_increment:显式新建和后续恢复是完整、可独立验证的前置,完整采用仍保留既有出口。long_horizon=improved,因为创建后积累的真实 Todo 可以继续读回并重试原结果,没有丢承诺、重复副作用或无终点重规划;这不是 soak 证书。user_experience=improved,一次设备选项减少每个新 Goal 的迁移准备,必要 preview 提供当前 revision,apply 授权这个已审阅范围,JSON 编辑可选,错误可以修正而不改变已保存策略。最强反对理由是新持久生命周期的维护成本;当前106行 typed 组合及真实负向恢复证明其成本与反复创建/恢复问题相称。未来重构已落实到完成重连路径,移除多余 Python 源读取/重建;仍有实际调用方的历史迁移/备份兼容不能只为降行数删除。剩余最强未验项是安装态跨入口升级和持续运行默认采用,归既有工作包,不妨碍这个默认关闭的有界前置。合并判断:在明确 owner 自合并授权和当前 head 原生 readiness 通过后,可执行;评审或绿色验证自身不授予合并权限。
English verdict: APPROVE - 7f1b231; the public CLI completed-retry blocker is fixed with real-provider red/green coverage, opposite refusal boundaries and default-off parity. This is a bounded opt-in prerequisite, not installed or release-default acceptance.
Summary
The device setting previously selected only the post-promotion provider, leaving fresh Goals on the legacy path. Extend that existing setting with explicit, default-off canonical creation: choose File/SQLite and soft_claim/hard_lease, freeze the original operation and target, initialize native authority, and fence legacy writers. Existing Goals retain their targets and require a separate reviewed migration.
Completed creation retries now reach the TypeScript receipt owner before compatibility Markdown reads or rebuild checks. Missing/unreadable Markdown no longer prevents returning the original result after later native writes. Force rebuild, changed operation/source, nonempty source and missing completed authority still fail closed. Python captures a full source only when the typed owner requests unfinished initialization; no parallel Python decision owner or new command is added.
The existing machine capability editor provides preview/apply/readback and invalid-policy recovery. CLI bootstrap and App create replay use the same owner. This is the bounded initialization/retry prerequisite for the accepted D3/T3 adoption package; installed upgrade, Lark readback, sustained D2, cohort and release-default acceptance remain open. The shipped default remains off.
Validation
At
7f1b231fb33a5843ae0cc87fcb13de9e792949ad, integrated with main745e2fdae55db5ce79b03d44af35ff94aff543e9:No remote CI was queried or polled under wait_for_ci=false. No installed App/Lark/Windows, full disaster recovery or sustained-operation certificate is claimed. The future-facing pass removes completed canonical legacy source/shadow decisions; historical formats remain for real migration and backup consumers.
Settings evidence
Synthetic public-safe examples; persistence is established by the real-backend readback above.
Author: model_agent, OpenAI GPT-6, using the LoopX Agent Git identity. Exact-head review and native merge readiness remain separate from validation and merge authority.