fix(list): keep project to-dos out of someday - #228
Merged
Merged
Conversation
Closes #211 Things' Someday list holds the deferred things you have not filed under a project. A to-do inside a project stays inside it however it is deferred: the app shows it greyed within the project rather than in the global list. The CLI returned those to-dos, so `things list someday` answered a different question from the one the app answers. The view gains p.uuid IS NULL. Because p resolves through COALESCE(t.project, h.project), a to-do filed under a project heading is excluded by the same clause rather than slipping through as unparented. Project rows have no parent project, so they still list (issue #206). The rule was measured, not assumed. The issue proposed excluding Someday to-dos whose parent project is not itself in Someday, but the database held no Someday projects, so that could not be told apart from the simpler rule. With the user's approval a throwaway project was created in Things, in Someday and holding one Someday to-do, and the app's own list membership read back: the project appeared in Someday, the child did not. The test is the presence of a parent, not the parent's bucket. The probe was deleted afterwards and the app's list is back to its 6 rows. Verified by uuid: the app lists 6, the CLI listed 15 before and 6 after, with no difference in either direction. The nine dropped are the eight named in the issue plus GXHKQn2Y12ChTiGXLdqQvB. --project on someday now errors instead of returning an empty list: the clauses contradict, so it could never match. It names the view and points at `things --project NAME`, the same call issue #124 made for date filters on this view.
ryanlewis
force-pushed
the
fix/issue-211-someday-parent
branch
from
September 10, 2026 11:39
80e6261 to
d0988cf
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #211
What changed
somedaynow returns only rows with no parent project. Things' Someday list is the deferred things you have not filed under a project: a to-do inside a project stays inside that project however it is deferred, and the app shows it greyed within the project rather than in the global list. The CLI returned those to-dos, sothings list somedayanswered a different question from the one the app answers.The view gains
p.uuid IS NULL. Becausepis resolved throughCOALESCE(t.project, h.project), a to-do filed under a project heading is excluded by the same clause rather than slipping through as unparented. Project rows have no parent project of their own, so they still list, which is what #206 established.The rule was measured, not assumed
The issue proposed excluding Someday to-dos "whose parent project is not itself in Someday". That is not the rule, and the difference mattered enough to test rather than guess.
Two rules fit the existing data equally well, because every one of the nine to-dos the CLI wrongly returned had an Anytime parent:
They differ only for a Someday to-do inside a Someday project, and this database contained no Someday projects at all, so the discriminating case did not exist. With the user's approval I created it through the app and measured it.
A throwaway project
PROBE-someday-20260910-122504was created in Things via AppleScript, moved to Someday, given a deadline, and one to-do added inside it via thethings:///addURL scheme withwhen=someday, so that both project and child sat in Someday with the child properly parented. Reading the app's own list membership:The app's Someday list went from 6 rows to 7, gaining only the project. So the test is the presence of a parent, not the parent's bucket: rule B. The probe project also appeared in the app's
Later Projectslist, which is where Things files deferred projects, and that list was empty before and after.Both probe items were then deleted through the app. The app's Someday list is back to 6,
Later Projectsback to 0, and the four probe rows sit in the Trash.Verified against the real database
With rule B implemented,
things list somedayreturns 6 rows and the app's Someday list holds 6, with no difference in either direction by uuid.list somedaybeforelist somedayafterThe nine dropped are the eight named in the issue plus
GXHKQn2Y12ChTiGXLdqQvB, which the issue did not list. All nine are Someday to-dos with an Anytime parent project.--projectonsomedayis now an errorNarrowing this view to a project asks for the contents of a project the view has already excluded, so the two clauses contradict and the listing is empty whatever the project holds. On
mainthat command listed a project's deferred to-dos, so leaving it silently empty would have been a regression with no explanation attached.It now fails with an error naming the view and pointing at
things --project "Name", which does return a project's own deferred to-dos. That follows the precedent this repo already set twice: #124 rejects date filters on this same view for the same reason, and--include-completedis rejected everywhere buttoday. Both the flag form and the positional form (things someday "Name") are covered.This is a small CLI surface change rather than something #211 asked for, so it is worth a reviewer's eye. The alternative is a command that returns nothing and says nothing.
Tests
Five tests in
internal/db/tasks_test.goover a newseedSomedayParentshelper, which seeds an Anytime parent and a Someday parent so the discriminating case is in the fixture rather than only in the prose:--areastill finds the project row and the unparented to-do, and--projectcan no longer match anything hereanytimeTestRunListSomedayRejectsProjectFilterincmd/things/run_test.gocovers the new error in both its flag and positional forms, and asserts baresomedayandsomeday --areastill work.TestTemplateProjectChildrenExcludedFromOpenViewsdrove each view with a template's child and an ordinary project's child, expecting the ordinary one to list. Someday no longer carries either, so that sibling cannot exist there and the case has moved toTestTemplateChildExcludedFromSomeday, which asserts both children stay out while a top-level to-do and a Someday project row still list. Coverage of the template guard on this view is kept, not dropped.Docs
internal/skill/SKILL.md,docs/content/commands.md,docs/content/agents.mdandREADME.mddescribe Someday as the deferred things not filed under a project, say explicitly that the rule holds even when the parent project is itself in Someday, and point atthings --project "Name"for a project's own deferred to-dos.