taskcheck 1.2.0__tar.gz → 1.3.1__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 (28) hide show
  1. taskcheck-1.3.1/PKG-INFO +114 -0
  2. taskcheck-1.3.1/README.md +99 -0
  3. {taskcheck-1.2.0 → taskcheck-1.3.1}/pyproject.toml +1 -1
  4. {taskcheck-1.2.0 → taskcheck-1.3.1}/taskcheck/__main__.py +3 -1
  5. {taskcheck-1.2.0 → taskcheck-1.3.1}/taskcheck/parallel.py +22 -7
  6. taskcheck-1.3.1/taskcheck.egg-info/PKG-INFO +114 -0
  7. {taskcheck-1.2.0 → taskcheck-1.3.1}/tests/test_main.py +9 -1
  8. {taskcheck-1.2.0 → taskcheck-1.3.1}/tests/test_parallel.py +27 -1
  9. taskcheck-1.2.0/PKG-INFO +0 -232
  10. taskcheck-1.2.0/README.md +0 -217
  11. taskcheck-1.2.0/taskcheck.egg-info/PKG-INFO +0 -232
  12. {taskcheck-1.2.0 → taskcheck-1.3.1}/LICENSE +0 -0
  13. {taskcheck-1.2.0 → taskcheck-1.3.1}/setup.cfg +0 -0
  14. {taskcheck-1.2.0 → taskcheck-1.3.1}/taskcheck/common.py +0 -0
  15. {taskcheck-1.2.0 → taskcheck-1.3.1}/taskcheck/google_calendar.py +0 -0
  16. {taskcheck-1.2.0 → taskcheck-1.3.1}/taskcheck/ical.py +0 -0
  17. {taskcheck-1.2.0 → taskcheck-1.3.1}/taskcheck/install.py +0 -0
  18. {taskcheck-1.2.0 → taskcheck-1.3.1}/taskcheck/report.py +0 -0
  19. {taskcheck-1.2.0 → taskcheck-1.3.1}/taskcheck.egg-info/SOURCES.txt +0 -0
  20. {taskcheck-1.2.0 → taskcheck-1.3.1}/taskcheck.egg-info/dependency_links.txt +0 -0
  21. {taskcheck-1.2.0 → taskcheck-1.3.1}/taskcheck.egg-info/entry_points.txt +0 -0
  22. {taskcheck-1.2.0 → taskcheck-1.3.1}/taskcheck.egg-info/requires.txt +0 -0
  23. {taskcheck-1.2.0 → taskcheck-1.3.1}/taskcheck.egg-info/top_level.txt +0 -0
  24. {taskcheck-1.2.0 → taskcheck-1.3.1}/tests/test_common.py +0 -0
  25. {taskcheck-1.2.0 → taskcheck-1.3.1}/tests/test_google_calendar.py +0 -0
  26. {taskcheck-1.2.0 → taskcheck-1.3.1}/tests/test_ical.py +0 -0
  27. {taskcheck-1.2.0 → taskcheck-1.3.1}/tests/test_install.py +0 -0
  28. {taskcheck-1.2.0 → taskcheck-1.3.1}/tests/test_report.py +0 -0
