fix(refresh): preserve goal-level accountable writes - #5588
huangruiteng merged 1 commit into
Conversation
Workspace isolation assumed every accountable outcome carried a Todo-bound settlement and dereferenced a missing identity for valid goal-level refreshes. Resolve Todo repository constraints only when an exact Todo settlement exists, while retaining the typed workspace qualification for other accountable writes. Signed-off-by: duanjialing.777 <[email protected]>
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
精确 head:584dffcbfa101e0b1ce742a536d8a65adbcdd19f;完整比较基线:deeb536d79e18d48eb4a64171ed279c8635a4e9d。未发现本 PR 引入的阻塞问题。
动机
通过 CLI 记录 Goal 进展、且这次写入没有绑定具体 Todo 的调用者会遇到这个问题。
同一条合法的 Goal 级 refresh-state 命令,旧版本因空的 settlement identity 崩溃,进展没有保存;新版本成功保存记录。
实测新 head 新增 1 条运行历史,分别读回 outcome_progress 和真实 Git 工作区凭据;base 新增 0 条。
本 PR 只修复这条写入路径,不新增执行授权、不替代 Todo 验收,也不改变配额、调度或 Goal 完成规则。
这是已发出的 CLI 回归修复。我没有把作者的 smoke 数量当作验收,也没有找到单独规范此空 identity 缺陷的已接受文档;判断来自同一既有 CLI 场景的 base/head 实跑和历史读回。工作区枚举仍由既有 typed owner 管理。
改动思路
CLI → refresh_state_run → 捕获实际生产工作区 → 既有 TypeScript 工作区隔离判断 → 写入历史。仅当 settlement identity 包含 Todo 时,才读取完整 Todo 源并取该 Todo 的 repository 合同。没有 Todo 时用空的 task 合同继续既有工作区判断,避免解引用空 identity。
不修会持续丢失合法进展;把工作区检查整体跳过又会削弱 peer 隔离。当前条件分支正好位于已有写入 owner,复用了原判断,没有新 schema、flag、capability 或第二个决策源。
具体改动
全 diff 仅 loopx/state_refresh.py,+13/−11,调整一个 Todo 查找分支。
refresh_state_run(693 行):空 identity 不再触发 Todo 查找;有 Todo 时仍按todo_id从完整来源读取,保留显式task_repository。qualify_delivery_workspace_isolation(loopx/control_plane/agents/delivery_workspace.py,129 行,未改):继续调用 TypeScript owner;peer Git 交付仍要求独立 worktree,注册 local Goal 使用原本的 local workspace 规则。
验收包括实际执行并独立读回一条历史记录;不是只看 dry-run 的成功 JSON。新 head 的既有 CLI lifecycle smoke 通过,同一 smoke 在 base 上因 NoneType.todo_id 失败。
对主干的风险
最强反例是条件过宽导致“有 Todo 的交付绕过 repository/worktree 限制”。实测相关 74 项用例通过,包括 File/SQLite local peer 完成、外来工作区拒绝、local receipt 不能满足显式 Git task、in-flight 保持任务 open、blocked writeback 不消费 quota。4 项完整语义/词汇架构套件共 252 项通过,development advisory 在 full-tree 检查前执行。
额外运行 examples/control_plane/refresh-state-write-correctness-smoke.py 在 base/head 都失败,均为 --next-action requires a registered --agent-id,发生在未改动的 recommendation 路径、早于本 PR 的工作区分支。保留为既有独立 smoke 问题;它不能证明此次修复失败,也不能被标成通过。早先调用不存在测试路径属于评审准备错误,已用实际存在的套件替代。
未读取或等待远端 CI。没有新 UI/Lark 配置旅程;改动是既有 CLI/共用 refresh 入口内部修复。没有性能测量,不能从少量条件分支宣称吞吐提升。
我的整体评价
APPROVE。长程价值来自消除合法写入失败和后续无效重试,并保持已有工作区及任务边界;体验上调用者不用为了保存 Goal 级进展虚构 Todo 参数。它没有解决其它 smoke 的注册参数问题,也不证明整个 Goal 或长时运行已经验收。未来重构检查:此处沿用 typed workspace owner 已足够,新增 nullable-contract 抽象的成本大于收益。
English verdict: APPROVE — 584dffc. The same non-dry public CLI fails without appending at base and records one qualified outcome at head. All 74 related runtime tests and 252 semantic/architecture checks pass. The extra write-correctness smoke has the same pre-existing registered-agent error on both revisions; it remains a separate hold. No CI was queried and no merge was attempted.
Summary
refresh-statecalls from dereferencing a missing settlement identityRoot cause
The workspace-isolation expansion treated
qualifies_turn_scoped_settlement(...)as proof that aSettlementIdentityexisted. Accountable Goal-level refreshes can legitimately provideoutcome_progresswithout a Todo or Turn, sorefresh_state_run()entered the isolation path withsettlement_identity=Noneand failed atsettlement_identity.todo_id.Validation
uv run --extra test python examples/cli-project-lifecycle-command-modularization-smoke.pyfailed on currentmainwithAttributeError: 'NoneType' object has no attribute 'todo_id'78 passedacross local-peer delivery, Goal acceptance, final-outcome diagnostics, state-refresh selection, delivery-claim validation, and Turn-settlement diagnosis3 passeduv run ruff check loopx/state_refresh.pygit diff --checkloopx canary premerge --changed-file loopx/state_refresh.py: all direct checks and 11 catalog/risk checks passed; the maintainability check is an inherited advisory for unchangedloopx/extensions/lark/goal_topic_runtime.py;refresh-state-write-correctness-smoke.pyfails identically on immutable basedeeb536d7before this diff atresolve_refresh_recommendation()(--next-action requires a registered --agent-id)No frontend surface changes.