diff options
| -rw-r--r-- | .ai/scripts/tests/test-todo-cleanup.el | 56 | ||||
| -rw-r--r-- | .ai/scripts/todo-cleanup.el | 38 | ||||
| -rw-r--r-- | claude-templates/.ai/scripts/tests/test-todo-cleanup.el | 56 | ||||
| -rw-r--r-- | claude-templates/.ai/scripts/todo-cleanup.el | 38 |
4 files changed, 160 insertions, 28 deletions
diff --git a/.ai/scripts/tests/test-todo-cleanup.el b/.ai/scripts/tests/test-todo-cleanup.el index 5d43f97..ad9260b 100644 --- a/.ai/scripts/tests/test-todo-cleanup.el +++ b/.ai/scripts/tests/test-todo-cleanup.el @@ -68,6 +68,28 @@ Return a plist: :result final file contents, :archived count from the last run, (tc-test--drop-buffer file) (delete-file file)))) +(defun tc-test--archive-report (content &optional runs check) + "Like `tc-test--archive' but also returns :report — the captured stdout of +`tc--emit-archive-report' from the last run. After the run loop the globals +still hold the last run's `tc-archived'/`tc-issues'/`tc-check-only', so the +captured report is the one that run would have printed." + (let ((file (make-temp-file "tc-test-" nil ".org")) + last-archived last-issues report) + (unwind-protect + (progn + (with-temp-file file (insert content)) + (dotimes (_ (or runs 1)) + (tc-test--reset check) + (tc-process-file file) + (setq last-archived tc-archived last-issues tc-issues) + (tc-test--drop-buffer file)) + (setq report (with-output-to-string (tc--emit-archive-report))) + (list :report report + :archived last-archived + :issues last-issues)) + (tc-test--drop-buffer file) + (delete-file file)))) + (defun tc-test--section (content needle) "Text of the level-1 section in CONTENT whose heading line contains NEEDLE — from the heading line through (not including) the next level-1 heading or EOF." @@ -299,6 +321,40 @@ from the heading line through (not including) the next level-1 heading or EOF." (should (= 3 (plist-get twice :archived))))) ;;; --------------------------------------------------------------------------- +;;; Report suppression: a real-mode no-op stays silent so a double-run wrap +;;; (wrap-it-up then open-tasks.org Phase A) doesn't print an alarming +;;; "0 subtree(s) moved" next to the first run's diff. + +(ert-deftest tc-archive-real-mode-zero-moves-is-silent () + (let ((out (tc-test--archive-report tc-test--nothing))) + (should (= 0 (plist-get out :archived))) + (should (equal "" (plist-get out :report))))) + +(ert-deftest tc-archive-double-run-second-pass-is-silent () + ;; First run archives, second run finds nothing — the second prints nothing. + (let ((out (tc-test--archive-report tc-test--basic 2))) + (should (= 0 (plist-get out :archived))) + (should (equal "" (plist-get out :report))))) + +(ert-deftest tc-archive-check-mode-zero-moves-still-reports () + ;; A preview the caller explicitly asked for still says "0 would move". + (let ((out (tc-test--archive-report tc-test--nothing nil t))) + (should (= 0 (plist-get out :archived))) + (should (tc-test--has (plist-get out :report) "0 subtree(s) would move")))) + +(ert-deftest tc-archive-real-mode-moves-are-reported () + (let ((out (tc-test--archive-report tc-test--basic))) + (should (= 1 (plist-get out :archived))) + (should (tc-test--has (plist-get out :report) "1 subtree(s) moved")))) + +(ert-deftest tc-archive-real-mode-skip-is-reported () + ;; 0 moved but a section is missing — the skip is a real condition and must + ;; not be swallowed by the silence rule. + (let ((out (tc-test--archive-report tc-test--no-resolved))) + (should (= 0 (plist-get out :archived))) + (should (tc-test--has (plist-get out :report) "skipped")))) + +;;; --------------------------------------------------------------------------- ;;; Realistic synthetic sample (committed under fixtures/) (defun tc-test--sample-file () diff --git a/.ai/scripts/todo-cleanup.el b/.ai/scripts/todo-cleanup.el index 569e7c7..6b3081a 100644 --- a/.ai/scripts/todo-cleanup.el +++ b/.ai/scripts/todo-cleanup.el @@ -397,20 +397,30 @@ before their descendants — a [#A] → [#B] → [#D] chain collapses in one pas (save-buffer)))) (defun tc--emit-archive-report () - (princ (format "todo-cleanup --archive-done: %d subtree(s) %s%s\n" - tc-archived - (if tc-check-only "would move" "moved") - (if tc-check-only " — CHECK MODE (no writes)" ""))) - (dolist (i (reverse tc-issues)) - (pcase (plist-get i :kind) - ('archive-skip - (princ (format " skipped %s: %s\n" (plist-get i :file) (plist-get i :detail)))) - ((or 'archive-moved 'archive-would) - (princ (format " %s:%d: %s %s\n" - (plist-get i :file) - (plist-get i :line) - (if tc-check-only "would move" "moved") - (plist-get i :heading))))))) + ;; A real-mode no-op stays silent. When nothing moved and nothing was + ;; skipped, there's nothing to report — and the wrap runs this twice + ;; (wrap-it-up, then open-tasks.org Phase A), so a vocal "0 subtree(s) moved" + ;; on the second pass reads as alarming next to the first pass's diff. Check + ;; mode always reports (a "0 would move" preview is information the caller + ;; asked for), and a skip always reports (a missing section is a real + ;; condition, not a no-op). + (let ((has-skip (cl-some (lambda (i) (eq (plist-get i :kind) 'archive-skip)) + tc-issues))) + (when (or tc-check-only (> tc-archived 0) has-skip) + (princ (format "todo-cleanup --archive-done: %d subtree(s) %s%s\n" + tc-archived + (if tc-check-only "would move" "moved") + (if tc-check-only " — CHECK MODE (no writes)" ""))) + (dolist (i (reverse tc-issues)) + (pcase (plist-get i :kind) + ('archive-skip + (princ (format " skipped %s: %s\n" (plist-get i :file) (plist-get i :detail)))) + ((or 'archive-moved 'archive-would) + (princ (format " %s:%d: %s %s\n" + (plist-get i :file) + (plist-get i :line) + (if tc-check-only "would move" "moved") + (plist-get i :heading))))))))) (defun tc--emit-hygiene-report () (princ (format "todo-cleanup: %d fix(es) applied%s\n" diff --git a/claude-templates/.ai/scripts/tests/test-todo-cleanup.el b/claude-templates/.ai/scripts/tests/test-todo-cleanup.el index 5d43f97..ad9260b 100644 --- a/claude-templates/.ai/scripts/tests/test-todo-cleanup.el +++ b/claude-templates/.ai/scripts/tests/test-todo-cleanup.el @@ -68,6 +68,28 @@ Return a plist: :result final file contents, :archived count from the last run, (tc-test--drop-buffer file) (delete-file file)))) +(defun tc-test--archive-report (content &optional runs check) + "Like `tc-test--archive' but also returns :report — the captured stdout of +`tc--emit-archive-report' from the last run. After the run loop the globals +still hold the last run's `tc-archived'/`tc-issues'/`tc-check-only', so the +captured report is the one that run would have printed." + (let ((file (make-temp-file "tc-test-" nil ".org")) + last-archived last-issues report) + (unwind-protect + (progn + (with-temp-file file (insert content)) + (dotimes (_ (or runs 1)) + (tc-test--reset check) + (tc-process-file file) + (setq last-archived tc-archived last-issues tc-issues) + (tc-test--drop-buffer file)) + (setq report (with-output-to-string (tc--emit-archive-report))) + (list :report report + :archived last-archived + :issues last-issues)) + (tc-test--drop-buffer file) + (delete-file file)))) + (defun tc-test--section (content needle) "Text of the level-1 section in CONTENT whose heading line contains NEEDLE — from the heading line through (not including) the next level-1 heading or EOF." @@ -299,6 +321,40 @@ from the heading line through (not including) the next level-1 heading or EOF." (should (= 3 (plist-get twice :archived))))) ;;; --------------------------------------------------------------------------- +;;; Report suppression: a real-mode no-op stays silent so a double-run wrap +;;; (wrap-it-up then open-tasks.org Phase A) doesn't print an alarming +;;; "0 subtree(s) moved" next to the first run's diff. + +(ert-deftest tc-archive-real-mode-zero-moves-is-silent () + (let ((out (tc-test--archive-report tc-test--nothing))) + (should (= 0 (plist-get out :archived))) + (should (equal "" (plist-get out :report))))) + +(ert-deftest tc-archive-double-run-second-pass-is-silent () + ;; First run archives, second run finds nothing — the second prints nothing. + (let ((out (tc-test--archive-report tc-test--basic 2))) + (should (= 0 (plist-get out :archived))) + (should (equal "" (plist-get out :report))))) + +(ert-deftest tc-archive-check-mode-zero-moves-still-reports () + ;; A preview the caller explicitly asked for still says "0 would move". + (let ((out (tc-test--archive-report tc-test--nothing nil t))) + (should (= 0 (plist-get out :archived))) + (should (tc-test--has (plist-get out :report) "0 subtree(s) would move")))) + +(ert-deftest tc-archive-real-mode-moves-are-reported () + (let ((out (tc-test--archive-report tc-test--basic))) + (should (= 1 (plist-get out :archived))) + (should (tc-test--has (plist-get out :report) "1 subtree(s) moved")))) + +(ert-deftest tc-archive-real-mode-skip-is-reported () + ;; 0 moved but a section is missing — the skip is a real condition and must + ;; not be swallowed by the silence rule. + (let ((out (tc-test--archive-report tc-test--no-resolved))) + (should (= 0 (plist-get out :archived))) + (should (tc-test--has (plist-get out :report) "skipped")))) + +;;; --------------------------------------------------------------------------- ;;; Realistic synthetic sample (committed under fixtures/) (defun tc-test--sample-file () diff --git a/claude-templates/.ai/scripts/todo-cleanup.el b/claude-templates/.ai/scripts/todo-cleanup.el index 569e7c7..6b3081a 100644 --- a/claude-templates/.ai/scripts/todo-cleanup.el +++ b/claude-templates/.ai/scripts/todo-cleanup.el @@ -397,20 +397,30 @@ before their descendants — a [#A] → [#B] → [#D] chain collapses in one pas (save-buffer)))) (defun tc--emit-archive-report () - (princ (format "todo-cleanup --archive-done: %d subtree(s) %s%s\n" - tc-archived - (if tc-check-only "would move" "moved") - (if tc-check-only " — CHECK MODE (no writes)" ""))) - (dolist (i (reverse tc-issues)) - (pcase (plist-get i :kind) - ('archive-skip - (princ (format " skipped %s: %s\n" (plist-get i :file) (plist-get i :detail)))) - ((or 'archive-moved 'archive-would) - (princ (format " %s:%d: %s %s\n" - (plist-get i :file) - (plist-get i :line) - (if tc-check-only "would move" "moved") - (plist-get i :heading))))))) + ;; A real-mode no-op stays silent. When nothing moved and nothing was + ;; skipped, there's nothing to report — and the wrap runs this twice + ;; (wrap-it-up, then open-tasks.org Phase A), so a vocal "0 subtree(s) moved" + ;; on the second pass reads as alarming next to the first pass's diff. Check + ;; mode always reports (a "0 would move" preview is information the caller + ;; asked for), and a skip always reports (a missing section is a real + ;; condition, not a no-op). + (let ((has-skip (cl-some (lambda (i) (eq (plist-get i :kind) 'archive-skip)) + tc-issues))) + (when (or tc-check-only (> tc-archived 0) has-skip) + (princ (format "todo-cleanup --archive-done: %d subtree(s) %s%s\n" + tc-archived + (if tc-check-only "would move" "moved") + (if tc-check-only " — CHECK MODE (no writes)" ""))) + (dolist (i (reverse tc-issues)) + (pcase (plist-get i :kind) + ('archive-skip + (princ (format " skipped %s: %s\n" (plist-get i :file) (plist-get i :detail)))) + ((or 'archive-moved 'archive-would) + (princ (format " %s:%d: %s %s\n" + (plist-get i :file) + (plist-get i :line) + (if tc-check-only "would move" "moved") + (plist-get i :heading))))))))) (defun tc--emit-hygiene-report () (princ (format "todo-cleanup: %d fix(es) applied%s\n" |
