Retire standalone Todo suggestion command - #4725
Conversation
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
17c187a to
036ad62
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Reviewed head: 036ad621c70bd921333afd716a901fe303ead112
Baseline: 9f1916960306b3650d795895b89f331eeae2516e
动机
本 PR 的有效目标是退役没有集成产品调用方的独立 Todo suggestion prompt,减少 TS/shared-authority 迁移面。审查依据是 TS RFC T4、shared-authority 的现有退役检查点,以及实际 CLI/Agent 调用链。最终版本直接删除 todo suggest,没有用 todo discover 重新包装旧 builder。它完成这一退役切片,不宣称完成自动候选分析或 provider 默认切换。
改动思路
复用既有职责:todo list 读取正式工作,当前 Agent 分析尚未覆盖的工作,用户或有权限的 controller 通过既有 authoring 选择并写入 Todo,quota/Turn 继续负责执行准入。candidate_discovery_args 保留原命令和返回结构。open、可执行、候选提案三者不混为一谈;列表上限也不能充当完整 frontier 的缺失证明。仓库内未发现 frontend/Lark/host 对旧 suggestion builder 的调用,因此不需要配套 UI 改造。
具体改动
17 个文件,+76/-638;其中生产代码 +7/-268,净减少 261 行。删除 suggestion 模块、专用 CLI 参数/分支、独立协议文档和只验证该 prompt 的 smoke;将退役负例并入现有 CLI diagnostics。同步中英文 TS/shared-authority 与 wishlist RFC,删除失效的未来 suggestion 扩展项,迁移指引归入既有 long-horizon 协议。
关键代码讲解
loopx/cli_commands/todo_registration.py:14—register_todo_command删除suggest、--from、--trigger;不注册新的 discover。非法命令在进入 Todo handler 前由 argparse 拒绝。loopx/cli_commands/todo.py:184—handle_todo_command删除 prompt builder/renderer 路由,保留 list、add、plan 与 lifecycle 调用;不会留下指向已删除模块的 import。loopx/cli_commands/todo_argument_validation.py:459—validate_shared_todo_options删除 suggestion 特例及 Namespace 字段访问;--limit保留 list 原有含义。todo_error_payload同步删除已不可达的 suggestion 分支。examples/cli-control-plane-command-modularization-smoke.py:32— 原有断言仅忽略排版空白,继续检查完整提示内容。修复了命令帮助缩短后换行位置改变导致的误报,默认和窄终端均通过。
对主干的风险
这是明确的 CLI 兼容性变化:旧脚本的 todo suggest 和专用选项会报错,不保留别名。文档给出迁移边界:移除 prompt 生成步骤,使用现有 Agent 交互;todo plan 不被宣传为可直接替换的 suggestion 命令。没有删除持久化 Todo、journal、receipt 或 runtime shadow capture。无法从只读命令缺少事件计数证明所有外部脚本都未使用它,因此外部手工脚本迁移是保留风险。
最强反例是:一个包装新命令可以通过自己的测试,却仍保留全部旧机制,并用 open 列表判断当前是否有可执行工作。最终版本撤掉了这层判断;保留的 formal discovery、provider 读取与 quota/Turn 规则由既有 owner 负责。
语义与 CI 对齐
复用既有合同,没有新增状态分类、actor 权限或协议词汇。候选分析仍是 advisory,authoring 和 quota/Turn 约束仍由已有机制执行。按照选定 review 配置的 wait_for_ci=false 不等待远端 CI,不把旧 head 的 CI 结果算到新 head。
本地证据:CLI/action-selection 100 项及 list/planning/canonical-read/Turn 65 项通过;同一组输入通过真实 public CLI,在 legacy、实际 File/SQLite 和隔离本机状态快照上比较 12 组,11 组输出相同,仅 suggest 从 exit 0 改为 exit 2。File/SQLite 使用同一份 canonical store,revision 未被归一化;仅归一化隔离路径。既有 Todo CLI/event-projection smoke、Ruff、22 个声明源文件的 mypy、wheel/sdist 及全新 wheel CLI 验证通过。最终 risk canary 19/19 通过,零 manual hold;初次 help 换行断言失败已修复并保留证据。Public-boundary 检查零错误,两个已有本地状态警告与本 PR 无关。
我的整体评价
APPROVE。当前方案的收益是删除完整的独立 prompt 边界,同时保持实际工作读取、authoring、planning 和执行准入路径。相较新增 wrapper,这是可独立验证和回滚的完整收敛;未来重构检查已落实为删除,不遗留一个等待下一轮迁移的新模块。精确 scope 的质量凭据 cqr_adc85ec208524560b604 有效,policy revision 7 的完整结果检查通过。本 PR 改变公开 CLI,保留 maintainer merge 边界。
English verdict: APPROVE - 036ad621c70bd921333afd716a901fe303ead112. Directly retires the standalone suggestion command without a replacement wrapper; preserves existing Todo and quota ownership. 165 focused tests, real File/SQLite paired CLI checks, package readback and 19/19 risk canaries passed. CLI retirement is an intentional compatibility break; remote CI was not awaited under the selected review policy. Maintainer merge required.
There was a problem hiding this comment.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
Post-merge audit of #4725, merged into main as a20e71395c(PR head 036ad621c70bd921333afd716a901fe303ead112,merged 2026-09-19T07:45:56Z)。此前我对中间 head 17c187a06ea9cb9fb8b5d14d4ff315be6660123f 的阻塞项(KunlunCode 只读白名单未随 todo discover 重命名更新)随该 head 被 rebase 取代而失效;这篇只记录合并后 main 上仍成立的新发现。
动机
本 PR 声称把 todo suggest 统一为只读 todo discover。实际合入 main 的内容是更小的“退役 todo suggest/capture-followups”切片,并携带了“完整工作量计数”语义(新增 loopx/control_plane/todos/summary_lanes.ts、countTodoWork(..., complete, ...),改动 todo_summary.py/todo_semantics.py/list_projection.py/quota_selection*)。因此合并后需要回答的问题变成:这次计数语义变化是否与其契约消费者保持一致。
改动思路
作者选择的是“先退役无人调用的建议命令、保留 todo list 作为 quota 发现路径”,并在同一批次里统一工作量计数。方向本身自洽:删除死代码并把计数下沉到共享 helper(countTodoWork)比在各投影里各算一份更可维护。问题在于共享 helper 的输出形状属于公共契约,而守护该形状的 public smoke 没有被同步更新。
具体改动
loopx/control_plane/todos/summary_lanes.ts(新增):TODO_SUMMARY_LANES与countTodoWork(rows, sourceOpenCount, complete, agentId),返回值包含complete布尔字段;loopx/control_plane/todos/list_projection.py的todo_summary_open_task_counts经该 helper 产出,于是多出complete键;examples/control_plane/todo-projection-shared-helper-smoke.py的三处严格相等断言(:398、:420、:448)仍按旧形状比较,未随新字段更新——这就是合并后 main 变红的直接原因;- 另:
loopx/kunluncode_goal_mode/guards.py:93的只读白名单仍写着{"list", "suggest"},其中suggest已不存在(死条目,当前不影响功能)。
对主干的风险
阻塞(合并后仍成立):examples/control_plane/todo-projection-shared-helper-smoke.py 在 a20e71395c 上失败:
AssertionError: {'open': 5, 'advancement': 3, 'monitor': 2, 'hidden': 0,
'complete': True, 'monitor_due': 1, 'monitor_schedule_gap': 1}
证据链:本地在 a20e71395c 复现同一断言;对照 9f1916960(本 PR squash 前的 main head,即 #4723)该 smoke 通过,说明是本 PR 的合并差分引入;CI 上表现为 full-public-smokes (2, 220) 与 (0, 0) 失败(后者是 cli-help-manpage,属于 #4706)并连带 smoke-fleet-health、merge-gate 红。另注意 Python Tests 的 test-shard (2) 是基础设施超时(Failed to CreateArtifact: ETIMEDOUT),非代码缺陷。
最小修复(二选一,由 owner 定权威侧):(1) 若 complete 计数是有意语义,更新该 smoke 的三处期望(至少加上 "complete": True);(2) 若旧公共形状才是契约,则把 complete 移出 todo_summary_open_task_counts 的返回。任一选择后请让 python examples/control_plane/todo-projection-shared-helper-smoke.py 与 Full Public Smokes 恢复绿色——该 smoke 只在 push 到 main 时运行,所以合并前没能拦住这次不一致。
非阻塞项:PR 描述与合并内容不一致(main 上不存在 todo discover/todo_candidate_discovery_v0/对应文档与 smoke),建议同步描述或协议索引;guards.py 的死条目建议下次一并清理。
我的整体评价
方向与范围我认可(删除无人调用的命令、计数下沉到共享 helper),但合并后的 main 确实因这次差分多了一条红的 public smoke,且该 smoke 守的正是共享计数 helper 的公共形状;在修复前这条 PR 的“已合并”状态不能视为绿灯交付。修复量很小,但需要 owner 明确 complete 字段是契约还是内部实现。
English verdict: REQUEST_CHANGES - post-merge audit of #4725 (merged as a20e713, PR head 036ad62): main's public smoke examples/control_plane/todo-projection-shared-helper-smoke.py now fails because the merged work-count change made shared_todo_summary_open_task_counts return an extra complete: True field while the smoke's strict-dict assertions (lines 398/420/448) still expect the old shape - reproduced locally, passing at the previous main head 9f19169 and failing at a20e713, visible in CI as full-public-smokes (2, 220) plus the aggregated smoke-fleet-health/merge-gate failures (the full-public-smokes (0, 0) failure is cli-help-manpage from #4706, and test-shard (2) failed on an artifact-upload ETIMEDOUT, not a test). Minimum repair: choose the authoritative shape, update the smoke expectations (or drop the field), and include Full Public Smokes in pre-merge validation for shared todo summary helper changes. Also noted: the merged content is the smaller "retire suggest" slice without the todo discover unification described in the PR body, and kunluncode_goal_mode/guards.py still allowlists the removed suggest.
Retire the standalone
todo suggestprompt command and its implementation. Candidate discovery continues through the current agent and existing Todo read/authoring paths; quota keeps its existingtodo listroute and response shape. This removes an unnecessary migration surface without introducing a replacement command or protocol.Behavior and compatibility
todo suggest, its dedicated--from/--triggeroptions, the prompt builder/renderer, protocol document and implementation-only smoke.todo list,todo add,todo plan, and current quota/Turn selection and revalidation. An open Todo or bounded list does not establish execution eligibility or a complete frontier.todo discover, automatic proposal generation, or automatic promotion is added.Only the public CLI and its documentation change. Caller searches found no frontend, Lark or host consumer of the removed builder; those entrypoints need no companion UI change. This builds on merged #4723 and supports #4574's reduction of duplicate control-plane surfaces, without claiming provider-default cutover.
Validation
suggestretirement (exit 0 to exit 2). Shared canonical stores preserve exact revisions; normalization covers fixture paths only.COLUMNS=50after correcting a whitespace-sensitive help assertion; the initial failure is retained in local evidence.canary premerge --from-git-diff: 19/19 selected checks passed, no manual holds. Exact quality receiptcqr_adc85ec208524560b604verified. Remote CI is not waited for under the selected review configuration.The future-facing simplification removes the entire unused prompt boundary and reuses existing owners. This is a disclosed CLI compatibility break; no persisted-state migration is needed. Maintainer merge is required.