Skip to content

Clear completed_at when a todo is reopened - #348

Merged
tylerreckart merged 9 commits into
mainfrom
fix/todo-reopen-clear-completed-at
Sep 21, 2026
Merged

tylerreckart merged 9 commits into
mainfrom
fix/todo-reopen-clear-completed-at

Conversation

@cursor

@cursor cursor Bot commented Sep 16, 2026 •

Copy link
Copy Markdown
Contributor

Problem

PATCH /v1/todos/:id (and batch PATCH) accept a non-terminal status (pending / in_progress), which is the HTTP reopen path. update_todo auto-stamped completed_at when moving to completed or canceled, but left the stamp in place on reopen.

Storage and docs say completed_at = 0 until terminal. A completed-then-reopened row kept a non-zero timestamp, so list/get JSON, UIs that treat completed_at > 0 as done, and any client filtering on that column were wrong. Subject/description edits on a still-terminal row were already correct (leave the stamp).

Writ /todo start only resolves against open rows, so this was HTTP-only — but PATCH is the supported reopen API.

Fix

When status is set and the caller did not pass completed_at:

  • terminal → stamp now() (unchanged)
  • non-terminal → write completed_at = 0

An explicit completed_at argument still overrides. Header, concept, and PATCH docs match the store.

Tests

unit_todos — reopen from completed→pending and canceled→in_progress clears the stamp; explicit override on reopen is honored; subject edit after completed does not clear. Suite 10/10 locally (+ ASan, 154 assertions). arbiter compiles.

Independently mergeable against main (0456350). merge-tree vs #321–#347: code auto-merges (update_todo / test_todos are disjoint from those hunks); only CHANGELOG [Unreleased] sibling-conflicts after the first of those merges.

Open in Web View Automation 

Note

Low Risk
Localized todo persistence and API contract fix with new unit tests; no auth or cross-tenant behavior changes.

Overview
Reopened todos now reset completed_at. TenantStore::update_todo (single and batch PATCH /v1/todos) used to stamp completed_at on completed/canceled but left the old timestamp when status moved back to pending or in_progress. That broke the documented rule that completed_at stays 0 until a terminal status.

When status is present and completed_at is omitted, non-terminal statuses now write completed_at = 0; terminal statuses still auto-stamp now(). An explicit completed_at in the request still wins. Subject/description-only updates on a terminal row do not touch the stamp.

Docs (PATCH API, todos concept) and CHANGELOG match the store. unit_todos adds reopen, override, and non-clearing edit cases.

Reviewed by Cursor Bugbot for commit 2231e28. Bugbot is set up for automated code reviews on this repo. Configure here.

update_todo stamped completed_at on terminal status but never cleared it
when PATCH moved the row back to pending or in_progress. HTTP reopen then
violated the documented completed_at=0-until-terminal contract.

Co-authored-by: Tyler Reckart <tylerreckart@users.noreply.github.com>
@tylerreckart
tylerreckart marked this pull request as ready for review September 21, 2026 12:58
@tylerreckart
tylerreckart enabled auto-merge (squash) September 21, 2026 12:58
@tylerreckart
tylerreckart merged commit 8e6fc0f into main Sep 21, 2026
2 of 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.

3 participants