whatnext 2.1__tar.gz → 3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. {whatnext-2.1 → whatnext-3.0}/CHANGELOG.md +23 -0
  2. {whatnext-2.1 → whatnext-3.0}/PKG-INFO +1 -1
  3. {whatnext-2.1 → whatnext-3.0}/docs/deferring.md +6 -2
  4. {whatnext-2.1 → whatnext-3.0}/docs/index.md +2 -2
  5. {whatnext-2.1 → whatnext-3.0}/docs/sequential.md +30 -0
  6. {whatnext-2.1 → whatnext-3.0}/example/projects/curtain.md +1 -1
  7. whatnext-3.0/tasks/deferring.md +24 -0
  8. whatnext-3.0/tests/deferring/needs-absolute.md +1 -0
  9. whatnext-3.0/tests/deferring/needs-subdir.md +1 -0
  10. whatnext-3.0/tests/deferring/phase-misplaced.md +3 -0
  11. whatnext-3.0/tests/deferring/phases-empty.md +10 -0
  12. whatnext-3.0/tests/deferring/phases-partial.md +15 -0
  13. whatnext-3.0/tests/deferring/phases-queue.md +16 -0
  14. whatnext-3.0/tests/deferring/phases.md +15 -0
  15. whatnext-3.0/tests/deferring/root-target.md +1 -0
  16. whatnext-3.0/tests/deferring/samename.md +1 -0
  17. whatnext-3.0/tests/deferring/subdir/needs-parent.md +1 -0
  18. whatnext-3.0/tests/deferring/subdir/needs-sibling.md +1 -0
  19. whatnext-3.0/tests/deferring/subdir/samename.md +1 -0
  20. whatnext-3.0/tests/deferring/subdir/target.md +1 -0
  21. whatnext-3.0/tests/deferring.bats +307 -0
  22. {whatnext-2.1 → whatnext-3.0}/tests/test_defer.py +181 -32
  23. {whatnext-2.1 → whatnext-3.0}/tests/test_file.py +38 -1
  24. {whatnext-2.1 → whatnext-3.0}/tests/test_limit.py +7 -1
  25. {whatnext-2.1 → whatnext-3.0}/whatnext/guide.txt +13 -3
  26. {whatnext-2.1 → whatnext-3.0}/whatnext/models.py +92 -20
  27. {whatnext-2.1 → whatnext-3.0}/whatnext/whatnext.py +74 -22
  28. whatnext-2.1/tasks/deferring.md +0 -4
  29. whatnext-2.1/tests/deferring.bats +0 -108
  30. {whatnext-2.1 → whatnext-3.0}/.flake8 +0 -0
  31. {whatnext-2.1 → whatnext-3.0}/.github/dependabot.yml +0 -0
  32. {whatnext-2.1 → whatnext-3.0}/.github/workflows/publish.yml +0 -0
  33. {whatnext-2.1 → whatnext-3.0}/.github/workflows/tests.yml +0 -0
  34. {whatnext-2.1 → whatnext-3.0}/.gitignore +0 -0
  35. {whatnext-2.1 → whatnext-3.0}/.whatnext +0 -0
  36. {whatnext-2.1 → whatnext-3.0}/LICENCE +0 -0
  37. {whatnext-2.1 → whatnext-3.0}/LICENSE +0 -0
  38. {whatnext-2.1 → whatnext-3.0}/Makefile +0 -0
  39. {whatnext-2.1 → whatnext-3.0}/README.md +0 -0
  40. {whatnext-2.1 → whatnext-3.0}/archive/done/tasks.md +0 -0
  41. {whatnext-2.1 → whatnext-3.0}/docs/annotations.md +0 -0
  42. {whatnext-2.1 → whatnext-3.0}/docs/basics.md +0 -0
  43. {whatnext-2.1 → whatnext-3.0}/docs/deadlines.md +0 -0
  44. {whatnext-2.1 → whatnext-3.0}/docs/exclusions.md +0 -0
  45. {whatnext-2.1 → whatnext-3.0}/docs/installation.md +0 -0
  46. {whatnext-2.1 → whatnext-3.0}/docs/next.md +0 -0
  47. {whatnext-2.1 → whatnext-3.0}/docs/prioritisation.md +0 -0
  48. {whatnext-2.1 → whatnext-3.0}/docs/usage.md +0 -0
  49. {whatnext-2.1 → whatnext-3.0}/example/archived/projects/tangerine.md +0 -0
  50. {whatnext-2.1 → whatnext-3.0}/example/projects/fountain.md +0 -0
  51. {whatnext-2.1 → whatnext-3.0}/example/projects/harvest.md +0 -0
  52. {whatnext-2.1 → whatnext-3.0}/example/projects/obelisk.md +0 -0
  53. {whatnext-2.1 → whatnext-3.0}/example/projects/tinsel.md +0 -0
  54. {whatnext-2.1 → whatnext-3.0}/example/tasks.md +0 -0
  55. {whatnext-2.1 → whatnext-3.0}/example/template.md +0 -0
  56. {whatnext-2.1 → whatnext-3.0}/pyproject.toml +0 -0
  57. {whatnext-2.1 → whatnext-3.0}/scripts/update-usage-examples.py +0 -0
  58. {whatnext-2.1 → whatnext-3.0}/tasks/documentation.md +0 -0
  59. {whatnext-2.1 → whatnext-3.0}/tasks/listing.md +0 -0
  60. {whatnext-2.1 → whatnext-3.0}/tasks/next.md +0 -0
  61. {whatnext-2.1 → whatnext-3.0}/tasks/test_refactor.md +0 -0
  62. {whatnext-2.1 → whatnext-3.0}/tasks/version_0.1.md +0 -0
  63. {whatnext-2.1 → whatnext-3.0}/tasks/version_0.2.md +0 -0
  64. {whatnext-2.1 → whatnext-3.0}/tasks/version_0.3.md +0 -0
  65. {whatnext-2.1 → whatnext-3.0}/tasks/version_0.4.md +0 -0
  66. {whatnext-2.1 → whatnext-3.0}/tasks/version_0.5.md +0 -0
  67. {whatnext-2.1 → whatnext-3.0}/tasks/version_1.0.md +0 -0
  68. {whatnext-2.1 → whatnext-3.0}/tasks/version_1.1.md +0 -0
  69. {whatnext-2.1 → whatnext-3.0}/tasks/version_1.2.md +0 -0
  70. {whatnext-2.1 → whatnext-3.0}/tasks/version_1.3.md +0 -0
  71. {whatnext-2.1 → whatnext-3.0}/tasks.md +0 -0
  72. {whatnext-2.1 → whatnext-3.0}/tests/colour.bats +0 -0
  73. {whatnext-2.1 → whatnext-3.0}/tests/config/.whatnext +0 -0
  74. {whatnext-2.1 → whatnext-3.0}/tests/config/.whatnext.alt +0 -0
  75. {whatnext-2.1 → whatnext-3.0}/tests/config/apples.md +0 -0
  76. {whatnext-2.1 → whatnext-3.0}/tests/config/oranges.md +0 -0
  77. {whatnext-2.1 → whatnext-3.0}/tests/config-external +0 -0
  78. {whatnext-2.1 → whatnext-3.0}/tests/config.bats +0 -0
  79. {whatnext-2.1 → whatnext-3.0}/tests/deadline.bats +0 -0
  80. {whatnext-2.1 → whatnext-3.0}/tests/deferring/bare-after.md +0 -0
  81. {whatnext-2.1 → whatnext-3.0}/tests/deferring/circular-a.md +0 -0
  82. {whatnext-2.1 → whatnext-3.0}/tests/deferring/circular-b.md +0 -0
  83. {whatnext-2.1 → whatnext-3.0}/tests/deferring/deferred.md +0 -0
  84. {whatnext-2.1 → whatnext-3.0}/tests/deferring/duplicate-warnings.md +0 -0
  85. {whatnext-2.1 → whatnext-3.0}/tests/deferring/missing-dep.md +0 -0
  86. {whatnext-2.1 → whatnext-3.0}/tests/deferring/regular.md +0 -0
  87. {whatnext-2.1 → whatnext-3.0}/tests/edit.bats +0 -0
  88. {whatnext-2.1 → whatnext-3.0}/tests/headerless/annotation.md +0 -0
  89. {whatnext-2.1 → whatnext-3.0}/tests/headerless/deadline.md +0 -0
  90. {whatnext-2.1 → whatnext-3.0}/tests/housekeeping.bats +0 -0
  91. {whatnext-2.1 → whatnext-3.0}/tests/invalid.md +0 -0
  92. {whatnext-2.1 → whatnext-3.0}/tests/list.bats +0 -0
  93. {whatnext-2.1 → whatnext-3.0}/tests/matching.bats +0 -0
  94. {whatnext-2.1 → whatnext-3.0}/tests/next/alternate.md +0 -0
  95. {whatnext-2.1 → whatnext-3.0}/tests/next/append-after.md +0 -0
  96. {whatnext-2.1 → whatnext-3.0}/tests/next/append.md +0 -0
  97. {whatnext-2.1 → whatnext-3.0}/tests/next/empty.md +0 -0
  98. {whatnext-2.1 → whatnext-3.0}/tests/next/insert.md +0 -0
  99. {whatnext-2.1 → whatnext-3.0}/tests/next/projects/alpha/tasks/things.md +0 -0
  100. {whatnext-2.1 → whatnext-3.0}/tests/next/projects/alpha/tasks.md +0 -0
  101. {whatnext-2.1 → whatnext-3.0}/tests/next/projects/beta/things.md +0 -0
  102. {whatnext-2.1 → whatnext-3.0}/tests/next/something.txt +0 -0
  103. {whatnext-2.1 → whatnext-3.0}/tests/next/tasks.md +0 -0
  104. {whatnext-2.1 → whatnext-3.0}/tests/next.bats +0 -0
  105. {whatnext-2.1 → whatnext-3.0}/tests/notnext.bats +0 -0
  106. {whatnext-2.1 → whatnext-3.0}/tests/queue/all-complete.md +0 -0
  107. {whatnext-2.1 → whatnext-3.0}/tests/queue/blocked.md +0 -0
  108. {whatnext-2.1 → whatnext-3.0}/tests/queue/in-progress.md +0 -0
  109. {whatnext-2.1 → whatnext-3.0}/tests/queue/normal.md +0 -0
  110. {whatnext-2.1 → whatnext-3.0}/tests/queue/prioritised.md +0 -0
  111. {whatnext-2.1 → whatnext-3.0}/tests/queue.bats +0 -0
  112. {whatnext-2.1 → whatnext-3.0}/tests/summary.bats +0 -0
  113. {whatnext-2.1 → whatnext-3.0}/tests/test_edit.py +0 -0
  114. {whatnext-2.1 → whatnext-3.0}/tests/test_output.py +0 -0
  115. {whatnext-2.1 → whatnext-3.0}/tests/test_summary.py +0 -0
  116. {whatnext-2.1 → whatnext-3.0}/tests/test_task.py +0 -0
  117. {whatnext-2.1 → whatnext-3.0}/tests/usage.bats +0 -0
  118. {whatnext-2.1 → whatnext-3.0}/tests/version.bats +0 -0
  119. {whatnext-2.1 → whatnext-3.0}/whatnext/__init__.py +0 -0
  120. {whatnext-2.1 → whatnext-3.0}/whatnext/next.py +0 -0
  121. {whatnext-2.1 → whatnext-3.0}/whatnext/summary.py +0 -0
