Metadata-Version: 2.1
Name: task-tracker-py
Version: 0.1.0
Summary: task-tracker-py: the .tracker/tasks/ format linter and CLI, stdlib only
Home-page: https://gitlab.com/meehai/task-tracker
License: MIT
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Provides-Extra: dev
Requires-Dist: pytest>=8.4; extra == "dev"

# task

A CLI for `.tracker/tasks/` task trackers: one dir per task, one `TASK.md` each. **Stdlib only, no
regular expressions.**

## Format

```
.tracker/tasks/{open,closed}/<ID>-<slug>/TASK.md   (attachments allowed beside it)
```

```
# Task title

**Created**: 2026-04-21
**Priority**: 2
**Closed**: n/a

... free form description ...
```

- The dir is `<ID>-<anything>`; only the ID before the first dash is read (`01-` is ID 1).
- IDs are integers 1..N, unique across `open/` + `closed/`, no gaps: deleting a task moves the highest-ID
  task into the hole.
- The header fields come in any order, each once, followed by an empty line.
- `**Created**` is an ISO date (or datetime). `**Closed**` is `n/a` in `open/`, and an ISO date no earlier
  than `**Created**` in `closed/`.
- `**Priority**` is a positive integer, higher is more urgent.
- Files directly in `open/` or `closed/` (e.g. `.gitkeep`) are ignored.

`task.Task` is one task, validated in `__post_init__` (wrong type: `TypeError`, bad value: `ValueError`). It can
be built in memory: its `TASK.md` need not exist, but its `extra_files` must. `task_from_path(task_dir)` reads a
task dir into a `Task`.

## `task/task.py [--dir <tasks_dir>] {ls,create,check}`

`--dir` defaults to `./.tracker/tasks`. Logs go through `logging`; set `TASK_LOGLEVEL` (default `INFO`).

```bash
python task/task.py ls                   # open tasks, by priority then ID
python task/task.py ls --include_closed  # plus closed ones
python -m task.task -d .tracker/tasks ls # same, via the installed package (`pip install .`)
```

`check` parses every task (so any format violation raises), then raises `ValueError` on duplicate IDs, an ID
gap (IDs must be 1..N), or a task whose `**Closed**` does not match its `open/` / `closed/` dir. `create` is
not implemented yet (task 1).

## Tests

```bash
python -m pytest test/
```

One broken rule per case:

- `test/unit/test_task.py` — `Task` field rules, on in-memory tasks.
- `test/unit/test_task_from_path.py` — the on-disk format: dir name, header, dates, extra files; `main` on a
  throwaway tracker.
- `test/unit/test_task_check.py` — `check` in-process (`handle_command`) on in-memory tasks: IDs and
  open/closed status.

`python test/lint/run_all.py` runs ruff and pylint.

## Acknowledgments

Inspired by tsoding's [tatr](https://github.com/tsoding/tatr): tasks as plain files in the repo, driven by
a small CLI.
