aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/design/2026-06-29-todo-cleanup-aging-proposal.org64
1 files changed, 64 insertions, 0 deletions
diff --git a/docs/design/2026-06-29-todo-cleanup-aging-proposal.org b/docs/design/2026-06-29-todo-cleanup-aging-proposal.org
new file mode 100644
index 0000000..5a18990
--- /dev/null
+++ b/docs/design/2026-06-29-todo-cleanup-aging-proposal.org
@@ -0,0 +1,64 @@
+#+TITLE: todo-cleanup.el — add Resolved-section file-aging to --archive-done
+
+* What changed (from .emacs.d, 2026-06-29)
+
+Extended =todo-cleanup.el='s =--archive-done= mode (the =make task-sorted=
+target) with a SECOND step, run after the existing Open Work -> Resolved move:
+
+- *Age the Resolved section.* Level-2 DONE/CANCELLED subtrees whose CLOSED date
+ is older than =tc-archive-retain-days= (default 7) — AND any with no parseable
+ CLOSED date — move out of the in-file Resolved section to =tc-archive-file=
+ (default =archive/task-archive.org= beside the todo file). Only tasks closed
+ within the last week stay in todo.org itself.
+
+Two files are attached (the edited canonical candidates):
+- =todo-cleanup.el=
+- =tests/test-todo-cleanup.el=
+
+* Why
+
+Craig's .emacs.d todo.org had grown to 768KB / 9616 lines, ~44% of it a
+243-task in-file "Resolved" section. The existing =--archive-done= only moved
+closures Open Work -> Resolved (same file), so the file grew without bound. The
+new step keeps only the last week of closed tasks in the file and sheds the rest
+to a git-tracked archive sibling. After this run: 207 aged out, todo.org
+9616 -> 5625 lines.
+
+* Design notes for the canonical
+
+- New defvars: =tc-archive-retain-days= (7; nil disables the step, preserving
+ legacy in-file-only behavior), =tc-archive-reference-date= ((YEAR MONTH DAY),
+ nil=real today — mockable for deterministic tests), =tc-archive-file= (nil =>
+ =archive/task-archive.org= beside the todo file).
+- Policy: KEEP iff CLOSED date present AND within the window (cutoff inclusive).
+ Older OR undated => archive. The undated->archive call is deliberate ("keep
+ the last week and that's it"); an earlier undated->keep version left 14 legacy
+ undated tasks behind and read as two weeks.
+- The aging step honors =--check= (previews + reports, writes nothing).
+- Report: an additive "N aged subtree(s) moved to task-archive.org" line, only
+ when N>0, so the existing real-mode-no-op silence tests are unaffected.
+- Archive file scaffold: =#+TITLE: Task Archive= / =#+FILETAGS: :archive:= /
+ =* Resolved (archived)=; aged subtrees append as level-2 children; created on
+ first use, appended to thereafter (one scaffold, never duplicated).
+- Tests: =tc-test--reset= now sets the aging knobs OFF (retain nil) so the
+ existing in-file-move + sync tests are untouched by the wall clock; a new
+ =tc-test--age= harness re-enables them with a fixed reference date and a temp
+ archive file. 6 new tests (old+undated move, cutoff-inclusive stay, disabled,
+ idempotent, check-no-write, straggler pipeline, append-preserves). 34/34 green.
+
+* Cross-project consideration for your value gate
+
+Default is ON (retain 7) for ALL consuming projects once this syncs. A project's
+first =task-sorted= after the sync will shed everything in its Resolved section
+older than a week to a new =archive/task-archive.org=. That's the intended
+feature, but flag it — projects with a large historical Resolved section will see
+a big first-run move (git-tracked, recoverable). Adjust the default or gate it if
+you'd rather it be opt-in per project.
+
+* Companion (project-local, NOT synced)
+
+.emacs.d's Makefile =task-sorted= target now also runs =lint-org.el todo.org=
+after the archive, as a structural-safety pass (org-lint catches links/drawers/
+blocks; we separately verified heading-level structure by hand). Makefiles aren't
+template-synced, so this is per-project — noting it in case the pattern is worth
+documenting alongside the tool.