@@ -1,6 +1,29 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## [v3.0] - 2026-02-14
5
+
6
+ **Breaking change:** `@after` filenames are now resolved relative to the
7
+ file containing the directive, supporting
8
+
9
+ ```
10
+ @after ../project-b/setup.md
11
+ @after subtask/notes.md
12
+ @after ~/tasks/dependency.md
13
+ ```
14
+
15
+ Previously `whatnext` assumed a flat hierarchy of unique filenames.
16
+
17
+ **Added:**
18
+ - `@phase` directive in section headers creates a dependency chain within
19
+ the file; the first phase is always visible, and subsequent phases
20
+ will only show when all previous phases are complete.
21
+
22
+ **Fixes:**
23
+ - `@after` referencing a file excluded by `--ignore` no longer warns about
24
+ the file not existing, instead treating the dependency as complete.
25
+
26
+
4
27
  ## [v2.0] - 2026-02-09
5
28
 
6
29
  Added `@queue` directive show only one task at a time, for simple sequential
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: whatnext
3
- Version: 2.1
3
+ Version: 3.0
4
4
  Summary: A lister of tasks found in Markdown files
5
5
  Project-URL: Homepage, https://github.com/norm/whatnext
6
6
  Project-URL: Repository, https://github.com/norm/whatnext
