tasks: CalDAV provider (Nextcloud Tasks/iOS), review reports unknown values; bump stops pointing at release (#139)
CI / verify (push) Successful in 1m12s
Release / release (push) Successful in 39s

Files changed:
- CHANGES.md
- INSTALL.md
- VERSION
- instructions/dev/version-parts.md
- instructions/gtd-weekly-review/SKILL.md
- tools/CONTRACT.md
- tools/chemenu/commands/doctor.py
- tools/chemenu/commands/version_cmd.py
- tools/chemenu/review.py
- tools/chemenu/tasks/__init__.py
- tools/chemenu/tasks/caldav.py
- tools/chemenu/tasks/config.py
- tools/chemenu/tests/test_caldav.py
- tools/chemenu/tests/test_doctor.py
- tools/chemenu/tests/test_review.py
- tools/requirements.txt
This commit is contained in:
torben committed 2026-09-25 20:43:53 +02:00
1 parent 4446424e01
commit 6d53c55d0d
16 files changed
+1912 -14

No files matched your search

+31 -2
View File
@@ -35,6 +35,17 @@ CHECK_UNPAGED_PROJECT = "unpaged_project"
CHECK_NO_OPEN_LOOP = "no_open_loop"
CHECK_SOMEDAY_STALE = "someday_stale"
# D3 (Gitea #139): a value a provider could not supply is reported as its own
# finding, under checks 2 and 3 respectively, rather than silently skipped -
# a real state both `superproductivity` (a task with neither `dueWithTime`
# nor `dueDay`) and `caldav` (no server in the account returns
# `DAV:creationdate`, so `created` falls back to the earliest item's own
# `CREATED`, `None` for an empty project) can produce. Not separate entries
# in `ALL_CHECKS`: each fires from within check 2's/check 3's own loop, so
# the five-checks-run count is unaffected.
CHECK_WAITING_NO_FOLLOWUP = "waiting_no_follow_up"
CHECK_PROJECT_AGE_UNKNOWN = "project_age_unknown"
# The checks that need the full tracker project list (#119 D26 checks 1/2/3/4)
# - `projects()` failing skips all four together, since none of them can be
# answered from `someday_items()` alone.
@@ -187,10 +198,19 @@ def run_review(root: Path, *, today: Optional[date] = None) -> ReviewReport:
checks_run.append(CHECK_STALLED)
# Check 2 - waiting-for overdue: any WAITING item whose follow_up_at
# is older than the threshold (#119 D9/D30 - never the due date).
# is older than the threshold (#119 D9/D30 - never the due date). A
# WAITING item with no follow_up_at at all is its own finding (D3),
# not a silent skip - the provider genuinely has nothing to judge
# staleness against.
for _key, (name, items) in open_items_by_key.items():
for item in items.waiting:
if item.follow_up_at is None:
findings.append(Finding(
CHECK_WAITING_NO_FOLLOWUP, name,
f"'{item.title}' is WAITING but has no follow_up_at - cannot judge "
"whether it is overdue.",
item_id=item.id,
))
continue
age_days = (today - item.follow_up_at).days
if age_days > cfg.thresholds.stalled_waiting_days:
@@ -204,9 +224,18 @@ def run_review(root: Path, *, today: Optional[date] = None) -> ReviewReport:
# Check 3 - tracker project with no kb/ page, older than the
# threshold (#119 D26's noise brake: an age threshold, not a marker).
# A project with no determinable creation date is its own finding
# (D3), not a silent skip - check 3 cannot judge its age either way.
for project in tracker_projects:
key = normalize_project_name(project.name)
if key in kb_projects or project.created is None:
if key in kb_projects:
continue
if project.created is None:
findings.append(Finding(
CHECK_PROJECT_AGE_UNKNOWN, project.name,
"No creation date available for this tracker project - cannot judge "
"whether it needs a kb/ page yet.",
))
continue
age_weeks = _weeks_between(project.created, today)
if age_weeks > cfg.thresholds.unpaged_project_weeks: