feat(todos): JSON argv form for the completion validation command - #3255
Conversation
huangruiteng
left a comment
There was a problem hiding this comment.
PR #3255 全量双语评审 — Todo Completion Validation JSON argv Form
精确评审头(Exact Head): 3255@5f4134c808021d90c4d274fe3711522ee52b17ac
Base: main | 类型: runtime behavior(8 files, +260/-32) | 作者: NIU-123370
详细中文评审
动机
完成校验命令此前只有单一 plain-string 形式(shlex 解析),而 run-once 路径已经有 JSON argv 先例;#3142 review 的最后一项 P2 就是补上 argv 形式。PR 让 todo add 接受 --validation-command-json(非空 JSON 字符串数组、两形式互斥、可配 timeout),持久化为 validation_command_argv,并在执行时走无 shell 解析的 validation_argv 通道;旧 shlex 形式与 issue_fix 调用方完全不变。动机真实且是明确的收尾项。
改动思路
双形式并存 + fail-closed:写入侧 _normalize_validation_command_json 与互斥检查前置校验;存储侧把 argv 序列化为 JSON 字符串写入 todo metadata;读取侧 _read_declared_validation 解析失败时折叠为 [](而非 None),让损坏声明仍触发 gate 并输出 command_malformed receipt,绝不静默跳过校验;执行侧 run_caller_validation 强制「command 与 argv 二选一」,argv 无 shell 解析。timeout 语义对两种形式一致。
具体改动
loopx/cli_commands/todo.py(+17/-3):新增--validation-command-json参数并透传到 add;帮助文本更新。loopx/control_plane/runtime/validation_command.py(+17/-3):validation_argv通道(无 shell),command/argv 二选一强校验。loopx/control_plane/todos/completion_validation.py(+81/-23):读取/运行声明校验,损坏 argv →[]fail-closed,command_malformedreceipt。loopx/todos.py(+43/-2):_normalize_validation_command_json、互斥校验、metadata 写入。loopx/control_plane/todos/contract.py(+2):metadata 允许validation_command_argv。loopx/canary/module_metric_baseline.json(+1/-1):todos.py 2190→2229(诚实 bump)。tests/control_plane/test_todo_completion_validation.py(+129):10 个新测试。
关键代码讲解
run_caller_validation(validation_command.py):if (validation_command is None) == (validation_argv is None): raise——精确二选一;argv 直接[str(item) for item in validation_argv],不经过 shlex。P2:空 argv 的报错文案仍写死"validation_command must not be empty",对 argv 形式建议改为中性的"validation command must not be empty"。_read_declared_validation(completion_validation.py):persisted argv 解析失败 →validation_argv=[](不是 None),配合_run_declared_completion_validation的validation_argv is not None判断,使损坏声明仍进入 gate 并产出command_malformed——这是本 PR 最有价值的 fail-closed 细节。_normalize_validation_command_json(todos.py):与 Turn-level 先例一致的 shape 规则(非空 list、全非空 str),写入前抛ValueError。- 互斥与 timeout 绑定:
--validation-command与--validation-command-json同时给 → ValueError;--validation-timeout-seconds现在对两种形式都有效。
正向路径
todo add --validation-command-json '["pytest","-q","tests/test_x.py"]' --validation-timeout-seconds 20 → 存储 argv → complete 时读回并解析 → argv 无 shell 直接执行 → exit 0 → passed=True → 完成提交;exit≠0 → passed=False 阻断完成。
负向路径
非 JSON/非数组/空数组/含非 str → 写入前拒绝;两形式同给 → 拒绝;persisted argv 被损坏 → 折叠为 [] → gate 运行并返回 command_malformed receipt(不静默跳过);timeout → timeout receipt 且不提交;无任何声明 → 原 fast path 不变。
对主干的风险
阻断项(P1,流程/CI):Sign-off(DCO)check FAILURE——commit 5f4134c8 的 message 无 Signed-off-by trailer(已用 git log 核实)。补 sign-off 后重推即可。
非阻断(P2):
- pytest 评审时刻 IN_PROGRESS:dependency-review/build 已 SUCCESS;
tests/control_plane/test_todo_completion_validation.py在 exact head 独立复现 20 passed(含 10 个新测试)。合并前确认全量 pytest 变绿。 - 空 argv 报错文案:
run_caller_validation的ValueError("validation_command must not be empty")在 argv 通道同样触发,建议改为中性文案并顺带覆盖。
验证矩阵(exact head 实测):
| 场景 | 结果 |
|---|---|
tests/control_plane/test_todo_completion_validation.py |
20 passed |
| commit sign-off trailer | 缺失 → 解释 Sign-off FAILURE |
| GitHub checks | dependency-review/build SUCCESS;Sign-off FAILURE;pytest IN_PROGRESS |
| 兼容性 | 旧 shlex 形式与 issue_fix 调用方代码路径未动(代码核对) |
我的整体评价
实现正确且收敛:argv 通道无 shell 解析、写入前校验、损坏声明 fail-closed、timeout 双形式一致、legacy 路径不动、测试覆盖正反路径(20 passed 含 10 新),baseline bump 诚实。唯一阻断是 DCO sign-off;补签后即可放行。结论:REQUEST_CHANGES(窄化到 sign-off 修复)。
English Verdict
Verdict: REQUEST_CHANGES — exact head 3255@5f4134c808021d90c4d274fe3711522ee52b17ac.
Summary: A well-scoped feature adding a JSON argv form for the todo completion-validation command: mutual exclusivity, upfront shape validation, a no-shell validation_argv execution channel, corrupted persisted declarations failing closed as command_malformed, timeout pairing with both forms, and legacy shlex behavior untouched. 20 validation tests pass at the head (10 new); dependency-review and build are green.
Blocking (P1): DCO Sign-off FAILS because commit 5f4134c8 lacks a Signed-off-by trailer (verified via git log). Add the sign-off and re-push.
P2 (non-blocking): confirm CI pytest turns green before merge; make the empty-command error message form-neutral (it currently says "validation_command must not be empty" even for the argv channel).
The completion-validation command was a plain string split with shlex. Add the run-once precedent's argv form alongside it: todo add accepts --validation-command-json, a JSON string array validated up front (non-empty, all strings) and persisted in the todo metadata as validation_command_argv. The two forms are mutually exclusive; --validation-timeout-seconds now pairs with either. The gate runs the argv form through run_caller_validation's new validation_argv channel (no shell parsing); the legacy shlex form is unchanged, and todos without either keep the no-command fast path. A persisted argv that fails to parse collapses to an empty list rather than None, so a corrupted declaration still runs the gate and fails closed as a command_malformed receipt instead of silently skipping validation. Signed-off-by: 牛瑞博 <912906590@qq.com>
5f4134c to
6c7845d
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
PR #3255 全量双语评审(re-review)— Todo Completion Validation JSON argv Form
精确评审头(Exact Head): 3255@6c7845dcb4e16251272528fa602a8329c230fd0e
Base: main | 类型: runtime behavior(8 files, +260/-32) | 作者: NIU-123370
详细中文评审
动机
上一轮评审(3255@5f4134c8)的阻断项是 DCO Sign-off 缺失,非阻断项是确认 CI pytest 变绿与空命令报错文案的中性化。本次新 head 6c7845dc 是作者重建后的分支:commit message 已带 Signed-off-by trailer,GitHub Sign-off check 由 FAILURE 转为 pass;pytest 全量 CI 也由 IN_PROGRESS 转为 pass。实现动机不变——完成校验命令此前只有 plain-string(shlex)形式,本 PR 补齐 run-once 路径已有的 JSON argv 形式,是 #3142 review 的收尾项。
改动思路
双形式并存 + fail-closed 的思路保持不变:写入侧 _normalize_validation_command_json 做形状前置校验(非空 JSON 字符串数组,与 Turn-level 先例同规则);存储侧持久化为 validation_command_argv metadata;读取侧解析失败折叠为 [](绝不退化成 None),让损坏声明仍触发 gate 并产出 command_malformed receipt;执行侧 run_caller_validation 强制 command/argv 二选一,argv 通道不做任何 shell 解析;legacy shlex 形式与 issue_fix 调用方保持兼容。
具体改动
loopx/canary/module_metric_baseline.json(+1/-1):loopx/todos.py2190→2229 的诚实 baseline bump。loopx/cli_commands/todo.py(+17/-3):新增--validation-command-json参数、透传与帮助文本;timeout 帮助改为两种形式均适用。loopx/cli_commands/todo_argument_validation.py(+1):参数白名单补validation_command_json。loopx/control_plane/runtime/validation_command.py(+17/-3):签名变为validation_command/validation_argv二选一,argv 直接[str(item) for item in ...],无 shlex。loopx/control_plane/todos/completion_validation.py(+58/-23):读取/运行声明校验,损坏 argv →[]fail-closed,command_malformedreceipt;fast path 仅当两种形式都未声明时生效。loopx/control_plane/todos/contract.py(+2):metadata 允许validation_command_argv并随行渲染。loopx/todos.py(+41/-2):_normalize_validation_command_json、互斥校验、validation_command_argv写入。tests/control_plane/test_todo_completion_validation.py(+129):10 个新测试覆盖 argv 通过/失败阻断、互斥、5 类非法 payload、timeout+argv、损坏持久化声明 fail-closed。
关键行为讲解
run_caller_validation:(validation_command is None) == (validation_argv is None)时抛错,保证精确二选一;argv 形式零 shell 解析。_read_declared_validation:persisted argv 非 JSON/非空字符串数组 →[];配合_run_declared_completion_validation的validation_argv is None判断,损坏声明仍进入 gate,返回command_malformed,绝不静默跳过。_normalize_validation_command_json:非数组/空数组/含非字符串/空字符串均在写入前ValueError拒绝。- 兼容性:issue_fix 的
acceptance_loop.py仍以validation_command=关键字调用,签名兼容;旧 shlex 路径代码未动。
正向路径
todo add --validation-command-json '["pytest","-q","tests/test_x.py"]' --validation-timeout-seconds 20 → 持久化 argv → complete 读回 → argv 无 shell 直接执行 → exit 0 → 完成提交;exit≠0 → 阻断完成。
负向路径
非法 JSON/非数组/空数组/非 str → 写入前拒绝;两种形式同给 → 互斥拒绝;持久化 argv 损坏 → [] → command_malformed 阻断;timeout → timeout receipt 且不提交;无声明 → 原 fast path。
对主干的风险
无阻断项(P1 已解决):commit 6c7845dc 含 Signed-off-by: 牛瑞博 <912906590@qq.com>,Sign-off check pass;GitHub checks 全绿(Sign-off/build/dependency-review/pytest 均 pass,publish-pypi/upload-release 为 skipping)。
非阻断(P2,沿用上轮):run_caller_validation 的空命令报错文案仍是 "validation_command must not be empty",在 argv 通道(损坏声明折叠为 [] 后)同样触发;建议改为形式中性的 "validation command must not be empty",可在后续小 PR 顺手覆盖。
验证矩阵(exact head 实测):
| 场景 | 结果 |
|---|---|
tests/control_plane/test_todo_completion_validation.py |
20 passed(exact head,uv test extra) |
| commit sign-off trailer | 存在 → Sign-off check pass |
| GitHub checks | Sign-off/build/dependency-review/pytest 全 pass |
| issue_fix 调用方 | validation_command= 关键字兼容(代码核对) |
| 兼容性 | 旧 shlex 形式与 fast path 未动(代码核对) |
我的整体评价
上轮唯一阻断项(DCO)已修复,CI 全绿,exact head 上 20 个 focused 测试独立复现通过;argv 通道无 shell 解析、写入前校验、损坏声明 fail-closed、timeout 双形式一致、legacy 路径兼容,实现收敛且测试覆盖正反路径。仅剩一个非阻断的报错文案中性化 P2。结论:APPROVE。
English Verdict
Verdict: APPROVE — exact head 3255@6c7845dcb4e16251272528fa602a8329c230fd0e.
Summary: The DCO blocker from the previous review is resolved — the rebuilt head carries Signed-off-by and the Sign-off check passes; CI is fully green (Sign-off, build, dependency-review, pytest). At the exact head, the focused completion-validation suite passes 20/20, and the issue_fix caller remains compatible with the new validation_argv channel. Non-blocking P2: make the empty-command error message form-neutral ("validation command must not be empty").
The runner's empty-command error said "validation_command must not be empty" even when triggered by the argv channel. Make the message form-neutral and cover it with a focused receipt assertion, per the huangruiteng#3255 review. Signed-off-by: 牛瑞博 <912906590@qq.com>
|
Both items addressed:
CI pytest is green on |
huangruiteng
left a comment
There was a problem hiding this comment.
PR #3255 全量双语评审(re-review 2)— Todo Completion Validation JSON argv Form
精确评审头(Exact Head): 3255@b2f875c6bcd7b922799f0311ebf5c7aec2e9648b
Base: main | 类型: runtime behavior(8 files, +260/-32,本轮 delta +20/-1) | 作者: NIU-123370
详细中文评审
动机
在 3255@6c7845dc 的 APPROVE 中,唯一非阻断项(P2)是空命令报错文案仍写死为 "validation_command must not be empty",在 argv 通道(损坏声明折叠为 [] 后)同样触发,建议改成形式中性的措辞。作者随即推送 b2f875c6,把该文案改为 "validation command must not be empty" 并新增一个 focused receipt 断言,是对上一轮评审的直接回应。
改动思路
保持上一轮已确认的双形式并存 + fail-closed 设计不变,本轮只做最小修复:run_caller_validation 的空 argv 报错不再绑定 validation_command 名称,避免 argv 通道的 command_malformed receipt 文案误导;测试侧直接调用 _run_declared_completion_validation(validation_argv=[]),断言 receipt 为 command_malformed 且 summary 含中性文案。不触碰执行语义、shlex 路径或任何其他行为。
具体改动
loopx/control_plane/runtime/validation_command.py(+1/-1):raise ValueError("validation command must not be empty")——仅文案,无行为变化。tests/control_plane/test_todo_completion_validation.py(+19):新增test_empty_argv_declaration_reports_neutral_message,覆盖空 argv 声明 →command_malformed+ 中性文案。- 其余 6 个文件与
6c7845dc完全相同(argv 通道、fail-closed、互斥校验、timeout、baseline bump)。
关键行为讲解
- 空命令检查:
run_caller_validation在not argv时抛ValueError;文案现在对 command 与 argv 两种形式都成立。 - 损坏声明路径:persisted argv 解析失败折叠为
[]→ 仍进入 gate →command_malformedreceipt,新测试直接断言该 receipt 的中性 summary。
正向路径
与上一轮一致:--validation-command-json '["pytest","-q","tests/test_x.py"]' → 持久化 → 无 shell 执行 → exit 0 → 完成提交。
负向路径
非法 JSON/非数组/空数组/非 str → 写入前拒绝;两形式同给 → 互斥拒绝;持久化 argv 损坏 → [] → command_malformed(新测试覆盖中性文案);timeout → timeout receipt;无声明 → fast path。
对主干的风险
无阻断项。commit b2f875c6 含 Signed-off-by,Sign-off/build/dependency-review 均 pass;exact head 上 focused 套件 21 passed(含新测试)。唯一观察项:pytest CI 在本轮评审时刻 pending(delta 仅文案+测试,本地 focused 套件已全绿),合并前确认全量 pytest 变绿即可。
验证矩阵(exact head 实测):
| 场景 | 结果 |
|---|---|
tests/control_plane/test_todo_completion_validation.py |
21 passed(exact head,uv test extra) |
| delta 范围 | 2 files, +20/-1,仅文案 + 1 个 focused 测试 |
| commit sign-off | 两个 commit 均含 Signed-off-by → Sign-off check pass |
| GitHub checks | Sign-off/build/dependency-review pass;pytest pending |
| 兼容性 | 执行语义与调用方未变(代码核对) |
我的整体评价
上一轮 APPROVE 的唯一 P2 已按建议修复并有 focused 测试兜底;改动极小、语义不变、无新增风险。结论:APPROVE。
English Verdict
Verdict: APPROVE — exact head 3255@b2f875c6bcd7b922799f0311ebf5c7aec2e9648b.
Summary: The last P2 from the prior review is resolved: the empty-command error is now form-neutral ("validation command must not be empty") and covered by a new focused receipt assertion. The delta is 2 files (+20/-1) with no behavior change; 21/21 focused tests pass at the exact head, Sign-off/build/dependency-review are green, and the full pytest CI was pending at review time.
Summary
Lands the last P2 flagged in the #3142 review: the completion-validation command had a single plain-string form parsed with shlex. This adds the argv form the run-once path already uses.
todo addaccepts--validation-command-json— a JSON string array, validated up front (must be a non-empty array of non-empty strings, same shape rule as Turn-level--validation-command-json). It persists as a newvalidation_command_argvmetadata field; the two forms are mutually exclusive, and--validation-timeout-secondsnow pairs with either.run_caller_validationgains avalidation_argvchannel (no shell parsing;validation_commandkeeps the shlex path untouched, so existing declarations and the issue_fix callers are unaffected).[], notNone— a corrupted declaration still runs the gate and surfaces acommand_malformedreceipt instead of silently skipping validation.Verification
pytest tests/control_plane/test_todo_completion_validation.py— 20 passed (10 new: argv pass/fail, mutual exclusion, 5 malformed payloads via parametrize, timeout-with-argv, corrupted persisted argv fails closed)pytest tests/canary/(incl. maintainability ratchet) — 20 passed;loopx/todos.pybaseline bumped 2190 → 2229 (honest bump)mypy— new/changed modules clean;loopx/todos.pycarries the same 4 pre-existing errors as mainRefs #3142 (final P2; the first two landed in #3209 and #3210).