Skip to content

fix(tui): let todo items default to a pending status - #148

Open
asto18089 wants to merge 1 commit into
pinvou3-cleanfrom
fix/todo-status-optional
Open

asto18089 wants to merge 1 commit into
pinvou3-cleanfrom
fix/todo-status-optional

Conversation

@asto18089

Copy link
Copy Markdown
Collaborator

Problem

The todo_write item schema listed status among the required item fields, but the executor has always read a missing status as TodoStatus::Pending (crates/tui/src/tools/todo.rs). "Leave status out = new pending todo" is the tool's real contract, so the schema was stricter than the execution semantics and declared a valid call shape invalid — exactly the failure mode the toolset contract's "minimize required parameters / if leaving it blank is business-sane, it must not be required" rule exists to prevent.

Document evidence (repository contract, no external provider doc involved)

  • Executor semantics: TodoStatus defaults to Pending for a missing status — the execution path is the authority for what the tool accepts (crates/tui/src/tools/todo.rs).
  • Toolset contract principle: required parameters must be minimized; a field whose omission has sensible business meaning (a new todo starts pending) must not be required.
  • Upstream comparison: upstream pins content+status required, so relaxing status is fork-distinct behavior — flagged for the fork-modifications register.

Changes (head ef7a1d9a9)

  • required on todo items narrows to ["content"]; status leaves the list.
  • The status description now states the default where the model reads it: "Task status. Defaults to pending when omitted."
  • content stays required — an item without text is not a todo.

Test evidence

  • todo_item_status_is_optional_with_a_pending_default asserts the schema's required and the stated default in the description.
  • work_update_treats_a_missing_status_as_pending executes a status-less item end-to-end and asserts the resulting checklist entry is pending.

Behavior changes

  • Model callers may omit status on a todo item; the executor records it as pending, matching behavior that already existed.
  • Explicit status values behave exactly as before.

Merge-conflict surface with #137

This branch edits crates/tui/src/tools/todo.rs only; it does not touch crates/tui/src/client/chat.rs or the use crate::config::{...} block that #137 (fix/kimi-k31-replay-spellings) edits, so there is no conflict surface with #137.

Probe declaration

No live probes were used in this change; the schema relaxation is derived from the executor's existing default, verified by the two tests above.

No-Issue: provider compatibility batch grounded in the published provider docs (fetched 2026-11-05); the repository has issues disabled.

The schema listed status among the required item fields, but the
executor reads a missing status as TodoStatus::Pending — 'leave status
out = new pending todo' is the tool's real contract, so the schema was
stricter than the execution semantics and a valid call shape was
declared invalid. status leaves required (content stays: an item
without text is not a todo) and the status description states the
default where the model reads it. Fork-distinct behavior change versus
the upstream schema (upstream pins content+status required); flagged
for the fork-modifications register.

Signed-off-by: asto <asto18089@126.com>
@asto18089

Copy link
Copy Markdown
Collaborator Author

Fresh 10-lane review — APPROVE (head ef7a1d9a9 @ base 11cba403d, rebase-verified as the latest tip)

Reviewed from scratch with 10 independent lanes: claim/root-cause, diff purity, whole-class audit, runtime-enforcement + work-surface path, elegance/precedent, mutation testing, adversarial input hunt, conventions/CI, parent-repo integration, and a final fresh-eyes adversarial pass. No P0/P1/P2 found.

Root cause confirmed, and the fix aligns with documented project intent. The executor has always read a missing status as TodoStatus::Pending (crates/tui/src/tools/todo.rs:339, byte-identical on base), while the schema — born at the v0.1.0 initial commit (6f1158a2d) and never deliberately examined since — pinned required: ["content","status"]. The same initial file's sibling todo_add already used the correct pattern (required: ["content"] + "(default: pending)" description), and the codewhale-hq#5123-class fail-fast commit (7e489fe64) explicitly stated "Missing status still defaults to pending, which is the documented shape" without touching the schema. Upstream (codewhale-hq/Codewhale, crates/engine/src/tools/todo.rs:285) carries the same never-examined inheritance, so the fork-distinct disclosure is accurate. After this PR, no schema-compliant todo_write call can fail at runtime.

Verification performed:

  • Mutation testing: reverting required, reverting the description, or changing the executor default each fails exactly the intended new test, with zero collateral kills; the required-assertion is exact-match and deterministic (registry canonicalization operates on a copy).
  • Provider lanes: the only strict lane (DeepSeek /beta strict_tool_mode, opt-in) re-tightens via enforce_strict_subset (all properties required + nullable: true), which is semantics-preserving because JSON null lands in the executor's None => Pending arm; the Moonshot MFJS whitelist passes required/description/enum through; no local runtime schema validation exists, so the declared shape is now truthful everywhere.
  • Hostile inputs (null/number/object status, empty/whitespace content, duplicates, 10k items, Unicode-whitespace aliases, empty replacement, consecutive calls) all terminate in executor arms byte-identical to base; O(n) behavior unchanged; no schema persistence/replay staleness path; combined state with open siblings fix(tui): hold Moonshot tool schemas to the MFJS docs #143/fix(tui): ship Anthropic input schemas verbatim #146 is complementary, not conflicting.
  • Class audit: this was the only shipped instance of "schema-required but executor-defaulted" in the repo — the declared class is fully fixed.
  • Purity: exactly one file, +46/−2 as declared, no deletions beyond the two schema lines, body claims map 1:1 to the diff, DCO clean, no probe artifacts or secrets.
  • CI: all 14 checks green at the current head SHA; the required 4 contexts passed and fork-ci's workspace cargo nextest run compiled and executed both new tests remotely. Locally: tools::todo 10/10 green in a clean worktree.

