fix(list): include projects in deadlines - #220
Conversation
Closes #213 A project takes a deadline exactly as a to-do does, `things projects -j` has reported it since #204, and agents.md advertises `things deadlines` as the way to sweep what is due — but the view pinned t.type = 0, so an agent following the docs missed every project deadline. The view now selects t.type IN (0, 1) through the existing todoOrProject constant, the same rule #205, #209 and #216 applied to the other views. ORDER BY t.deadline ASC is unchanged, so project rows fall in among the to-dos by date rather than forming a block of their own, and --on/--from/ --to filter a project row by its own deadline. Verification here is negative only, and the PR says so. Nothing on this database exercises the change: all seven projects carrying a deadline are already excluded by the status and trashed clause this commit does not touch, four closed and three trashed, so the view returns the same 13 to-do rows before and after. What is verified is that no project is wrongly admitted and none wrongly held back for a new reason. Docs now say every named view except inbox carries projects, and name the bare --project/--area/--tag filter as the other exception: it routes to the internal catch-all view, which is still to-do only.
|
Follow-up: this now has the positive verification the PR body said it lacked. When PR #228 needed a probe to settle #211, the user approved giving that throwaway project a deadline so it could check this view too. A project
So a project deadline created in the app does reach this view, ordered by its date among the to-dos. Before this change the same query returned 13 rows and no project. The probe was deleted through the app afterwards and |
Closes #222 ## What changed The internal catch-all view — the one a bare `--project`/`--area`/`--tag` filter routes to when no view is named — was still pinned to `t.type = 0` while every named view except `inbox` had been widened to `todoOrProject` (#205, #209, #216, #220). It now uses the same set. `--project` is unaffected in practice: a project has no parent project of its own, so `p.uuid` never matches a project row and the filter still returns a project's contents. The visible change is for `--area` and `--tag`. ## Why An agent sweeping an area with `things --area Work -j` got none of that area's projects, which is exactly the miss #222 describes. Parity with what Things.app shows in the matching list is the project's stated goal. ## How verified Measured by uuid against Things.app on 10 Sep 2026. For one area the app reports four projects; the CLI returned zero project rows before this change and returns the same four uuids after. `things --project <uuid> -j` still returns zero project rows. Tests added in `internal/db/tasks_test.go` cover the widened set, the `--area`/`--tag`/`--project` split, and the exclusions that must not widen with it — headings, trashed projects, repeating project templates and the to-dos inside them. Four existing tests asserted the old to-do-only behaviour and now assert the project rows: two area filters, the catch-all grouping order, and the CLI-level default-view test. `make test` and `make lint` are clean. ## Docs The paragraph naming the bare-filter exception was rewritten once, in `internal/skill/SKILL.md`, `docs/content/commands.md`, `docs/content/agents.md` and the README. It now states the `--project` case rather than a whole-view exception.
Closes #213
What changed
deadlinesnow lists projects alongside to-dos. A project takes a deadline exactly as a to-do does,things projects -jhas reported it since #204, and agents.md advertises this view as the way to sweep what is due — so an agent following the docs missed every project deadline. The view was pinned tot.type = 0, so those rows were excluded by construction, not by data.The view now selects
t.type IN (0, 1)through the existingtodoOrProjectconstant, the same rule #205, #209 and #216 applied to the other views. ItsORDER BY t.deadline ASCis unchanged, so project rows fall in among the to-dos by date rather than forming a block of their own.--on,--fromand--toalready filtert.deadlineon this view and now filter project rows by their own deadline.inboxis now the only named view that stays to-do only, which is a property of the Inbox rather than a limitation: an inbox item has not been filed anywhere yet, so it is never a project. A bare-p/-a/-tfilter with no view named is the other exception, and the docs now say so explicitly — it routes to the internal catch-all view, which is still pinned to to-dos.Verification: negative only, and worth being plain about
There is nothing on this database that exercises the change, and I would rather say so than imply a check I did not make.
The app has no Deadlines list to compare against, so the fallback is
things projects -j, which reports no project deadlines at all. Reading the live database withsqlite3 -readonlyshows why. Seven projects carry a deadline, and every one is already excluded by thestatus = 0 AND trashed = 0clause this PR does not touch:So
things deadlinesreturns the same 13 to-do rows before and after this change, and the SQL the new filter generates selects those same 13. What I have verified is that no project is wrongly admitted and none is wrongly held back for a reason this PR introduces. What I have not verified is a project deadline appearing in the app and then in the CLI, because no such project exists here.The tests below cover what the live data cannot.
Tests
Six tests in
internal/db/tasks_test.goover a newseedDeadlineshelper. The fixture interleaves a project between two to-dos by deadline while running"index"against that order, so an ordering that fell back to"index"or grouped by type would fail:model.TypeProject--onmatches a project row by its own deadline--areafinds a project through its own area;--projectcannot match oneviewsIncludingTemplatesrather than the view filterDocs
internal/skill/SKILL.md,docs/content/commands.md,docs/content/agents.mdandREADME.md: the view lists now say every named view exceptinboxcarries projects, and name the bare-filter exception so an agent knows to name a view when project rows matter. The README gains the general rule it never stated, so itsdeadlinestable row no longer reads as though that view is the only one carrying projects.internal/output/output.gohad a comment enumerating the old set of views.