aboutsummaryrefslogtreecommitdiff
path: root/.ai/scripts/tests
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-05-20 15:06:17 -0400
committerCraig Jennings <c@cjennings.net>2026-05-20 15:06:17 -0400
commite9bd073b8133c50a2df425196e32fdf3f5c4c2bd (patch)
treeace469011d84044a78f93a2e6883de673b9a198d /.ai/scripts/tests
parent49898a8c364430abf792567d2a51ac09db97a94f (diff)
downloadrulesets-e9bd073b8133c50a2df425196e32fdf3f5c4c2bd.tar.gz
rulesets-e9bd073b8133c50a2df425196e32fdf3f5c4c2bd.zip
feat(workflows): add task-review list-hygiene habit
The new task-review.org workflow is the daily habit that retires the old date-coverage scan. It surfaces the oldest-unreviewed top-level tasks, walks them one at a time, and records each outcome — keep, re-grade, kill, mark DOING, or edit — stamping :LAST_REVIEWED: as it goes. It's a pure Claude workflow, no elisp. open-tasks.org displays the list; this one changes it. task-review-staleness.sh gains a --list mode that emits the N oldest-unreviewed tasks (line, review date, heading), oldest first, so the workflow walks a deterministic batch instead of eyeballing todo.org. Never-reviewed and unparseable-date tasks sort oldest. Seven new bats cases cover ordering, the count limit, exclusions, and output format; count mode is unchanged. startup.org gains the matching nudge. Phase A counts tasks unreviewed for >7 days and Phase C surfaces one line when that count is non-zero, pointing at the workflow. It lives in the template startup.org rather than the project-only startup-extras layer, so every project picks it up the same way it picks up the wrap-up health check. The INDEX entry is added with the "task review" triggers the rename freed up.
Diffstat (limited to '.ai/scripts/tests')
-rw-r--r--.ai/scripts/tests/task-review-staleness.bats64
1 files changed, 64 insertions, 0 deletions
diff --git a/.ai/scripts/tests/task-review-staleness.bats b/.ai/scripts/tests/task-review-staleness.bats
index abb7585..488b023 100644
--- a/.ai/scripts/tests/task-review-staleness.bats
+++ b/.ai/scripts/tests/task-review-staleness.bats
@@ -147,3 +147,67 @@ task_unreviewed() {
run bash "$SCRIPT" "$TEST_DIR/does-not-exist.org" 30
[ "$status" -ne 0 ]
}
+
+# ---- --list mode -----------------------------------------------------
+
+@test "staleness --list: orders oldest-reviewed first, unreviewed before dated" {
+ task_reviewed TODO A "Reviewed recently" "$D5"
+ task_reviewed TODO B "Reviewed long ago" "$D40"
+ task_unreviewed DOING A "Never reviewed"
+ run bash "$SCRIPT" --list "$TODO" 10
+ [ "$status" -eq 0 ]
+ [[ "${lines[0]}" == *"Never reviewed"* ]]
+ [[ "${lines[1]}" == *"Reviewed long ago"* ]]
+ [[ "${lines[2]}" == *"Reviewed recently"* ]]
+}
+
+@test "staleness --list: takes only the requested count" {
+ task_unreviewed TODO A "First"
+ task_reviewed TODO B "Second" "$D40"
+ task_reviewed TODO C "Third" "$D30"
+ run bash "$SCRIPT" --list "$TODO" 2
+ [ "$status" -eq 0 ]
+ [ "${#lines[@]}" -eq 2 ]
+}
+
+@test "staleness --list: count larger than available returns all candidates" {
+ task_unreviewed TODO A "Only one"
+ run bash "$SCRIPT" --list "$TODO" 10
+ [ "$status" -eq 0 ]
+ [ "${#lines[@]}" -eq 1 ]
+}
+
+@test "staleness --list: excludes DONE, deeper headings, and cookie-less headings" {
+ task_reviewed DONE A "Shipped" "$D40"
+ printf '*** TODO [#A] Child task\n\n' >> "$TODO"
+ printf '** TODO Cookie-less\n\n' >> "$TODO"
+ task_unreviewed TODO B "Real one"
+ run bash "$SCRIPT" --list "$TODO" 10
+ [ "$status" -eq 0 ]
+ [ "${#lines[@]}" -eq 1 ]
+ [[ "${lines[0]}" == *"Real one"* ]]
+}
+
+@test "staleness --list: emits line, review value, and heading tab-separated" {
+ task_unreviewed TODO A "Never reviewed"
+ run bash "$SCRIPT" --list "$TODO" 10
+ [ "$status" -eq 0 ]
+ line_no=$(printf '%s' "${lines[0]}" | cut -f1)
+ value=$(printf '%s' "${lines[0]}" | cut -f2)
+ heading=$(printf '%s' "${lines[0]}" | cut -f3)
+ [ "$line_no" = "1" ]
+ [ "$value" = "NONE" ]
+ [ "$heading" = "** TODO [#A] Never reviewed" ]
+}
+
+@test "staleness --list: empty file produces no output" {
+ : > "$TODO"
+ run bash "$SCRIPT" --list "$TODO" 10
+ [ "$status" -eq 0 ]
+ [ -z "$output" ]
+}
+
+@test "staleness --list: missing file exits non-zero" {
+ run bash "$SCRIPT" --list "$TEST_DIR/nope.org" 10
+ [ "$status" -ne 0 ]
+}