@@ -33,8 +33,12 @@ by naming the other task file(s):
33
33
 
34
34
  - [ ] design the booster separation
35
35
 
36
- Filenames are compared against all task files found, without considering
37
- the directory they are in.
36
+ Filenames are resolved relative to the file containing the `@after`
37
+ directive.
38
+
39
+ @after ../project-b/setup.md
40
+ @after subtask/notes.md
41
+ @after ~/tasks/dependency.md
38
42
 
39
43
  Circular dependencies (where A depends on B and B depends on A) will
40
44
  cause an error showing the cycle. Referencing a nonexistent file will
@@ -56,8 +56,8 @@ and sections can have [annotations included](annotations.md).
56
56
  If a task has a dependency on other tasks, such that it cannot be done in any
57
57
  order, you can [defer tasks](deferring.md) until all/some other tasks are complete.
58
58
 
59
- For sequential work where only one task can be done at a time, you can
60
- [limit output](sequential.md) to the next open task in the file.
59
+ For sequential work where only one task or small group of tasks can be done at
60
+ a time, you can [limit output](sequential.md) within the file.
61
61
 
62
62
  If you need to exclude out some Markdown files for any reason, there are
63
63
  [two ways to do that](exclusions.md).
@@ -1,5 +1,10 @@
1
1
  # Sequential tasks
