diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-15 16:16:18 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-15 16:16:18 -0500 |
| commit | ee721ee96f984ccd38233309f0dfe6362057e644 (patch) | |
| tree | f84a3b21ae846c82a2677a59f54947ee5b557174 /.ai/scripts/todo-cleanup.el | |
| parent | 421b17a15219c7061ee92c07451993965fad88ea (diff) | |
| download | rulesets-ee721ee96f984ccd38233309f0dfe6362057e644.tar.gz rulesets-ee721ee96f984ccd38233309f0dfe6362057e644.zip | |
chore(ai): sync scripts and workflows from claude-templates
- todo-cleanup.el: :no-sync: tag now inherits down the outline tree
- task-review.org: completion procedure scoped to top-level entries
- cj-scan.py + cj-remove-block.py: helpers for cj-comment block handling
- inbox-send.py: cross-project messaging via inbox directories
Diffstat (limited to '.ai/scripts/todo-cleanup.el')
| -rw-r--r-- | .ai/scripts/todo-cleanup.el | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/.ai/scripts/todo-cleanup.el b/.ai/scripts/todo-cleanup.el index 11851b2..569e7c7 100644 --- a/.ai/scripts/todo-cleanup.el +++ b/.ai/scripts/todo-cleanup.el @@ -41,7 +41,10 @@ ;; match a child. Children with no priority cookie at all are left alone, as ;; are parents with no priority cookie. A child can opt out of being bumped ;; by carrying the `:no-sync:' tag — useful for `Follow-up:'/`Spike:' children -;; that are deliberately deprioritized. Because the walk visits parents +;; that are deliberately deprioritized. The opt-out inherits down the tree: +;; if any ancestor heading carries `:no-sync:', every descendant under it is +;; skipped, so tagging a top-level PROJECT once is enough to keep its whole +;; subtree from cascading. Because the walk visits parents ;; before their descendants in document order, a multi-level chain ;; ([#A] → [#B] → [#D]) collapses to the top priority in a single pass. ;; --check-child-priority is the report-only alias for --sync-child-priority @@ -60,7 +63,9 @@ "Regexp matching an org priority cookie. Match group 1 is the letter.") (defconst tc-no-sync-tag "no-sync" - "Org tag a child heading carries to opt out of `--sync-child-priority'.") + "Org tag that opts a heading and all its descendants out of +`--sync-child-priority'. Inherits down: a tag on an ancestor counts for +every heading below it.") (defvar tc-fixes 0) (defvar tc-archived 0) @@ -271,20 +276,36 @@ the alphabet, since A is highest in org's default priority scheme." (and child parent (> child parent))) (defun tc--heading-has-no-sync-tag-p () - "Non-nil when the heading line at point carries `:no-sync:' as a trailing -tag-style marker. Uses a literal regex match rather than `org-get-tags' -because org's default tag character class (`org-tag-re') excludes hyphens — + "Non-nil when the heading line at point carries the literal substring +`:no-sync:'. Uses a literal regex match rather than `org-get-tags' because +org's default tag character class (`org-tag-re') excludes hyphens — `no-sync' isn't recognized as a real org tag in batch mode unless the user has extended that regex. The literal `:no-sync:' is what wrap-up sessions -actually type, so match it directly: any `:no-sync:' preceded by whitespace -on the heading line counts." +actually type, so match it directly anywhere on the heading line; the +heading line is scoped narrowly enough that a false-positive match in title +text is unlikely, and the cost would only be skipping a bump." (save-excursion (org-back-to-heading t) (let ((line (buffer-substring-no-properties (line-beginning-position) (line-end-position)))) - (string-match-p (format "[ \t]:%s:" (regexp-quote tc-no-sync-tag)) + (string-match-p (format ":%s:" (regexp-quote tc-no-sync-tag)) line)))) +(defun tc--ancestor-or-self-has-no-sync-tag-p () + "Non-nil when the heading at point, or any strict ancestor, carries the +literal `:no-sync:' tag on its own heading line. Walks up the outline +chain via `org-up-heading-safe', which returns nil at the top level +instead of erroring." + (save-excursion + (org-back-to-heading t) + (catch 'found + (when (tc--heading-has-no-sync-tag-p) + (throw 'found t)) + (while (org-up-heading-safe) + (when (tc--heading-has-no-sync-tag-p) + (throw 'found t))) + nil))) + (defun tc--set-heading-priority (letter) "Rewrite the priority cookie on the heading at point to LETTER (a character)." (save-excursion @@ -313,9 +334,10 @@ level deeper than the parent." (defun tc-sync-child-priority-at-heading () "If the heading at point carries a priority cookie, bump any direct child -heading whose own priority is lower, skipping children tagged -`tc-no-sync-tag'. A priority-less parent is a no-op; priority-less children -are left untouched (down-only does not invent priorities)." +heading whose own priority is lower, skipping children whose own heading +or any ancestor carries `tc-no-sync-tag'. A priority-less parent is a +no-op; priority-less children are left untouched (down-only does not +invent priorities)." (let ((parent (tc--heading-priority-letter))) (when parent (let ((parent-heading (org-get-heading t t t t))) @@ -325,7 +347,7 @@ are left untouched (down-only does not invent priorities)." (let ((child (tc--heading-priority-letter))) (when (and child (tc--priority-lower-p child parent) - (not (tc--heading-has-no-sync-tag-p))) + (not (tc--ancestor-or-self-has-no-sync-tag-p))) (let ((child-heading (org-get-heading t t t t)) (child-line (line-number-at-pos))) (cl-incf tc-bumped) |