Non-blocking notes:

  1. Parent-side backflow is time-sensitive: once this merges, pinvou3-clean tip diverges from the parent gitlink and verify-public-submodule.sh goes fail-closed red repo-wide until the same-day backflow PR lands (gitlink bump + fork-guard.sh EXPECTED_HEAD/EXPECTED_COMMITS 93→94 + docs/fork-modifications.md §0/§3, per the feat: per-cell thinking fold/unfold via Space key codewhale-hq/Codewhale#2385 template). The forward declaration in the commit message is the correct CodeWhale-side form per precedent (feat(provider): add Tachyon reasoning controls #113 → parent v0.8.60: Sub-agent checkpoint and continue child work across turns codewhale-hq/Codewhale#2029, fix(route): honor custom table wire on runtime routes #79 → parent feat(permissions): external_directory gate + broader-pattern always-allow (#411 #412) codewhale-hq/Codewhale#625).
  2. Recommended at backflow time: two fingerprint pins for todo_item_status_is_optional_with_a_pending_default and work_update_treats_a_missing_status_as_pending — neither is forkguard_-prefixed, so without pins the fork-distinct schema behavior rides unpinned (silent pass) in every parent-side layer.
  3. Pre-existing (adjacent, not introduced here): the status enum is only weakly pinned (contains-"cancelled"; dropping "pending" from the enum passes the whole module — exact-equality assertion would close it); wrong-typed status (null/number) silently coerces to pending while unknown strings fail fast; empty/whitespace content is accepted (the test comment "an item without text is not a todo" overstates what required enforces); the missing-status test exercises the fallback branch, not the attached-graph branch of publish_todo_snapshot.
  4. Follow-up batch candidate (opposite direction, different failure mode): rlm.rs and github/mod.rs unified schemas declare no required while the executor enforces per-action fields (P1-class), plus automation/harness/send_later/coord (P2) — worth a tracked sibling batch consistent with fix(tui): hold Moonshot tool schemas to the MFJS docs #143–fix(tui): let todo items default to a pending status #148.
  5. Cosmetic: the No-Issue footer's "grounded in the published provider docs" wording is inherited from the provider-docs siblings (this PR's grounding is the repository contract, which its body states correctly); the body lacks the explicit red-green claim siblings fix(tui): pass xAI root unions of object branches through #144–fix(tui): ship Anthropic input schemas verbatim #146 include; PR title and commit subject drift slightly. docs/TOOL_SURFACE.md:44 still describes the item shape as {content, status}.
  6. Since the same mismatch exists upstream and the fix is generic, consider carrying it upstream (precedent: fix(config): 严格直连 provider 大小写不敏感匹配自身目录行 #14 → upstream fix(config): resolve owned direct model casing safely codewhale-hq/Codewhale#5475).

Ready to merge from my side, contingent only on the standing same-day parent backflow practice.

@JensenChen28 JensenChen28 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

已审查固定 head ef7a1d9a91f7b613d61730a22de259dd70bf8b79,base 11cba403dc6bd6ca5c4dca55042785b03449ac8e。规范与需求两个轴均无实质问题,批准本 PR。

schema 允许省略 item.status,并说明默认为 pending,与既有执行器一致;todos/content 仍必填,显式状态枚举、错误处理、列表替换及发布流程未变。已追踪 fallback 与 attached Work graph 接收同一个已定型 snapshot 的路径;新增 async 测试覆盖的是 fallback,未将其视为完整图集成或 provider 测试。

实际验证:fetch 最新 base/head、完整 diff/调用链检查、git diff --check、从实际 Rust 源码提取 JSON schema 并验证 required/enum,以及比较确认生产代码仅两处 schema 变更、执行器未改。只读核对该 head 的远程检查均通过(sync 跳过)。本机未运行 Cargo/Rust 或真实 provider 请求,作者测试计数属于外部证据。父仓消费 gitlink 时的 fork 登记/指纹与集成验证仍由对应父仓变更处理;本审核未执行该集成。发送前已核对最新 head/base 和讨论未变化。

@zhuowp zhuowp left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approve ef7a1d9a91f7b613d61730a22de259dd70bf8b79, reviewed against actual pinvou3-clean / merge-base 11cba403dc6bd6ca5c4dca55042785b03449ac8e.

Making item status optional aligns the model-facing schema with the existing executor's explicit Pending default. Item content and the outer list remain required; explicit status values, complete-list replacement and output checklist fields retain their existing contracts. The canonical todo_write and compatibility aliases share the real handler. The attached work-graph and detached-list consumers receive an explicit typed status, and invalid later items are rejected before publishing a replacement.

The v3 review covers the complete one-file change, all three fragments and both complete new test bodies, with registration, provider adaptation, execution, ownership and checklist consumers checked. No introduced blocking defect was confirmed. Exact-head CI executes both new tests successfully; its workspace nextest result is 15004 passed and 15 skipped. The executor-default test preserves an existing behavior; the schema test distinguishes the changed requirement.

This review does not claim live-provider, real-model, visible-terminal or packaged-release execution. Source approval does not override branch protection, merge-queue checks or release authorization.

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.

3 participants