2
2
 
3
+ For ordering tasks within a file, you can use `@queue` and `@phase`.
4
+
5
+
6
+ ## One task at a time
7
+
3
8
  For simpler work that is done sequentially, either because they have to be
4
9
  done one-after-the-other, or because they represent larger blocks that are
5
10
  not broken down into subtasks, add `@queue` to the file:
@@ -24,3 +29,28 @@ auditing.md:
24
29
  ```
25
30
 
26
31
  When querying with `--all` or `--summary` arguments, all tasks are presented.
32
+
33
+
34
+ ## One section at a time
35
+
36
+ For work with multiple tasks with an inherent grouping and you don't want to
37
+ break the work into multiple files, instead break the work into sections and
38
+ include `@phase` in the header:
39
+
40
+ ```markdown
41
+ # Red @phase
42
+ - [ ] add/amend tests to assert desired behaviour
43
+ - [ ] prove new tests fail
44
+
45
+ # Green @phase
46
+ - [ ] update code to implement desired behaviour
47
+ - [ ] prove tests pass
48
+
49
+ # Refactor @phase
50
+ - [ ] simplify and improve new code
51
+ - [ ] prove tests still pass
52
+ ```
53
+
54
+ This creates a dependency chain within the file; the first phase is
55
+ always visible, and subsequent phases will only show when all previous
56
+ phases are complete.
@@ -2,7 +2,7 @@
2
2
 
3
3
  @after
4
4
 
5
- ## Final bow @after tangerine.md
5
+ ## Final bow @after ../archived/projects/tangerine.md
6
6
 
7
7
  - [ ] Take a bow
8
8
 
@@ -0,0 +1,24 @@
1
+ Deferring tasks improvements.
2
+
3
+ - [X] what if an \@after file is queried solo on the command line?
4
+ - [#] \@after with headers from the current file, not just filenames?
5
+ (decided on \@phase, below)
6
+ - [X] \@after combined with --ignore on the command line produces warnings,
7
+ it should check we're not deliberately ignoring
8
+
9
+ Deferring to another file should be relative to the current file, but it
10
+ is not working:
11
+
12
+ ```
13
+ (computer)% whatnext
14
+ WARNING: tasks/notebooks.md: 'wiki/modelling.md' does not exist
15
+ ```
16
+
17
+ - [X] \@after should be relative to the file in question
18
+ - [X] \@after filenames should support `~/...` as a shortcut to `$HOME`
19
+
20
+ `@phase` in a section header creates a dependency chain within the file.
21
+ Later sections also tagged with phase are not shown when earlier phases
22
+ are incomplete. Non-tagged sections are shown as normal.
23
+
24
+ - [X] implement \@phase directive for section-level sequencing
@@ -0,0 +1 @@
1
+ - [ ] depends on absolute path @after /tmp/whatnext-test-prereq.md
@@ -0,0 +1 @@
1
+ - [ ] depends on subdir file @after subdir/target.md
@@ -0,0 +1,3 @@
1
+ @phase
2
+
3
+ - [ ] task with misplaced phase directive
@@ -0,0 +1,10 @@
1
+ # Setup @phase
2
+
3
+ - [X] install dependencies
4
+
5
+ # Configuration @phase
6
+
7
+ # Implementation @phase
8
+
9
+ - [ ] write code
10
+ - [ ] add tests
@@ -0,0 +1,15 @@
1
+ # Bugs
2
+
3
+ - [ ] fix bug
4
+
5
+ # Setup @phase
6
+
7
+ - [X] install dependencies
8
+
9
+ # Implementation @phase
10
+
11
+ - [ ] write code
12
+
13
+ # Testing @phase
14
+
15
+ - [ ] run tests
@@ -0,0 +1,16 @@
1
+ @queue
2
+
3
+ # Setup @phase
4
+
5
+ - [X] first setup task
6
+ - [X] second setup task
7
+
8
+ # Implementation @phase
9
+
10
+ - [ ] first impl task
11
+ - [ ] second impl task
12
+
13
+ # Refactor @phase
14
+
15
+ - [ ] make it easier to read
16
+ - [ ] make it faster
@@ -0,0 +1,15 @@
1
+ # Bugs
2
+
3
+ - [ ] fix bug
4
+
5
+ # New feature @phase
6
+
7
+ - [ ] install dependencies
8
+
9
+ ## Implement @phase
10
+
11
+ - [ ] write code
12
+
13
+ ## Test @phase
14
+
15
+ - [ ] run tests
@@ -0,0 +1 @@
1
+ - [X] complete target at root
@@ -0,0 +1 @@
1
+ - [ ] incomplete task at root
@@ -0,0 +1 @@
1
+ - [ ] depends on parent file @after ../root-target.md
@@ -0,0 +1 @@
1
+ - [ ] depends on sibling @after samename.md
@@ -0,0 +1 @@
1
+ - [X] complete task in subdir
@@ -0,0 +1 @@
1
+ - [X] complete target in subdir
@@ -0,0 +1,307 @@
1
+ bats_require_minimum_version 1.5.0
2
+
3
+ setup_file() {
4
+ echo "- [ ] complete task" > /tmp/whatnext-test-prereq.md
5
+ }
6
+
7
+ teardown_file() {
8
+ rm -f /tmp/whatnext-test-prereq.md
9
+ }
10
+
11
+ @test "circular dependency exits with error" {
12
+ run --separate-stderr \
13
+ whatnext \
14
+ tests/deferring/circular-a.md \
15
+ tests/deferring/circular-b.md
16
+
17
+ expected_stderr=$(sed -e 's/^ //' <<" EOF"
18
+ ERROR: Circular dependency: circular-a.md -> circular-b.md -> circular-a.md
19
+ EOF
20
+ )
21
+ diff -u <(echo "$expected_stderr") <(echo "$stderr")
22
+ [ $status -eq 1 ]
23
+ }
24
+
25
+ @test "warning on nonexistent file dependency" {
26
+ run --separate-stderr \
27
+ whatnext \
28
+ tests/deferring/missing-dep.md
29
+
30
+ expected_stderr=$(sed -e 's/^ //' <<" EOF"
31
+ WARNING: tests/deferring/missing-dep.md: 'nonexistent.md' does not exist
32
+ EOF
33
+ )
34
+ diff -u <(echo "$expected_stderr") <(echo "$stderr")
35
+ [ $status -eq 0 ]
36
+ }
37
+
38
+ @test "all errors and warnings shown" {
39
+ run --separate-stderr \
40
+ whatnext \
41
+ tests/deferring
42
+
43
+ expected_stderr=$(sed -e 's/^ //' <<" EOF"
44
+ WARNING: @phase has no meaning except in a header
45
+ WARNING: duplicate-warnings.md: 'missing-a.md' does not exist
46
+ WARNING: duplicate-warnings.md: 'missing-b.md' does not exist
47
+ WARNING: missing-dep.md: 'nonexistent.md' does not exist
48
+ ERROR: Circular dependency: circular-a.md -> circular-b.md -> circular-a.md
49
+ EOF
50
+ )
51
+ diff -u <(echo "$expected_stderr") <(echo "$stderr")
52
+ [ $status -eq 1 ]
53
+ }
54
+
55
+ @test "warnings are not duplicated" {
56
+ run --separate-stderr \
57
+ whatnext \
58
+ tests/deferring/duplicate-warnings.md
59
+
60
+ expected_stderr=$(sed -e 's/^ //' <<" EOF"
61
+ WARNING: tests/deferring/duplicate-warnings.md: 'missing-a.md' does not exist
62
+ WARNING: tests/deferring/duplicate-warnings.md: 'missing-b.md' does not exist
63
+ EOF
64
+ )
65
+ diff -u <(echo "$expected_stderr") <(echo "$stderr")
66
+ [ $status -eq 0 ]
67
+ }
68
+
69
+ @test "warning suppresseds" {
70
+ run --separate-stderr \
71
+ whatnext \
72
+ --quiet \
73
+ tests/deferring/missing-dep.md
74
+
75
+ diff -u <(echo "") <(echo "$stderr")
76
+ [ $status -eq 0 ]
77
+ }
78
+
79
+ @test "deferred tasks hidden by default" {
80
+ expected_output=$(sed -e 's/^ //' <<" EOF"
81
+ tests/deferring/regular.md:
82
+ - [ ] do the thing
83
+ EOF
84
+ )
85
+
86
+ run whatnext tests/deferring/regular.md tests/deferring/deferred.md
87
+ diff -u <(echo "$expected_output") <(echo "$output")
88
+ [ $status -eq 0 ]
89
+ }
90
+
91
+ @test "tasks shown when file queried directly" {
92
+ expected_output=$(sed -e 's/^ //' <<" EOF"
93
+ tests/deferring/bare-after.md:
94
+ - [ ] do this last
95
+ EOF
96
+ )
97
+
98
+ # nothing else is outstanding (as nothing else was loaded),
99
+ # so the contents should be shown
100
+ run whatnext tests/deferring/bare-after.md
101
+ diff -u <(echo "$expected_output") <(echo "$output")
102
+ [ $status -eq 0 ]
103
+ }
104
+
105
+ @test "after can be ignored" {
106
+ expected_output=$(sed -e 's/^ //' <<" EOF"
107
+ tests/deferring/deferred.md:
108
+ - [ ] wait for regular
109
+ tests/deferring/regular.md:
110
+ - [ ] do the thing
111
+ EOF
112
+ )
113
+
114
+ run whatnext --ignore-after tests/deferring/regular.md tests/deferring/deferred.md
115
+ diff -u <(echo "$expected_output") <(echo "$output")
116
+ [ $status -eq 0 ]
117
+ }
118
+
119
+ @test "dependency treated as satisfied when file is deliberately ignored" {
120
+ expected_output=$(sed -e 's/^ //' <<" EOF"
121
+ tests/deferring/deferred.md:
122
+ - [ ] wait for regular
123
+ EOF
124
+ )
125
+
126
+ run --separate-stderr \
127
+ whatnext \
128
+ --ignore regular.md \
129
+ tests/deferring/deferred.md
130
+
131
+ diff -u <(echo "$expected_output") <(echo "$output")
132
+ diff -u <(echo "") <(echo "$stderr")
133
+ [ $status -eq 0 ]
134
+ }
135
+
136
+ @test "after resolves bare filename relative to file" {
137
+ expected_output=$(sed -e 's/^ //' <<" EOF"
138
+ tests/deferring/samename.md:
139
+ - [ ] incomplete task at root
140
+ tests/deferring/subdir/needs-sibling.md:
141
+ - [ ] depends on sibling
142
+ EOF
143
+ )
144
+
145
+ run --separate-stderr \
146
+ whatnext \
147
+ tests/deferring/subdir/needs-sibling.md \
148
+ tests/deferring/subdir/samename.md \
149
+ tests/deferring/samename.md
150
+
151
+ diff -u <(echo "$expected_output") <(echo "$output")
152
+ [ $status -eq 0 ]
153
+ }
154
+
155
+ @test "after resolves path descending into subdirectory" {
156
+ expected_output=$(sed -e 's/^ //' <<" EOF"
157
+ tests/deferring/needs-subdir.md:
158
+ - [ ] depends on subdir file
159
+ EOF
160
+ )
161
+
162
+ run --separate-stderr \
163
+ whatnext \
164
+ tests/deferring/needs-subdir.md \
165
+ tests/deferring/subdir/target.md
166
+
167
+ diff -u <(echo "$expected_output") <(echo "$output")
168
+ [ $status -eq 0 ]
169
+ }
170
+
171
+ @test "after resolves path ascending to parent directory" {
172
+ expected_output=$(sed -e 's/^ //' <<" EOF"
173
+ tests/deferring/subdir/needs-parent.md:
174
+ - [ ] depends on parent file
175
+ EOF
176
+ )
177
+
178
+ run --separate-stderr \
179
+ whatnext \
180
+ tests/deferring/subdir/needs-parent.md \
181
+ tests/deferring/root-target.md
182
+
183
+ diff -u <(echo "$expected_output") <(echo "$output")
184
+ [ $status -eq 0 ]
185
+ }
186
+
187
+ @test "after resolves absolute path" {
188
+ expected_output=$(sed -e 's/^ //' <<" EOF"
189
+ /tmp/whatnext-test-prereq.md:
190
+ - [ ] complete task
191
+ EOF
192
+ )
193
+
194
+ run --separate-stderr \
195
+ whatnext \
196
+ tests/deferring/needs-absolute.md \
197
+ /tmp/whatnext-test-prereq.md
198
+
199
+ diff -u <(echo "$expected_output") <(echo "$output")
200
+ [ $status -eq 0 ]
201
+ }
202
+
203
+ @test "phase sections filter later phases" {
204
+ expected_output=$(sed -e 's/^ //' <<" EOF"
205
+ tests/deferring/phases.md:
206
+ # Bugs
207
+ - [ ] fix bug
208
+ # New feature [phase 1/3]
209
+ - [ ] install dependencies
210
+ EOF
211
+ )
212
+
213
+ run --separate-stderr \
214
+ whatnext \
215
+ tests/deferring/phases.md
216
+
217
+ diff -u <(echo "$expected_output") <(echo "$output")
218
+ [ $status -eq 0 ]
219
+ }
220
+
221
+ @test "phase shows next when previous complete" {
222
+ expected_output=$(sed -e 's/^ //' <<" EOF"
223
+ tests/deferring/phases-partial.md:
224
+ # Bugs
225
+ - [ ] fix bug
226
+ # Implementation [phase 2/3]
227
+ - [ ] write code
228
+ EOF
229
+ )
230
+
231
+ run --separate-stderr \
232
+ whatnext \
233
+ tests/deferring/phases-partial.md
234
+
235
+ diff -u <(echo "$expected_output") <(echo "$output")
236
+ [ $status -eq 0 ]
237
+ }
238
+
239
+ @test "all phases shown with --all" {
240
+ expected_output=$(sed -e 's/^ //' <<" EOF"
241
+ tests/deferring/phases.md:
242
+ # Bugs
243
+ - [ ] fix bug
244
+ # New feature [phase 1/3]
245
+ - [ ] install dependencies
246
+ # New feature / Implement [phase 2/3]
247
+ - [ ] write code
248
+ # New feature / Test [phase 3/3]
249
+ - [ ] run tests
250
+ EOF
251
+ )
252
+
253
+ run --separate-stderr \
254
+ whatnext \
255
+ --all \
256
+ tests/deferring/phases.md
257
+
258
+ diff -u <(echo "$expected_output") <(echo "$output")
259
+ [ $status -eq 0 ]
260
+ }
261
+
262
+ @test "queue limits tasks within phase" {
263
+ expected_output=$(sed -e 's/^ //' <<" EOF"
264
+ tests/deferring/phases-queue.md:
265
+ # Implementation [phase 2/3]
266
+ - [ ] first impl task
267
+ EOF
268
+ )
269
+
270
+ run --separate-stderr \
271
+ whatnext \
272
+ tests/deferring/phases-queue.md
273
+
274
+ diff -u <(echo "$expected_output") <(echo "$output")
275
+ [ $status -eq 0 ]
276
+ }
277
+
278
+ @test "empty phase skips to next" {
279
+ expected_output=$(sed -e 's/^ //' <<" EOF"
280
+ tests/deferring/phases-empty.md:
281
+ # Implementation [phase 3/3]
282
+ - [ ] write code
283
+ - [ ] add tests
284
+ EOF
285
+ )
286
+
287
+ run --separate-stderr \
288
+ whatnext \
289
+ tests/deferring/phases-empty.md
290
+
291
+ diff -u <(echo "$expected_output") <(echo "$output")
292
+ [ $status -eq 0 ]
293
+ }
294
+
295
+ @test "warning when @phase outside header" {
296
+ expected_stderr=$(sed -e 's/^ //' <<" EOF"
297
+ WARNING: @phase has no meaning except in a header
298
+ EOF
299
+ )
300
+
301
+ run --separate-stderr \
302
+ whatnext \
303
+ tests/deferring/phase-misplaced.md
304
+
305
+ diff -u <(echo "$expected_stderr") <(echo "$stderr")
306
+ [ $status -eq 0 ]
307
+ }