Skip to content

feat(todos): JSON argv form for the completion validation command - #3255

Merged
huangruiteng merged 2 commits into
huangruiteng:mainfrom
NIU-123370:feat/validation-command-json
Aug 16, 2026
Merged

feat(todos): JSON argv form for the completion validation command#3255
huangruiteng merged 2 commits into
huangruiteng:mainfrom
NIU-123370:feat/validation-command-json

Conversation

@NIU-123370

Copy link
Copy Markdown
Contributor

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 add accepts --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 new validation_command_argv metadata field; the two forms are mutually exclusive, and --validation-timeout-seconds now pairs with either.
  • run_caller_validation gains a validation_argv channel (no shell parsing; validation_command keeps the shlex path untouched, so existing declarations and the issue_fix callers are unaffected).
  • Fail-closed detail: a persisted argv that fails to parse collapses to [], not None — a corrupted declaration still runs the gate and surfaces a command_malformed receipt 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)
  • all todo-related suites (14 files) — 162 passed
  • pytest tests/canary/ (incl. maintainability ratchet) — 20 passed; loopx/todos.py baseline bumped 2190 → 2229 (honest bump)
  • mypy — new/changed modules clean; loopx/todos.py carries the same 4 pre-existing errors as main

Refs #3142 (final P2; the first two landed in #3209 and #3210).

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_malformed receipt。
  • 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 个新测试。

关键代码讲解

  1. 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"
  2. _read_declared_validation(completion_validation.py):persisted argv 解析失败 → validation_argv=[](不是 None),配合 _run_declared_completion_validationvalidation_argv is not None 判断,使损坏声明仍进入 gate 并产出 command_malformed——这是本 PR 最有价值的 fail-closed 细节。
  3. _normalize_validation_command_json(todos.py):与 Turn-level 先例一致的 shape 规则(非空 list、全非空 str),写入前抛 ValueError
  4. 互斥与 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):

  1. pytest 评审时刻 IN_PROGRESS:dependency-review/build 已 SUCCESS;tests/control_plane/test_todo_completion_validation.py 在 exact head 独立复现 20 passed(含 10 个新测试)。合并前确认全量 pytest 变绿。
  2. 空 argv 报错文案run_caller_validationValueError("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>
@NIU-123370
NIU-123370 force-pushed the feat/validation-command-json branch from 5f4134c to 6c7845d Compare August 16, 2026 07:59
huangruiteng
huangruiteng previously approved these changes Aug 16, 2026

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.py 2190→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_malformed receipt;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。

关键行为讲解

  1. run_caller_validation(validation_command is None) == (validation_argv is None) 时抛错,保证精确二选一;argv 形式零 shell 解析。
  2. _read_declared_validation:persisted argv 非 JSON/非空字符串数组 → [];配合 _run_declared_completion_validationvalidation_argv is None 判断,损坏声明仍进入 gate,返回 command_malformed,绝不静默跳过。
  3. _normalize_validation_command_json:非数组/空数组/含非字符串/空字符串均在写入前 ValueError 拒绝。
  4. 兼容性: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 6c7845dcSigned-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>
@NIU-123370

Copy link
Copy Markdown
Contributor Author

Both items addressed:

  • P1 (DCO): the review ran against the old head 5f4134c8. The re-pushed head 6c7845dc carries the Signed-off-by trailer and the Sign-off check is green on it.
  • P2 (empty-command message): now form-neutral — validation command must not be empty — with a focused receipt assertion covering the argv channel collapsing to [] (head b2f875c6, signed). Full suite: 21 passed in test_todo_completion_validation.py, canary 20 passed.

CI pytest is green on 6c7845dc; the new head should follow shortly.

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)。

关键行为讲解

  1. 空命令检查run_caller_validationnot argv 时抛 ValueError;文案现在对 command 与 argv 两种形式都成立。
  2. 损坏声明路径:persisted argv 解析失败折叠为 [] → 仍进入 gate → command_malformed receipt,新测试直接断言该 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 b2f875c6Signed-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.

@huangruiteng
huangruiteng merged commit 92e4054 into huangruiteng:main Aug 16, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants