Skip to content

fix(transition): advance DEADLINE repeater on terminal transition (v0.6.1) - #18

Open
miles-on-nightshift wants to merge 3 commits into
mainfrom
fix/deadline-repeater
Open

miles-on-nightshift wants to merge 3 commits into
mainfrom
fix/deadline-repeater

Conversation

@miles-on-nightshift

@miles-on-nightshift miles-on-nightshift commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • transition() now checks both SCHEDULED and DEADLINE for a repeater cookie
  • _advance_repeater() parameterised with timestamp_attr to advance the right planning timestamp
  • SCHEDULED checked before DEADLINE (matches Emacs behaviour when both carry a cookie)

Root cause

transition() only tested raw_node.scheduled for a repeater. Tasks with the cookie on DEADLINE transitioned to DONE and terminated rather than recurring.

Reported by @Amperture: nvim-orgmode habit tracker uses DEADLINE as a workaround for missing org-habit support.

Test plan

  • test_transition_recurring_advances_deadline.+1d habit, +1w plain advance, no-repeater terminal all verified
  • Existing test_transition_recurring_advances_scheduled — no regression (284 tests pass)

Version

Bumps to v0.6.1 (v0.6.0 shipped 2026-09-23 before this fix landed).

Closes #17.

🤖 Generated with Claude Code

@miles-on-nightshift miles-on-nightshift left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

CTO pr-review (2026-09-23)

Code review: LGTM. The logic change is correct and minimal — transition() now checks deadline when scheduled has no repeater, and _advance_repeater() correctly parameterises which attribute to advance via timestamp_attr. SCHEDULED-first ordering matches Emacs behaviour. Test coverage is solid: habit (.+1d), plain advance (+1w), and no-repeater terminal all verified; existing SCHEDULED test suite passes without regression (284 tests).

Blocker fixed: All 4 Python-version CI runs failed on ruff I001 — missing blank line between stdlib and third-party imports in the new test (line 296). Fixed and pushed in 643c940. CI should rerun now.

Ready to approve once CI is green.

@miles-on-nightshift

Copy link
Copy Markdown
Collaborator Author

CI green across all 4 Python versions (3.10–3.13). PR is ready for merge by @plur9.

miles-on-nightshift and others added 2 commits September 23, 2026 13:58
SCHEDULED was the only planning timestamp checked for a repeater cookie.
Tasks that carry the repeater on DEADLINE (e.g. nvim-orgmode habit
trackers that use DEADLINE as a workaround for missing org-habit support)
transitioned to DONE and terminated.

`transition()` now checks SCHEDULED first, then DEADLINE. `_advance_repeater()`
accepts a `timestamp_attr` parameter so it reads and writes the right attribute.
When both carry a repeater, SCHEDULED wins (Emacs behaviour).

Closes #17. Bumps to v0.5.5.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@miles-on-nightshift miles-on-nightshift changed the title fix(transition): advance DEADLINE repeater on terminal transition (v0.5.5) fix(transition): advance DEADLINE repeater on terminal transition (v0.6.1) Sep 23, 2026
@miles-on-nightshift

Copy link
Copy Markdown
Collaborator Author

Rebased onto main (v0.6.0 → v0.6.1 version bump). CI re-running. Ready to merge once green — fixes the DEADLINE repeater bug reported by @Amperture.

…-23)

v0.6.0 shipped today; the CHANGELOG was left with (unreleased).
Add the v0.6.1 entry for the DEADLINE-repeater fix (#17) so the PR
description matches the code.
@miles-on-nightshift

Copy link
Copy Markdown
Collaborator Author

CTO pr-review (2026-09-24)

Code is correct. transition() now checks SCHEDULED first, then DEADLINE for a repeater — SCHEDULED-first ordering matches Emacs behaviour. _advance_repeater() parameterised with timestamp_attr (default "scheduled") is the minimal correct change; getattr/setattr usage is clean and backwards-compatible.

Test coverage is solid: habit (.+1d), plain advance (+1w), no-repeater terminal — all 3 paths covered. The .+1d assertion against date.today() is intentional (habit restarts from completion). 284 existing tests pass. Sep 23 ruff I001 blocker was fixed; all 5 CI checks green (Python 3.10–3.13 + Coverage).

The commit headline reads "v0.5.5" but pyproject.toml correctly shows 0.6.0 → 0.6.1 — stale message, not a blocker.

LGTM — ready to merge. @plur9 approve and merge when convenient.

This branch has not been deployed

No deployments
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.

transition() does not advance a repeater on DEADLINE, terminating the task

1 participant