@@ -0,0 +1,114 @@
1
+ Metadata-Version: 2.4
2
+ Name: taskcheck
3
+ Version: 1.3.1
4
+ Summary: Automatic scheduler for taskwarrior
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: appdirs>=1.4.4
8
+ Requires-Dist: google-api-python-client>=2.198.0
9
+ Requires-Dist: google-auth>=2.56.2
10
+ Requires-Dist: google-auth-oauthlib>=1.2.2
11
+ Requires-Dist: icalendar>=6.0.1
12
+ Requires-Dist: random-unicode-emoji>=2.8
13
+ Requires-Dist: requests>=2.32.3
14
+ Requires-Dist: rich>=13.9.4
15
+
16
+ ![immagine](https://github.com/user-attachments/assets/27b83bb1-7a50-4923-a453-0a958fbe11ed)
17
+
18
+ A Taskwarrior scheduler for people who want a realistic plan, not a manual to-do list.
19
+ It turns tasks, working hours, and calendar blocks into an actionable schedule — then keeps due dates visible.
20
+
21
+ Use it if you want to:
22
+ - stop guessing what to do next
23
+ - fit tasks into real availability
24
+ - be sure your long-time plan won't go overdue
25
+ - keep Taskwarrior as the source of truth
26
+
27
+ > [!IMPORTANT]
28
+ > This repo is actively maintained again
29
+
30
+ ## Features
31
+
32
+ - ✨ Auto-schedule tasks from working hours + calendar blocks
33
+ - 🧭 Support complex working-hour maps
34
+ - ⏱️ Consider urgency, due dates, and dependencies
35
+ - 🧪 Dry-run mode to preview changes
36
+ - 🧠 Auto-adjust urgency when deadlines cannot be met
37
+ - 🔄 Force-refresh iCal calendars
38
+ - 📊 Custom reports for planned and unplanned tasks
39
+ - 🎨 Report styling with emoji and extra attributes
40
+ - 🗓️ Block time with iCal or Google Calendar, including all-day events
41
+
42
+ ## Quick start
43
+
44
+ 1. `pipx install taskcheck`
45
+ 2. `taskcheck --install` ← setup only
46
+ 3. add `estimated` + `time_map` UDAs
47
+ 4. edit `~/.config/task/taskcheck.toml` (see [Reference](#Reference))
48
+ 5. `taskcheck --schedule`
49
+
50
+ ## How it works
51
+
52
+ Taskcheck reads your pending and waiting tasks, estimates when each one can be worked on, and writes back a schedule.
53
+ It respects:
54
+ - your working hours
55
+ - task duration estimates
56
+ - calendar events and vacations from iCal / Google Calendar
57
+ - task urgency and due dates
58
+
59
+ It updates Taskwarrior with:
60
+ - `scheduled` → when work should start
61
+ - `completion_date` → when work is expected to finish
62
+ - a warning when a task will miss its due date
63
+
64
+ ### Required UDAs
65
+
66
+ - `estimated`: expected duration in hours
67
+ - `time_map`: which working-hour profile applies to the task, for example `work` or `weekend`
68
+
69
+ Example:
70
+
71
+ ```toml
72
+ [time_maps.work]
73
+ monday = [[9, 12.30], [14, 17]]
74
+ tuesday = [[9, 12.30], [14, 17]]
75
+ ```
76
+
77
+ ### Reports
78
+
79
+ - `taskcheck -r today` → tasks planned for today
80
+ - `taskcheck -r 1w` → tasks planned for the next week
81
+
82
+ ## Reference
83
+
84
+ 📚 Full reference: [REFERENCE.md](REFERENCE.md)
85
+
86
+ In short:
87
+ - `taskcheck --install` is interactive
88
+ - it installs required Taskwarrior settings if you confirm the first prompt
89
+ - it installs optional urgency/report tuning if you confirm the second prompt
90
+ - it can also create the default config file if you confirm the third prompt
91
+ - it does **not** schedule tasks or fetch calendars
92
+ - scheduling happens with `taskcheck --schedule`
93
+ - all flags/config keys/settings are documented in `REFERENCE.md`
94
+
95
+ ## Algorithm
96
+
97
+ The algorithm simulates a workday one chunk at a time.
98
+
99
+ For each day starting from today, it sorts tasks by urgency and picks the most urgent task that fits the available time.
100
+ It assigns a small block of work, then recomputes urgency exactly as Taskwarrior would on that day.
101
+ If urgency changes, the next task choice can change too.
102
+
103
+ For `today`, taskcheck skips past hours.
104
+
105
+ The default work chunk is 2 hours (or less if the task is shorter); you can tune it with the Taskwarrior UDA `min_block`.
106
+
107
+ If a task would finish after its `due_date`, taskcheck retries. It keeps that task's current non-due urgency weight, then lowers the weight by 0.1 only for tasks that have not missed a deadline. Due urgency is never reduced. Retries stop when deadlines are respected or unflagged tasks reach a weight of 0.
108
+
109
+ ## Tips and Tricks
110
+
111
+ - You can exclude a task from being scheduled by removing the `time_map` or `estimated` attributes.
112
+ - You can see tasks that you can execute now with the `task ready` report.
113
+
114
+ See the reference section above for flags, config keys, and installed Taskwarrior settings.
@@ -0,0 +1,99 @@
1
+ ![immagine](https://github.com/user-attachments/assets/27b83bb1-7a50-4923-a453-0a958fbe11ed)
2
+
3
+ A Taskwarrior scheduler for people who want a realistic plan, not a manual to-do list.
4
+ It turns tasks, working hours, and calendar blocks into an actionable schedule — then keeps due dates visible.
5
+
6
+ Use it if you want to:
7
+ - stop guessing what to do next
8
+ - fit tasks into real availability
9
+ - be sure your long-time plan won't go overdue
10
+ - keep Taskwarrior as the source of truth
11
+
12
+ > [!IMPORTANT]
13
+ > This repo is actively maintained again
14
+
15
+ ## Features
16
+
17
+ - ✨ Auto-schedule tasks from working hours + calendar blocks
18
+ - 🧭 Support complex working-hour maps
19
+ - ⏱️ Consider urgency, due dates, and dependencies
20
+ - 🧪 Dry-run mode to preview changes
21
+ - 🧠 Auto-adjust urgency when deadlines cannot be met
22
+ - 🔄 Force-refresh iCal calendars
23
+ - 📊 Custom reports for planned and unplanned tasks
24
+ - 🎨 Report styling with emoji and extra attributes
25
+ - 🗓️ Block time with iCal or Google Calendar, including all-day events
26
+
27
+ ## Quick start
28
+
29
+ 1. `pipx install taskcheck`
30
+ 2. `taskcheck --install` ← setup only
31
+ 3. add `estimated` + `time_map` UDAs
32
+ 4. edit `~/.config/task/taskcheck.toml` (see [Reference](#Reference))
33
+ 5. `taskcheck --schedule`
34
+
35
+ ## How it works
36
+
37
+ Taskcheck reads your pending and waiting tasks, estimates when each one can be worked on, and writes back a schedule.
38
+ It respects:
39
+ - your working hours
40
+ - task duration estimates
41
+ - calendar events and vacations from iCal / Google Calendar
42
+ - task urgency and due dates
43
+
44
+ It updates Taskwarrior with:
45
+ - `scheduled` → when work should start
46
+ - `completion_date` → when work is expected to finish
47
+ - a warning when a task will miss its due date
48
+
49
+ ### Required UDAs
50
+
51
+ - `estimated`: expected duration in hours
52
+ - `time_map`: which working-hour profile applies to the task, for example `work` or `weekend`
53
+
54
+ Example:
55
+
56
+ ```toml
57
+ [time_maps.work]
58
+ monday = [[9, 12.30], [14, 17]]
59
+ tuesday = [[9, 12.30], [14, 17]]
60
+ ```
61
+
62
+ ### Reports
63
+
64
+ - `taskcheck -r today` → tasks planned for today
65
+ - `taskcheck -r 1w` → tasks planned for the next week
66
+
67
+ ## Reference
68
+
69
+ 📚 Full reference: [REFERENCE.md](REFERENCE.md)
70
+
71
+ In short:
72
+ - `taskcheck --install` is interactive
73
+ - it installs required Taskwarrior settings if you confirm the first prompt
74
+ - it installs optional urgency/report tuning if you confirm the second prompt
75
+ - it can also create the default config file if you confirm the third prompt
76
+ - it does **not** schedule tasks or fetch calendars
77
+ - scheduling happens with `taskcheck --schedule`
78
+ - all flags/config keys/settings are documented in `REFERENCE.md`
79
+
80
+ ## Algorithm
81
+
82
+ The algorithm simulates a workday one chunk at a time.
83
+
84
+ For each day starting from today, it sorts tasks by urgency and picks the most urgent task that fits the available time.
85
+ It assigns a small block of work, then recomputes urgency exactly as Taskwarrior would on that day.
86
+ If urgency changes, the next task choice can change too.
87
+
88
+ For `today`, taskcheck skips past hours.
89
+
90
+ The default work chunk is 2 hours (or less if the task is shorter); you can tune it with the Taskwarrior UDA `min_block`.
91
+
92
+ If a task would finish after its `due_date`, taskcheck retries. It keeps that task's current non-due urgency weight, then lowers the weight by 0.1 only for tasks that have not missed a deadline. Due urgency is never reduced. Retries stop when deadlines are respected or unflagged tasks reach a weight of 0.
93
+
94
+ ## Tips and Tricks
95
+
96
+ - You can exclude a task from being scheduled by removing the `time_map` or `estimated` attributes.
97
+ - You can see tasks that you can execute now with the `task ready` report.
98
+
99
+ See the reference section above for flags, config keys, and installed Taskwarrior settings.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "taskcheck"
3
- version = "1.2.0"
3
+ version = "1.3.1"
4
4
  description = "Automatic scheduler for taskwarrior"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1,10 +1,12 @@
1
1
  import tomllib
2
2
  import argparse
3
+ from importlib.metadata import version
3
4
 
4
5
  from taskcheck.parallel import check_tasks_parallel
5
6
  from taskcheck.common import config_dir
6
7
 
7
8
  arg_parser = argparse.ArgumentParser()
9
+ arg_parser.add_argument("--version", action="version", version=f"taskcheck {version('taskcheck')}")
8
10
  arg_parser.add_argument(
9
11
  "-v", "--verbose", action="store_true", help="Increase output verbosity."
10
12
  )
@@ -52,7 +54,7 @@ arg_parser.add_argument(
52
54
  dest="auto_adjust_urgency",
53
55
  action="store_false",
54
56
  default=True,
55
- help="Disable automatic reduction of urgency weight when tasks cannot be completed on time. (Enabled by default, meaning automatic reduction will occur.)",
57
+ help="Disable automatic per-task urgency adjustment when tasks cannot be completed on time.",
56
58
  )
57
59
  arg_parser.add_argument(
58
60
  "--add-google-calendar",
@@ -111,6 +111,7 @@ def check_tasks_parallel(
111
111
  urgency_coefficients = get_urgency_coefficients(taskrc=taskrc)
112
112
 
113
113
  current_weight = initial_weight_urgency
114
+ frozen_weights = {}
114
115
 
115
116
  # Always re-initialize task_info inside the loop to avoid mutated state
116
117
  task_info_original = initialize_task_info(
@@ -132,6 +133,7 @@ def check_tasks_parallel(
132
133
  urgency_coefficients,
133
134
  verbose,
134
135
  current_weight,
136
+ frozen_weights,
135
137
  )
136
138
 
137
139
  # Check if any tasks cannot be completed on time
@@ -159,7 +161,9 @@ def check_tasks_parallel(
159
161
  if not tasks_overdue or not auto_adjust_urgency:
160
162
  break
161
163
 
162
- # If we have overdue tasks and auto-adjust is enabled, reduce weight and try again
164
+ for task in tasks_overdue:
165
+ frozen_weights.setdefault(task["uuid"], current_weight)
166
+
163
167
  if verbose:
164
168
  console.print(
165
169
  f"[red]{len(tasks_overdue)} task(s) cannot be completed on time[/red]"
@@ -175,12 +179,12 @@ def check_tasks_parallel(
175
179
  if tasks_overdue:
176
180
  # We tried to adjust but still have overdue tasks
177
181
  console.print(
178
- "[red]Warning: cannot find a solution even with urgency weight 0.0[/red]"
182
+ "[red]Warning: cannot find a solution after per-task urgency adjustment[/red]"
179
183
  )
180
184
  else:
181
185
  # We successfully resolved overdue tasks by adjusting weight
182
186
  console.print(
183
- f"[green]Final urgency weight: {max(current_weight, 0.0):.1f}[/green]"
187
+ f"[green]Resolved deadlines with per-task urgency adjustment[/green]"
184
188
  )
185
189
 
186
190
  if dry_run:
@@ -275,6 +279,7 @@ def allocate_time_for_day(
275
279
  urgency_coefficients,
276
280
  verbose,
277
281
  weight_urgency,
282
+ frozen_weights=None,
278
283
  ):
279
284
  date = datetime.today().date() + timedelta(days=day_offset)
280
285
  total_available_hours = compute_total_available_hours(task_info, day_offset)
@@ -287,7 +292,13 @@ def allocate_time_for_day(
287
292
  tasks_remaining = prepare_tasks_remaining(task_info, day_offset)
288
293
 
289
294
  while day_remaining_hours > 0 and tasks_remaining:
290
- recompute_urgencies(tasks_remaining, urgency_coefficients, date, weight_urgency)
295
+ recompute_urgencies(
296
+ tasks_remaining,
297
+ urgency_coefficients,
298
+ date,
299
+ weight_urgency,
300
+ frozen_weights,
301
+ )
291
302
  sorted_task_ids = sorted(
292
303
  tasks_remaining.keys(),
293
304
  key=lambda x: tasks_remaining[x]["urgency"],
@@ -423,8 +434,11 @@ def update_urgency(info, urgency_key, urgency_compute_fn, urgency_coefficients,
423
434
  info["urgency"] = info["urgency"] - old_urgency + urgency_value
424
435
 
425
436
 
426
- def recompute_urgencies(tasks_remaining, urgency_coefficients, date, weight_urgency):
427
- """Recompute urgency simulating that today is `date`"""
437
+ def recompute_urgencies(
438
+ tasks_remaining, urgency_coefficients, date, weight_urgency, frozen_weights=None
439
+ ):
440
+ """Recompute urgency simulating that today is `date`."""
441
+ frozen_weights = frozen_weights or {}
428
442
  # Recompute estimated urgencies as before
429
443
  for info in tasks_remaining.values():
430
444
  # Update estimated urgency
@@ -438,7 +452,8 @@ def recompute_urgencies(tasks_remaining, urgency_coefficients, date, weight_urge
438
452
 
439
453
  # Apply weights to create a combined score
440
454
  base_urgency = info["urgency"] - info["due_urgency"]
441
- base_urgency *= weight_urgency
455
+ task_weight = frozen_weights.get(info["task"]["uuid"], weight_urgency)
456
+ base_urgency *= task_weight
442
457
  # Always add due_urgency, only weight estimated and age
443
458
  weighted_urgency = base_urgency + info["due_urgency"]
444
459
  info["urgency"] = weighted_urgency
@@ -0,0 +1,114 @@
1
+ Metadata-Version: 2.4
2
+ Name: taskcheck
3
+ Version: 1.3.1
4
+ Summary: Automatic scheduler for taskwarrior
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: appdirs>=1.4.4
8
+ Requires-Dist: google-api-python-client>=2.198.0
9
+ Requires-Dist: google-auth>=2.56.2
10
+ Requires-Dist: google-auth-oauthlib>=1.2.2
11
+ Requires-Dist: icalendar>=6.0.1
12
+ Requires-Dist: random-unicode-emoji>=2.8
13
+ Requires-Dist: requests>=2.32.3
14
+ Requires-Dist: rich>=13.9.4
15
+
16
+ ![immagine](https://github.com/user-attachments/assets/27b83bb1-7a50-4923-a453-0a958fbe11ed)
17
+
18
+ A Taskwarrior scheduler for people who want a realistic plan, not a manual to-do list.
19
+ It turns tasks, working hours, and calendar blocks into an actionable schedule — then keeps due dates visible.
20
+
21
+ Use it if you want to:
22
+ - stop guessing what to do next
23
+ - fit tasks into real availability
24
+ - be sure your long-time plan won't go overdue
25
+ - keep Taskwarrior as the source of truth
26
+
27
+ > [!IMPORTANT]
28
+ > This repo is actively maintained again
29
+
30
+ ## Features
31
+
32
+ - ✨ Auto-schedule tasks from working hours + calendar blocks
33
+ - 🧭 Support complex working-hour maps
34
+ - ⏱️ Consider urgency, due dates, and dependencies
35
+ - 🧪 Dry-run mode to preview changes
36
+ - 🧠 Auto-adjust urgency when deadlines cannot be met
37
+ - 🔄 Force-refresh iCal calendars
38
+ - 📊 Custom reports for planned and unplanned tasks
39
+ - 🎨 Report styling with emoji and extra attributes
40
+ - 🗓️ Block time with iCal or Google Calendar, including all-day events
41
+
42
+ ## Quick start
43
+
44
+ 1. `pipx install taskcheck`
45
+ 2. `taskcheck --install` ← setup only
46
+ 3. add `estimated` + `time_map` UDAs
47
+ 4. edit `~/.config/task/taskcheck.toml` (see [Reference](#Reference))
48
+ 5. `taskcheck --schedule`
49
+
50
+ ## How it works
51
+
52
+ Taskcheck reads your pending and waiting tasks, estimates when each one can be worked on, and writes back a schedule.
53
+ It respects:
54
+ - your working hours
55
+ - task duration estimates
56
+ - calendar events and vacations from iCal / Google Calendar
57
+ - task urgency and due dates
58
+
59
+ It updates Taskwarrior with:
60
+ - `scheduled` → when work should start
61
+ - `completion_date` → when work is expected to finish
62
+ - a warning when a task will miss its due date
63
+
64
+ ### Required UDAs
65
+
66
+ - `estimated`: expected duration in hours
67
+ - `time_map`: which working-hour profile applies to the task, for example `work` or `weekend`
68
+
69
+ Example:
70
+
71
+ ```toml
72
+ [time_maps.work]
73
+ monday = [[9, 12.30], [14, 17]]
74
+ tuesday = [[9, 12.30], [14, 17]]
75
+ ```
76
+
77
+ ### Reports
78
+
79
+ - `taskcheck -r today` → tasks planned for today
80
+ - `taskcheck -r 1w` → tasks planned for the next week
81
+
82
+ ## Reference
83
+
84
+ 📚 Full reference: [REFERENCE.md](REFERENCE.md)
85
+
86
+ In short:
87
+ - `taskcheck --install` is interactive
88
+ - it installs required Taskwarrior settings if you confirm the first prompt
89
+ - it installs optional urgency/report tuning if you confirm the second prompt
90
+ - it can also create the default config file if you confirm the third prompt
91
+ - it does **not** schedule tasks or fetch calendars
92
+ - scheduling happens with `taskcheck --schedule`
93
+ - all flags/config keys/settings are documented in `REFERENCE.md`
94
+
95
+ ## Algorithm
96
+
97
+ The algorithm simulates a workday one chunk at a time.
98
+
99
+ For each day starting from today, it sorts tasks by urgency and picks the most urgent task that fits the available time.
100
+ It assigns a small block of work, then recomputes urgency exactly as Taskwarrior would on that day.
101
+ If urgency changes, the next task choice can change too.
102
+
103
+ For `today`, taskcheck skips past hours.
104
+
105
+ The default work chunk is 2 hours (or less if the task is shorter); you can tune it with the Taskwarrior UDA `min_block`.
106
+
107
+ If a task would finish after its `due_date`, taskcheck retries. It keeps that task's current non-due urgency weight, then lowers the weight by 0.1 only for tasks that have not missed a deadline. Due urgency is never reduced. Retries stop when deadlines are respected or unflagged tasks reach a weight of 0.
108
+
109
+ ## Tips and Tricks
110
+
111
+ - You can exclude a task from being scheduled by removing the `time_map` or `estimated` attributes.
112
+ - You can see tasks that you can execute now with the `task ready` report.
113
+
114
+ See the reference section above for flags, config keys, and installed Taskwarrior settings.
@@ -1,6 +1,8 @@
1
- import pytest
1
+ from importlib.metadata import version
2
2
  from unittest.mock import patch, Mock, mock_open
3
3
 
4
+ import pytest
5
+
4
6
  from taskcheck.__main__ import main, load_config, arg_parser
5
7
 
6
8
 
@@ -99,6 +101,12 @@ class TestArgumentParsing:
99
101
  args = arg_parser.parse_args(["--no-auto-adjust-urgency"])
100
102
  assert args.auto_adjust_urgency is False
101
103
 
104
+ def test_version_argument(self, capsys):
105
+ with pytest.raises(SystemExit, match="0"):
106
+ arg_parser.parse_args(["--version"])
107
+
108
+ assert capsys.readouterr().out == f"taskcheck {version('taskcheck')}\n"
109
+
102
110
 
103
111
  class TestConfigLoading:
104
112
  @patch(
@@ -287,6 +287,32 @@ class TestWeightConfiguration:
287
287
  recompute_urgencies(tasks_remaining, coeffs, date, 0.7)
288
288
  assert tasks_remaining["task-1"]["urgency"] >= tasks_remaining["task-1"]["due_urgency"]
289
289
 
290
+ def test_recompute_urgencies_uses_frozen_weight_per_task(self):
291
+ tasks_remaining = {
292
+ uuid: {
293
+ "task": {"uuid": uuid, "id": index, "entry": "20240101T000000Z"},
294
+ "urgency": 10.0,
295
+ "estimated_urgency": 5.0,
296
+ "due_urgency": 0.0,
297
+ "age_urgency": 0.0,
298
+ "remaining_hours": 2.0,
299
+ "started": False,
300
+ }
301
+ for index, uuid in enumerate(("frozen", "unfrozen"), start=1)
302
+ }
303
+ coeffs = UrgencyCoefficients({"P2H": 5.0}, False, 0, 365, 0, 0)
304
+
305
+ recompute_urgencies(
306
+ tasks_remaining,
307
+ coeffs,
308
+ datetime(2024, 1, 1).date(),
309
+ 0.2,
310
+ frozen_weights={"frozen": 0.7},
311
+ )
312
+
313
+ assert tasks_remaining["frozen"]["urgency"] == 7.0
314
+ assert tasks_remaining["unfrozen"]["urgency"] == 2.0
315
+
290
316
  def test_recompute_urgencies_inherit_and_cycle(self):
291
317
  tasks_remaining = {
292
318
  "a": {"task": {"uuid": "a", "depends": ["b"]}, "urgency": 1.0, "estimated_urgency": 0.0, "due_urgency": 0.0, "age_urgency": 0.0, "remaining_hours": 1.0, "started": False},
@@ -503,7 +529,7 @@ class TestAutoAdjustUrgency:
503
529
  with patch("taskcheck.parallel.console.print") as mock_console_print:
504
530
  check_tasks_parallel(sample_config, verbose=True, taskrc=test_taskrc, auto_adjust_urgency=True)
505
531
  messages = [" ".join(str(arg).lower() for arg in call.args) for call in mock_console_print.call_args_list]
506
- assert any("final urgency weight" in msg or "cannot find a solution" in msg for msg in messages)
532
+ assert any("per-task urgency adjustment" in msg for msg in messages)
507
533
 
508
534
  @patch("taskcheck.parallel.get_calendars")
509
535
  @patch("taskcheck.parallel.get_tasks")
taskcheck-1.2.0/PKG-INFO DELETED
@@ -1,232 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: taskcheck
3
- Version: 1.2.0
4
- Summary: Automatic scheduler for taskwarrior
5
- Requires-Python: >=3.11
6
- Description-Content-Type: text/markdown
7
- Requires-Dist: appdirs>=1.4.4
8
- Requires-Dist: google-api-python-client>=2.198.0
9
- Requires-Dist: google-auth>=2.56.2
10
- Requires-Dist: google-auth-oauthlib>=1.2.2
11
- Requires-Dist: icalendar>=6.0.1
12
- Requires-Dist: random-unicode-emoji>=2.8
13
- Requires-Dist: requests>=2.32.3
14
- Requires-Dist: rich>=13.9.4
15
-
16
- <div align="center">
17
-
18
- ```
19
- ######## ### ###### ## ## ###### ## ## ######## ###### ## ##
20
- ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
21
- ## ## ## ## ## ## ## ## ## ## ## ## ##
22
- ## ## ## ###### ##### ## ######### ###### ## #####
23
- ## ######### ## ## ## ## ## ## ## ## ## ##
24
- ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
25
- ## ## ## ###### ## ## ###### ## ## ######## ###### ## ##
26
- ```
27
-
28
- > _A non-AI automatic scheduler for taskwarrior (i.e. alternative to skedpal / timehero / flowsavvy / reclaim / trevor / motion)_
29
-
30
- ![immagine](https://github.com/user-attachments/assets/27b83bb1-7a50-4923-a453-0a958fbe11ed)
31
-
32
- </div>
33
-
34
- This is a taskwarrior extension that automatically schedules your tasks based on your working hours,
35
- estimated time, and calendar events, finding an optimal time to work on each task and match all your
36
- deadlines.
37
-
38
- > [!IMPORTANT]
39
- > This repo is actively maintained again
40
-
41
- ## Features
42
-
43
- - [x] **Use arbitrarily complex time maps for working hours**
44
- - [x] Block scheduling time using iCal calendars (meetings, vacations, holidays, etc.)
45
- - [x] **Parallel scheduling algorithm for multiple tasks, considering urgency and dependencies**
46
- - [x] Dry-run mode: preview scheduling without modifying your Taskwarrior database
47
- - [x] Custom urgency weighting for scheduling (via CLI or config)
48
- - [x] **Auto-fix scheduling to match due dates**
49
- - [x] Force update of iCal calendars, bypassing cache
50
- - [x] Simple, customizable reports for planned and unplanned tasks
51
- - [x] Emoji and attribute customization in reports
52
- - [ ] Use Google API to access calendars
53
-
54
- ## Install
55
-
56
- 1. `pipx install taskcheck`
57
- 2. `taskcheck --install`
58
-
59
- ## How does it work
60
-
61
- This extension parses your pending and waiting tasks sorted decreasingly by urgency and tries to schedule them in the future.
62
- It considers their estimated time to schedule all tasks starting from the most urgent one.
63
-
64
- #### UDAs
65
-
66
- Taskcheck leverages two UDAs, `estimated` and `time_map`. The `estimated` attribute is
67
- the expected time to complete the task in hours. The `time_map` is a comma-separated list of strings
68
- that indicates the hours per day in which you will work on a task (e.g. `work`, `weekend`, etc.).
69
- The exact correspondence between the `time_map` and the hours of the day is defined in the configuration
70
- file of taskcheck. For instance:
71
-
72
- ```toml
73
- [time_maps]
74
- # get an error)
75
- [time_maps.work]
76
- monday = [[9, 12.30], [14, 17]]
77
- tuesday = [[9, 12.30], [14, 17]]
78
- # ...
79
- ```
80
-
81
- #### They say it's an "AI"
82
-
83
- Taskcheck will also parse online iCal calendars (Google, Apple, etc.) and will match them with your time maps.
84
- It will then modify the Taskwarrior tasks by adding the `completion_date` attribute with the expected
85
- date of completion and the `scheduled` attribute with the date in which the task is expected to
86
- start.
87
-
88
- It will also print a red line for every task whose `completion_date` is after its `due_date`.
89
-
90
- In general, it is recommended to run taskcheck rather frequently and at least once at the beginning
91
- of your working day.
92
-
93
- #### Reports
94
-
95
- You can also print simple reports that exploit the `scheduling` UDA filled by Taskcheck to grasp
96
- how much time you have to work on which task in which day. For
97
- instance:
98
-
99
- - `taskcheck -r today` will show the tasks planned for today
100
- - `taskcheck -r 1w` will show the tasks planned for the next week
101
-
102
- ## Configuration
103
-
104
- `taskcheck --install` allows you to create required and recommended configurations for
105
- Taskwarrior. It will also generate a default configuration file for taskcheck.
106
-
107
- Below is an example of a taskcheck configuration file, with all relevant options:
108
-
109
- ```toml
110
- [time_maps]
111
- # Define your working hours for each named time map (in 24h format, e.g. 9.5 = 9:30)
112
- [time_maps.work]
113
- monday = [[9, 12.30], [14, 17]]
114
- tuesday = [[9, 12.30], [14, 17]]
115
- wednesday = [[9, 12.30], [14, 17]]
116
- thursday = [[9, 12.30], [14, 17]]
117
- friday = [[9, 12.30], [14, 17]]
118
-
119
- [time_maps.weekend]
120
- saturday = [[9, 12.30]]
121
- sunday = [[9, 12.30]]
122
-
123
- [scheduler]
124
- days_ahead = 1000 # How far to go with the schedule (lower values = faster computation)
125
- weight_urgency = 1.0 # Default weight for urgency in scheduling (overridable via CLI)
126
- # if weight_urgency is set to 0, only due urgency is considered
127
- # by default, this factor is automatically reduced if some task cannot be scheduled in time,
128
- # leading to tasks with due dates being prioritized (see --no-auto-adjust-urgency)
129
-
130
- [calendars]
131
- # iCal calendars can be used to block your time and make the scheduling more precise
132
- [calendars.1]
133
- url = "https://your/url/to/calendar.ics"
134
- expiration = 0.08 # In hours (0.08 hours ≈ 5 minutes)
135
- timezone = "Europe/Rome" # If set, force timezone for this calendar (see TZ database)
136
-
137
- [calendars.holidays]
138
- url = "https://www.officeholidays.com/ics-clean/italy/milan"
139
- event_all_day_is_blocking = true
140
- expiration = 720 # In hours (720 hours = 30 days)
141
-
142
- [report]
143
- include_unplanned = true
144
- additional_attributes = ["estimated", "due", "urgency"] # Extra attributes to show in the report
145
- additional_attributes_unplanned = ["due", "urgency"] # Extra attributes for unplanned tasks
146
- unplanned_max_due = "30d" # Only show unplanned tasks due within this Taskwarrior-relative horizon; tasks without a due date are always shown
147
- emoji_keywords = {"meet"=":busts_in_silhouette:", "review"=":mag_right:"} # Map keywords to emoji
148
- ```
149
-
150
- ### Configuration Options
151
-
152
- - **[scheduler]**
153
- - `days_ahead`: How many days ahead to schedule tasks.
154
- - `weight_urgency`: Default weight for urgency in scheduling (0.0 to 1.0). Can be overridden with `--urgency-weight`.
155
- - **[calendars]**
156
- - `url`: iCal URL to block time.
157
- - `expiration`: Cache expiration in hours.
158
- - `timezone`: (Optional) Force a timezone for this calendar.
159
- - `event_all_day_is_blocking`: (Optional, bool) Treat all-day events as blocking.
160
- - **[report]**
161
- - `include_unplanned`: Show unplanned tasks in a separate section.
162
- - `additional_attributes`: Extra columns to show in the report.
163
- - `additional_attributes_unplanned`: Extra columns for unplanned tasks.
164
- - `unplanned_max_due`: Optional Taskwarrior-relative horizon (for example `30d`) for dated unplanned tasks. Tasks without a due date are always shown; omitting this setting applies no limit.
165
- - `emoji_keywords`: Map keywords in task descriptions to emoji.
166
-
167
- ## Algorithm
168
-
169
- The algorithm simulates what happens if you work on a task for a certain time on a given day.
170
-
171
- For each day X starting from today, it sorts the tasks by decreasing urgency.
172
- It start from the most urgent tasks that can be allocated on day X depending on the task's
173
- `time_map` and on your calendars. It allocates a few number of hours to the task,
174
- then recomputes the urgencies exactly as Taskwarrior would do
175
- if it was running on day X. Having recomputed the urgencies, it restarts.
176
-
177
- If after 2 hours a long task has decreased its urgency, it will be noticed and the newer most urgent
178
- task will get scheduled in its place.
179
-
180
- For `today`, taskcheck will skip the hours in the past -- i.e. if you're running at 12 pm, it will
181
- skip all the available slots until 12 pm.
182
-
183
- The maximum time that is allocated at each attempt is by default 2 hours
184
- (or less if the task is shorter), but you can change it by tuning the Taskwarrior UDA `min_block`.
185
-
186
- After the scheduling is done, if any task has a `completion_date` after its `due_date`, the
187
- `weight_urgency` factor is reduced by 0.1 and the scheduling is repeated, until all tasks
188
- are scheduled before their due dates or the `weight_urgency` factor reaches 0.
189
-
190
- ## Tips and Tricks
191
-
192
- - You can exclude a task from being scheduled by removing the `time_map` or `estimated` attributes.
193
- - You can see tasks that you can execute now with the `task ready` report.
194
-
195
- ## CLI Options
196
-
197
- ```
198
- usage: __main__.py [-h] [-v] [-i] [-r REPORT] [-s] [-f] [--taskrc TASKRC] [--urgency-weight URGENCY_WEIGHT] [--dry-run] [--no-auto-adjust-urgency]
199
-
200
- options:
201
- -h, --help show this help message and exit
202
- -v, --verbose Increase output verbosity.
203
- -i, --install Install the UDAs, required settings, and default config file.
204
- -r REPORT, --report REPORT
205
- Generate a report of the tasks based on the scheduling; can be any Taskwarrior datetime specification (e.g. today, tomorrow, eom, som, 1st, 2nd, etc.). It is considered as `by`, meaning that the report will be
206
- generated for all the days until the specified date and including it.
207
- -s, --schedule Perform the scheduling algorithm, giving a schedule and a scheduling UDA and alerting for not completable tasks
208
- -f, --force-update Force update of all ical calendars by ignoring cache expiration
209
- --taskrc TASKRC Set custom TASKRC directory for debugging purposes
210
- --urgency-weight URGENCY_WEIGHT
211
- Weight for urgency in scheduling (0.0 to 1.0), overrides config value. When 1.0, the whole Taskwarrior urgency is used for scheduling. When 0.0, the Taskwarrior urgency is reduced to only due urgency.
212
- --dry-run Perform scheduling without modifying the Taskwarrior database, useful for testing
213
- --no-auto-adjust-urgency
214
- Disable automatic reduction of urgency weight … (default: enabled)
215
- ```
216
-
217
- ### Examples
218
-
219
- - `taskcheck --schedule`
220
- Run the scheduler and update your Taskwarrior tasks.
221
- - `taskcheck --schedule --dry-run`
222
- Preview the schedule without modifying your database.
223
- - `taskcheck --schedule --urgency-weight 0.5`
224
- Use a custom urgency weighting for this run.
225
- - `taskcheck --schedule --no-auto-adjust-urgency`
226
- Avoid the automatically reduction of urgency weight if tasks can't be scheduled before their due dates.
227
- - `taskcheck --report today`
228
- Show the schedule for today.
229
- - `taskcheck --report 1w`
230
- Show the schedule for the next week.
231
- - `taskcheck --force-update`
232
- Force refresh of all iCal calendars, ignoring cache.
taskcheck-1.2.0/README.md DELETED
@@ -1,217 +0,0 @@
1
- <div align="center">
2
-
3
- ```
4
- ######## ### ###### ## ## ###### ## ## ######## ###### ## ##
5
- ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6
- ## ## ## ## ## ## ## ## ## ## ## ## ##
7
- ## ## ## ###### ##### ## ######### ###### ## #####
8
- ## ######### ## ## ## ## ## ## ## ## ## ##
9
- ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
10
- ## ## ## ###### ## ## ###### ## ## ######## ###### ## ##
11
- ```
12
-
13
- > _A non-AI automatic scheduler for taskwarrior (i.e. alternative to skedpal / timehero / flowsavvy / reclaim / trevor / motion)_
14
-
15
- ![immagine](https://github.com/user-attachments/assets/27b83bb1-7a50-4923-a453-0a958fbe11ed)
16
-
17
- </div>
18
-
19
- This is a taskwarrior extension that automatically schedules your tasks based on your working hours,
20
- estimated time, and calendar events, finding an optimal time to work on each task and match all your
21
- deadlines.
22
-
23
- > [!IMPORTANT]
24
- > This repo is actively maintained again
25
-
26
- ## Features
27
-
28
- - [x] **Use arbitrarily complex time maps for working hours**
29
- - [x] Block scheduling time using iCal calendars (meetings, vacations, holidays, etc.)
30
- - [x] **Parallel scheduling algorithm for multiple tasks, considering urgency and dependencies**
31
- - [x] Dry-run mode: preview scheduling without modifying your Taskwarrior database
32
- - [x] Custom urgency weighting for scheduling (via CLI or config)
33
- - [x] **Auto-fix scheduling to match due dates**
34
- - [x] Force update of iCal calendars, bypassing cache
35
- - [x] Simple, customizable reports for planned and unplanned tasks
36
- - [x] Emoji and attribute customization in reports
37
- - [ ] Use Google API to access calendars
38
-
39
- ## Install
40
-
41
- 1. `pipx install taskcheck`
42
- 2. `taskcheck --install`
43
-
44
- ## How does it work
45
-
46
- This extension parses your pending and waiting tasks sorted decreasingly by urgency and tries to schedule them in the future.
47
- It considers their estimated time to schedule all tasks starting from the most urgent one.
48
-
49
- #### UDAs
50
-
51
- Taskcheck leverages two UDAs, `estimated` and `time_map`. The `estimated` attribute is
52
- the expected time to complete the task in hours. The `time_map` is a comma-separated list of strings
53
- that indicates the hours per day in which you will work on a task (e.g. `work`, `weekend`, etc.).
54
- The exact correspondence between the `time_map` and the hours of the day is defined in the configuration
55
- file of taskcheck. For instance:
56
-
57
- ```toml
58
- [time_maps]
59
- # get an error)
60
- [time_maps.work]
61
- monday = [[9, 12.30], [14, 17]]
62
- tuesday = [[9, 12.30], [14, 17]]
63
- # ...
64
- ```
65
-
66
- #### They say it's an "AI"
67
-
68
- Taskcheck will also parse online iCal calendars (Google, Apple, etc.) and will match them with your time maps.
69
- It will then modify the Taskwarrior tasks by adding the `completion_date` attribute with the expected
70
- date of completion and the `scheduled` attribute with the date in which the task is expected to
71
- start.
72
-
73
- It will also print a red line for every task whose `completion_date` is after its `due_date`.
74
-
75
- In general, it is recommended to run taskcheck rather frequently and at least once at the beginning
76
- of your working day.
77
-
78
- #### Reports
79
-
80
- You can also print simple reports that exploit the `scheduling` UDA filled by Taskcheck to grasp
81
- how much time you have to work on which task in which day. For
82
- instance:
83
-
84
- - `taskcheck -r today` will show the tasks planned for today
85
- - `taskcheck -r 1w` will show the tasks planned for the next week
86
-
87
- ## Configuration
88
-
89
- `taskcheck --install` allows you to create required and recommended configurations for
90
- Taskwarrior. It will also generate a default configuration file for taskcheck.
91
-
92
- Below is an example of a taskcheck configuration file, with all relevant options:
93
-
94
- ```toml
95
- [time_maps]
96
- # Define your working hours for each named time map (in 24h format, e.g. 9.5 = 9:30)
97
- [time_maps.work]
98
- monday = [[9, 12.30], [14, 17]]
99
- tuesday = [[9, 12.30], [14, 17]]
100
- wednesday = [[9, 12.30], [14, 17]]
101
- thursday = [[9, 12.30], [14, 17]]
102
- friday = [[9, 12.30], [14, 17]]
103
-
104
- [time_maps.weekend]
105
- saturday = [[9, 12.30]]
106
- sunday = [[9, 12.30]]
107
-
108
- [scheduler]
109
- days_ahead = 1000 # How far to go with the schedule (lower values = faster computation)
110
- weight_urgency = 1.0 # Default weight for urgency in scheduling (overridable via CLI)
111
- # if weight_urgency is set to 0, only due urgency is considered
112
- # by default, this factor is automatically reduced if some task cannot be scheduled in time,
113
- # leading to tasks with due dates being prioritized (see --no-auto-adjust-urgency)
114
-
115
- [calendars]
116
- # iCal calendars can be used to block your time and make the scheduling more precise
117
- [calendars.1]
118
- url = "https://your/url/to/calendar.ics"
119
- expiration = 0.08 # In hours (0.08 hours ≈ 5 minutes)
120
- timezone = "Europe/Rome" # If set, force timezone for this calendar (see TZ database)
121
-
122
- [calendars.holidays]
123
- url = "https://www.officeholidays.com/ics-clean/italy/milan"
124
- event_all_day_is_blocking = true
125
- expiration = 720 # In hours (720 hours = 30 days)
126
-
127
- [report]
128
- include_unplanned = true
129
- additional_attributes = ["estimated", "due", "urgency"] # Extra attributes to show in the report
130
- additional_attributes_unplanned = ["due", "urgency"] # Extra attributes for unplanned tasks
131
- unplanned_max_due = "30d" # Only show unplanned tasks due within this Taskwarrior-relative horizon; tasks without a due date are always shown
132
- emoji_keywords = {"meet"=":busts_in_silhouette:", "review"=":mag_right:"} # Map keywords to emoji
133
- ```
134
-
135
- ### Configuration Options
136
-
137
- - **[scheduler]**
138
- - `days_ahead`: How many days ahead to schedule tasks.
139
- - `weight_urgency`: Default weight for urgency in scheduling (0.0 to 1.0). Can be overridden with `--urgency-weight`.
140
- - **[calendars]**
141
- - `url`: iCal URL to block time.
142
- - `expiration`: Cache expiration in hours.
143
- - `timezone`: (Optional) Force a timezone for this calendar.
144
- - `event_all_day_is_blocking`: (Optional, bool) Treat all-day events as blocking.
145
- - **[report]**
146
- - `include_unplanned`: Show unplanned tasks in a separate section.
147
- - `additional_attributes`: Extra columns to show in the report.
148
- - `additional_attributes_unplanned`: Extra columns for unplanned tasks.
149
- - `unplanned_max_due`: Optional Taskwarrior-relative horizon (for example `30d`) for dated unplanned tasks. Tasks without a due date are always shown; omitting this setting applies no limit.
150
- - `emoji_keywords`: Map keywords in task descriptions to emoji.
151
-
152
- ## Algorithm
153
-
154
- The algorithm simulates what happens if you work on a task for a certain time on a given day.
155
-
156
- For each day X starting from today, it sorts the tasks by decreasing urgency.
157
- It start from the most urgent tasks that can be allocated on day X depending on the task's
158
- `time_map` and on your calendars. It allocates a few number of hours to the task,
159
- then recomputes the urgencies exactly as Taskwarrior would do
160
- if it was running on day X. Having recomputed the urgencies, it restarts.
161
-
162
- If after 2 hours a long task has decreased its urgency, it will be noticed and the newer most urgent
163
- task will get scheduled in its place.
164
-
165
- For `today`, taskcheck will skip the hours in the past -- i.e. if you're running at 12 pm, it will
166
- skip all the available slots until 12 pm.
167
-
168
- The maximum time that is allocated at each attempt is by default 2 hours
169
- (or less if the task is shorter), but you can change it by tuning the Taskwarrior UDA `min_block`.
170
-
171
- After the scheduling is done, if any task has a `completion_date` after its `due_date`, the
172
- `weight_urgency` factor is reduced by 0.1 and the scheduling is repeated, until all tasks
173
- are scheduled before their due dates or the `weight_urgency` factor reaches 0.
174
-
175
- ## Tips and Tricks
176
-
177
- - You can exclude a task from being scheduled by removing the `time_map` or `estimated` attributes.
178
- - You can see tasks that you can execute now with the `task ready` report.
179
-
180
- ## CLI Options
181
-
182
- ```
183
- usage: __main__.py [-h] [-v] [-i] [-r REPORT] [-s] [-f] [--taskrc TASKRC] [--urgency-weight URGENCY_WEIGHT] [--dry-run] [--no-auto-adjust-urgency]
184
-
185
- options:
186
- -h, --help show this help message and exit
187
- -v, --verbose Increase output verbosity.
188
- -i, --install Install the UDAs, required settings, and default config file.
189
- -r REPORT, --report REPORT
190
- Generate a report of the tasks based on the scheduling; can be any Taskwarrior datetime specification (e.g. today, tomorrow, eom, som, 1st, 2nd, etc.). It is considered as `by`, meaning that the report will be
191
- generated for all the days until the specified date and including it.
192
- -s, --schedule Perform the scheduling algorithm, giving a schedule and a scheduling UDA and alerting for not completable tasks
193
- -f, --force-update Force update of all ical calendars by ignoring cache expiration
194
- --taskrc TASKRC Set custom TASKRC directory for debugging purposes
195
- --urgency-weight URGENCY_WEIGHT
196
- Weight for urgency in scheduling (0.0 to 1.0), overrides config value. When 1.0, the whole Taskwarrior urgency is used for scheduling. When 0.0, the Taskwarrior urgency is reduced to only due urgency.
197
- --dry-run Perform scheduling without modifying the Taskwarrior database, useful for testing
198
- --no-auto-adjust-urgency
199
- Disable automatic reduction of urgency weight … (default: enabled)
200
- ```
201
-
202
- ### Examples
203
-
204
- - `taskcheck --schedule`
205
- Run the scheduler and update your Taskwarrior tasks.
206
- - `taskcheck --schedule --dry-run`
207
- Preview the schedule without modifying your database.
208
- - `taskcheck --schedule --urgency-weight 0.5`
209
- Use a custom urgency weighting for this run.
210
- - `taskcheck --schedule --no-auto-adjust-urgency`
211
- Avoid the automatically reduction of urgency weight if tasks can't be scheduled before their due dates.
212
- - `taskcheck --report today`
213
- Show the schedule for today.
214
- - `taskcheck --report 1w`
215
- Show the schedule for the next week.
216
- - `taskcheck --force-update`
217
- Force refresh of all iCal calendars, ignoring cache.
@@ -1,232 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: taskcheck
3
- Version: 1.2.0
4
- Summary: Automatic scheduler for taskwarrior
5
- Requires-Python: >=3.11
6
- Description-Content-Type: text/markdown
7
- Requires-Dist: appdirs>=1.4.4
8
- Requires-Dist: google-api-python-client>=2.198.0
9
- Requires-Dist: google-auth>=2.56.2
10
- Requires-Dist: google-auth-oauthlib>=1.2.2
11
- Requires-Dist: icalendar>=6.0.1
12
- Requires-Dist: random-unicode-emoji>=2.8
13
- Requires-Dist: requests>=2.32.3
14
- Requires-Dist: rich>=13.9.4
15
-
16
- <div align="center">
17
-
18
- ```
19
- ######## ### ###### ## ## ###### ## ## ######## ###### ## ##
20
- ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
21
- ## ## ## ## ## ## ## ## ## ## ## ## ##
22
- ## ## ## ###### ##### ## ######### ###### ## #####
23
- ## ######### ## ## ## ## ## ## ## ## ## ##
24
- ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
25
- ## ## ## ###### ## ## ###### ## ## ######## ###### ## ##
26
- ```
27
-
28
- > _A non-AI automatic scheduler for taskwarrior (i.e. alternative to skedpal / timehero / flowsavvy / reclaim / trevor / motion)_
29
-
30
- ![immagine](https://github.com/user-attachments/assets/27b83bb1-7a50-4923-a453-0a958fbe11ed)
31
-
32
- </div>
33
-
34
- This is a taskwarrior extension that automatically schedules your tasks based on your working hours,
35
- estimated time, and calendar events, finding an optimal time to work on each task and match all your
36
- deadlines.
37
-
38
- > [!IMPORTANT]
39
- > This repo is actively maintained again
40
-
41
- ## Features
42
-
43
- - [x] **Use arbitrarily complex time maps for working hours**
44
- - [x] Block scheduling time using iCal calendars (meetings, vacations, holidays, etc.)
45
- - [x] **Parallel scheduling algorithm for multiple tasks, considering urgency and dependencies**
46
- - [x] Dry-run mode: preview scheduling without modifying your Taskwarrior database
47
- - [x] Custom urgency weighting for scheduling (via CLI or config)
48
- - [x] **Auto-fix scheduling to match due dates**
49
- - [x] Force update of iCal calendars, bypassing cache
50
- - [x] Simple, customizable reports for planned and unplanned tasks
51
- - [x] Emoji and attribute customization in reports
52
- - [ ] Use Google API to access calendars
53
-
54
- ## Install
55
-
56
- 1. `pipx install taskcheck`
57
- 2. `taskcheck --install`
58
-
59
- ## How does it work
60
-
61
- This extension parses your pending and waiting tasks sorted decreasingly by urgency and tries to schedule them in the future.
62
- It considers their estimated time to schedule all tasks starting from the most urgent one.
63
-
64
- #### UDAs
65
-
66
- Taskcheck leverages two UDAs, `estimated` and `time_map`. The `estimated` attribute is
67
- the expected time to complete the task in hours. The `time_map` is a comma-separated list of strings
68
- that indicates the hours per day in which you will work on a task (e.g. `work`, `weekend`, etc.).
69
- The exact correspondence between the `time_map` and the hours of the day is defined in the configuration
70
- file of taskcheck. For instance:
71
-
72
- ```toml
73
- [time_maps]
74
- # get an error)
75
- [time_maps.work]
76
- monday = [[9, 12.30], [14, 17]]
77
- tuesday = [[9, 12.30], [14, 17]]
78
- # ...
79
- ```
80
-
81
- #### They say it's an "AI"
82
-
83
- Taskcheck will also parse online iCal calendars (Google, Apple, etc.) and will match them with your time maps.
84
- It will then modify the Taskwarrior tasks by adding the `completion_date` attribute with the expected
85
- date of completion and the `scheduled` attribute with the date in which the task is expected to
86
- start.
87
-
88
- It will also print a red line for every task whose `completion_date` is after its `due_date`.
89
-
90
- In general, it is recommended to run taskcheck rather frequently and at least once at the beginning
91
- of your working day.
92
-
93
- #### Reports
94
-
95
- You can also print simple reports that exploit the `scheduling` UDA filled by Taskcheck to grasp
96
- how much time you have to work on which task in which day. For
97
- instance:
98
-
99
- - `taskcheck -r today` will show the tasks planned for today
100
- - `taskcheck -r 1w` will show the tasks planned for the next week
101
-
102
- ## Configuration
103
-
104
- `taskcheck --install` allows you to create required and recommended configurations for
105
- Taskwarrior. It will also generate a default configuration file for taskcheck.
106
-
107
- Below is an example of a taskcheck configuration file, with all relevant options:
108
-
109
- ```toml
110
- [time_maps]
111
- # Define your working hours for each named time map (in 24h format, e.g. 9.5 = 9:30)
112
- [time_maps.work]
113
- monday = [[9, 12.30], [14, 17]]
114
- tuesday = [[9, 12.30], [14, 17]]
115
- wednesday = [[9, 12.30], [14, 17]]
116
- thursday = [[9, 12.30], [14, 17]]
117
- friday = [[9, 12.30], [14, 17]]
118
-
119
- [time_maps.weekend]
120
- saturday = [[9, 12.30]]
121
- sunday = [[9, 12.30]]
122
-
123
- [scheduler]
124
- days_ahead = 1000 # How far to go with the schedule (lower values = faster computation)
125
- weight_urgency = 1.0 # Default weight for urgency in scheduling (overridable via CLI)
126
- # if weight_urgency is set to 0, only due urgency is considered
127
- # by default, this factor is automatically reduced if some task cannot be scheduled in time,
128
- # leading to tasks with due dates being prioritized (see --no-auto-adjust-urgency)
129
-
130
- [calendars]
131
- # iCal calendars can be used to block your time and make the scheduling more precise
132
- [calendars.1]
133
- url = "https://your/url/to/calendar.ics"
134
- expiration = 0.08 # In hours (0.08 hours ≈ 5 minutes)
135
- timezone = "Europe/Rome" # If set, force timezone for this calendar (see TZ database)
136
-
137
- [calendars.holidays]
138
- url = "https://www.officeholidays.com/ics-clean/italy/milan"
139
- event_all_day_is_blocking = true
140
- expiration = 720 # In hours (720 hours = 30 days)
141
-
142
- [report]
143
- include_unplanned = true
144
- additional_attributes = ["estimated", "due", "urgency"] # Extra attributes to show in the report
145
- additional_attributes_unplanned = ["due", "urgency"] # Extra attributes for unplanned tasks
146
- unplanned_max_due = "30d" # Only show unplanned tasks due within this Taskwarrior-relative horizon; tasks without a due date are always shown
147
- emoji_keywords = {"meet"=":busts_in_silhouette:", "review"=":mag_right:"} # Map keywords to emoji
148
- ```
149
-
150
- ### Configuration Options
151
-
152
- - **[scheduler]**
153
- - `days_ahead`: How many days ahead to schedule tasks.
154
- - `weight_urgency`: Default weight for urgency in scheduling (0.0 to 1.0). Can be overridden with `--urgency-weight`.
155
- - **[calendars]**
156
- - `url`: iCal URL to block time.
157
- - `expiration`: Cache expiration in hours.
158
- - `timezone`: (Optional) Force a timezone for this calendar.
159
- - `event_all_day_is_blocking`: (Optional, bool) Treat all-day events as blocking.
160
- - **[report]**
161
- - `include_unplanned`: Show unplanned tasks in a separate section.
162
- - `additional_attributes`: Extra columns to show in the report.
163
- - `additional_attributes_unplanned`: Extra columns for unplanned tasks.
164
- - `unplanned_max_due`: Optional Taskwarrior-relative horizon (for example `30d`) for dated unplanned tasks. Tasks without a due date are always shown; omitting this setting applies no limit.
165
- - `emoji_keywords`: Map keywords in task descriptions to emoji.
166
-
167
- ## Algorithm
168
-
169
- The algorithm simulates what happens if you work on a task for a certain time on a given day.
170
-
171
- For each day X starting from today, it sorts the tasks by decreasing urgency.
172
- It start from the most urgent tasks that can be allocated on day X depending on the task's
173
- `time_map` and on your calendars. It allocates a few number of hours to the task,
174
- then recomputes the urgencies exactly as Taskwarrior would do
175
- if it was running on day X. Having recomputed the urgencies, it restarts.
176
-
177
- If after 2 hours a long task has decreased its urgency, it will be noticed and the newer most urgent
178
- task will get scheduled in its place.
179
-
180
- For `today`, taskcheck will skip the hours in the past -- i.e. if you're running at 12 pm, it will
181
- skip all the available slots until 12 pm.
182
-
183
- The maximum time that is allocated at each attempt is by default 2 hours
184
- (or less if the task is shorter), but you can change it by tuning the Taskwarrior UDA `min_block`.
185
-
186
- After the scheduling is done, if any task has a `completion_date` after its `due_date`, the
187
- `weight_urgency` factor is reduced by 0.1 and the scheduling is repeated, until all tasks
188
- are scheduled before their due dates or the `weight_urgency` factor reaches 0.
189
-
190
- ## Tips and Tricks
191
-
192
- - You can exclude a task from being scheduled by removing the `time_map` or `estimated` attributes.
193
- - You can see tasks that you can execute now with the `task ready` report.
194
-
195
- ## CLI Options
196
-
197
- ```
198
- usage: __main__.py [-h] [-v] [-i] [-r REPORT] [-s] [-f] [--taskrc TASKRC] [--urgency-weight URGENCY_WEIGHT] [--dry-run] [--no-auto-adjust-urgency]
199
-
200
- options:
201
- -h, --help show this help message and exit
202
- -v, --verbose Increase output verbosity.
203
- -i, --install Install the UDAs, required settings, and default config file.
204
- -r REPORT, --report REPORT
205
- Generate a report of the tasks based on the scheduling; can be any Taskwarrior datetime specification (e.g. today, tomorrow, eom, som, 1st, 2nd, etc.). It is considered as `by`, meaning that the report will be
206
- generated for all the days until the specified date and including it.
207
- -s, --schedule Perform the scheduling algorithm, giving a schedule and a scheduling UDA and alerting for not completable tasks
208
- -f, --force-update Force update of all ical calendars by ignoring cache expiration
209
- --taskrc TASKRC Set custom TASKRC directory for debugging purposes
210
- --urgency-weight URGENCY_WEIGHT
211
- Weight for urgency in scheduling (0.0 to 1.0), overrides config value. When 1.0, the whole Taskwarrior urgency is used for scheduling. When 0.0, the Taskwarrior urgency is reduced to only due urgency.
212
- --dry-run Perform scheduling without modifying the Taskwarrior database, useful for testing
213
- --no-auto-adjust-urgency
214
- Disable automatic reduction of urgency weight … (default: enabled)
215
- ```
216
-
217
- ### Examples
218
-
219
- - `taskcheck --schedule`
220
- Run the scheduler and update your Taskwarrior tasks.
221
- - `taskcheck --schedule --dry-run`
222
- Preview the schedule without modifying your database.
223
- - `taskcheck --schedule --urgency-weight 0.5`
224
- Use a custom urgency weighting for this run.
225
- - `taskcheck --schedule --no-auto-adjust-urgency`
226
- Avoid the automatically reduction of urgency weight if tasks can't be scheduled before their due dates.
227
- - `taskcheck --report today`
228
- Show the schedule for today.
229
- - `taskcheck --report 1w`
230
- Show the schedule for the next week.
231
- - `taskcheck --force-update`
232
- Force refresh of all iCal calendars, ignoring cache.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes