bot-todo 0.2.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.
- bot_todo-0.2.1/PKG-INFO +318 -0
- bot_todo-0.2.1/README.md +299 -0
- bot_todo-0.2.1/pyproject.toml +84 -0
- bot_todo-0.2.1/pyproject.toml.orig +80 -0
- bot_todo-0.2.1/src/bot_todo/__init__.py +19 -0
- bot_todo-0.2.1/src/bot_todo/cli.py +1622 -0
- bot_todo-0.2.1/src/bot_todo/config.py +746 -0
- bot_todo-0.2.1/src/bot_todo/repository.py +1775 -0
- bot_todo-0.2.1/src/bot_todo/skill_assets/task_management.md +9 -0
- bot_todo-0.2.1/src/bot_todo/skill_assets/todo/SKILL.md +136 -0
- bot_todo-0.2.1/src/bot_todo/skill_assets/todo/agents/openai.yaml +4 -0
- bot_todo-0.2.1/src/bot_todo/skill_installation.py +537 -0
- bot_todo-0.2.1/src/bot_todo/task_management_snippet.py +35 -0
bot_todo-0.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: bot-todo
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Manage canonical repository task files.
|
|
5
|
+
Classifier: Development Status :: 4 - Beta
|
|
6
|
+
Classifier: Intended Audience :: Developers
|
|
7
|
+
Classifier: Operating System :: OS Independent
|
|
8
|
+
Classifier: Programming Language :: Python
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Natural Language :: English
|
|
13
|
+
Classifier: Topic :: Utilities
|
|
14
|
+
Requires-Dist: portalocker>=2.7
|
|
15
|
+
Requires-Python: >=3.11
|
|
16
|
+
Project-URL: Homepage, https://github.com/caltechads/bot-todo
|
|
17
|
+
Project-URL: Repository, https://github.com/caltechads/bot-todo
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# bot-todo
|
|
21
|
+
|
|
22
|
+
`bot-todo` is a command-line tool for a canonical, Git-friendly task backlog.
|
|
23
|
+
Humans and coding agents share one `TODO.md` per repository and mutate it only
|
|
24
|
+
through this CLI.
|
|
25
|
+
|
|
26
|
+
The package also ships a thin `todo` skill that teaches Codex, Claude, Cursor,
|
|
27
|
+
and Grok to call `bot-todo` instead of editing the task files by hand.
|
|
28
|
+
|
|
29
|
+
## Requirements
|
|
30
|
+
|
|
31
|
+
- Python 3.11 or newer
|
|
32
|
+
- [uv](https://docs.astral.sh/uv/) for installation (recommended)
|
|
33
|
+
|
|
34
|
+
The only runtime dependency is `portalocker`, used for per-repository locking.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
uv tool bot-todo
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
That puts `bot-todo` on your `PATH` in an isolated environment. While hacking
|
|
43
|
+
on the CLI itself, keep the checkout live:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
uv tool install --editable .
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
One-shot use without a persistent install:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
uvx --from . bot-todo --help
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Confirm the install:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
bot-todo --version
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Quick start
|
|
62
|
+
|
|
63
|
+
From a project directory:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
bot-todo init
|
|
67
|
+
bot-todo add "Write the README" --type docs --priority P1 --acceptance "README covers install and usage"
|
|
68
|
+
bot-todo list
|
|
69
|
+
bot-todo claim T001 --actor glenn
|
|
70
|
+
bot-todo complete T001
|
|
71
|
+
bot-todo validate
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`init` always targets the current directory (or `--root`). Omit `--name` to use
|
|
75
|
+
the repository directory basename as the project heading. Successful human
|
|
76
|
+
`init` prints a copy-paste Task Management section for `AGENTS.md` or
|
|
77
|
+
`CLAUDE.md`; JSON `init` includes that text as `data.snippet`. `bot-todo`
|
|
78
|
+
never writes those instruction files. Other commands without a selector walk
|
|
79
|
+
from the current directory toward the filesystem root and use the nearest
|
|
80
|
+
`TODO.md`.
|
|
81
|
+
|
|
82
|
+
## Usage
|
|
83
|
+
|
|
84
|
+
Global options precede the command:
|
|
85
|
+
|
|
86
|
+
```text
|
|
87
|
+
bot-todo [--json] [--config PATH] [--root PATH | --repo NAME | --all] COMMAND ...
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`--help` and `--version` always print human text and succeed, including when
|
|
91
|
+
`--json` is present. Commands never prompt, page, or colorize output.
|
|
92
|
+
|
|
93
|
+
### Commands
|
|
94
|
+
|
|
95
|
+
| Command | Purpose |
|
|
96
|
+
| --- | --- |
|
|
97
|
+
| `init [--name NAME]` | Create `TODO.md` and `TODO.archive.md` |
|
|
98
|
+
| `validate` | Check the canonical files |
|
|
99
|
+
| `list` | List open and review tasks |
|
|
100
|
+
| `show TASK_ID` | Print one task |
|
|
101
|
+
| `critical` | Highest-priority open task (even if blocked or claimed) |
|
|
102
|
+
| `actionable` | First unclaimed open task whose blockers are completed |
|
|
103
|
+
| `add TITLE --type TYPE` | Create an open task |
|
|
104
|
+
| `edit TASK_ID ...` | Change an open or review task |
|
|
105
|
+
| `claim TASK_ID --actor NAME` | Take an advisory claim on an open task |
|
|
106
|
+
| `release TASK_ID` | Drop a claim |
|
|
107
|
+
| `review TASK_ID` | Move an open task into review |
|
|
108
|
+
| `reopen TASK_ID` | Return a review task to open |
|
|
109
|
+
| `complete TASK_ID` | Mark an open or review task completed |
|
|
110
|
+
| `cancel TASK_ID --reason TEXT` | Mark an open or review task cancelled |
|
|
111
|
+
| `archive` | Move older Done tasks into the archive |
|
|
112
|
+
| `migrate` | Upgrade the task data format to 2 |
|
|
113
|
+
| `repos path` | Show the active configuration path |
|
|
114
|
+
| `repos list` | List configured repositories |
|
|
115
|
+
| `repos add [PATH]` | Add a repository entry; PATH defaults to `.` |
|
|
116
|
+
| `repos remove TARGET` | Remove a repository entry by name or path |
|
|
117
|
+
| `install-skill --target TARGET` | Install the bundled `todo` skill |
|
|
118
|
+
| `snippet` | Print the Task Management section for `AGENTS.md` or `CLAUDE.md` |
|
|
119
|
+
|
|
120
|
+
Task IDs look like `T001` and are never reused. Types are `bug`, `chore`,
|
|
121
|
+
`docs`, `feature`, and `ops`. Priorities are `P0`, `P1`, and `P2` (default
|
|
122
|
+
`P2`).
|
|
123
|
+
|
|
124
|
+
`add` requires either `--acceptance` or `--simple`. Repeatable options are
|
|
125
|
+
`--tag` and `--blocked-by`. `claim` records the actor, today's date, and the
|
|
126
|
+
current Git branch unless `--branch` is given. `review` clears that claim and
|
|
127
|
+
records today's date; `reopen` returns the task to open. `complete` and
|
|
128
|
+
`cancel` accept open or review tasks.
|
|
129
|
+
|
|
130
|
+
`init` writes Task Data Format 2. Format 1 files still load for queries;
|
|
131
|
+
mutations require `bot-todo migrate` first.
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
bot-todo add "Fix the lock timeout" --type bug --priority P0 \
|
|
135
|
+
--acceptance "Conflict errors after five seconds, no partial writes" \
|
|
136
|
+
--tag locking --blocked-by T002
|
|
137
|
+
|
|
138
|
+
bot-todo edit T003 --title "Clarify lock timeout" --priority P1 --clear-blockers
|
|
139
|
+
bot-todo cancel T004 --reason "Superseded by T003"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`edit` is a usage error if it requests no change. It also accepts `--simple`,
|
|
143
|
+
`--clear-context`, `--clear-related`, and `--clear-blockers`.
|
|
144
|
+
|
|
145
|
+
### Selecting a repository
|
|
146
|
+
|
|
147
|
+
| Selector | Meaning | Allowed commands |
|
|
148
|
+
| --- | --- | --- |
|
|
149
|
+
| *(none)* | Nearest ancestor `TODO.md`; `init` uses the current directory | Task commands |
|
|
150
|
+
| `--root PATH` | Exact directory | Task commands |
|
|
151
|
+
| `--repo NAME` | One named entry from configuration | Task commands |
|
|
152
|
+
| `--all` | Every configured repository | `list`, `critical`, `actionable` only |
|
|
153
|
+
|
|
154
|
+
`--root`, `--repo`, and `--all` are mutually exclusive. `install-skill` and
|
|
155
|
+
`snippet` accept none of them. `repos` accepts `--config` and rejects the other
|
|
156
|
+
selectors.
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
bot-todo --root ~/Programming/bot_todo list
|
|
160
|
+
bot-todo --repo bot-todo show T001
|
|
161
|
+
bot-todo --all critical
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Configuration
|
|
165
|
+
|
|
166
|
+
`--repo`, `--all`, and `repos` read a TOML file. `--config PATH` overrides
|
|
167
|
+
`BOT_TODO_CONFIG`, which overrides the platform default:
|
|
168
|
+
|
|
169
|
+
- Unix: `${XDG_CONFIG_HOME:-~/.config}/bot-todo/config.toml`
|
|
170
|
+
- Windows: `%APPDATA%\bot-todo\config.toml`
|
|
171
|
+
|
|
172
|
+
```toml
|
|
173
|
+
schema_version = 1
|
|
174
|
+
|
|
175
|
+
[[repositories]]
|
|
176
|
+
name = "bot-todo"
|
|
177
|
+
path = "~/Programming/bot_todo"
|
|
178
|
+
|
|
179
|
+
[[repositories]]
|
|
180
|
+
name = "ledger"
|
|
181
|
+
path = "~/Programming/ledger"
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Names are unique lowercase slugs matching `[a-z0-9][a-z0-9._-]*`. Paths may be
|
|
185
|
+
absolute, start with `~`, or be relative to the configuration file. A missing
|
|
186
|
+
path is valid so `init --repo NAME` can create it.
|
|
187
|
+
|
|
188
|
+
`--all` orders JSON results, `critical`, and `actionable` by priority, then
|
|
189
|
+
configuration order, then file order. Human `--all list` groups tasks by
|
|
190
|
+
Repository Name in collection order, omits repositories with no open tasks,
|
|
191
|
+
and omits the name from task lines.
|
|
192
|
+
|
|
193
|
+
If any configured repository cannot be read, the command prints no task data
|
|
194
|
+
and exits `3`.
|
|
195
|
+
|
|
196
|
+
A missing default config is an empty collection. Local discovery and `--root`
|
|
197
|
+
never load configuration.
|
|
198
|
+
|
|
199
|
+
Manage the collection without editing the file by hand:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
bot-todo repos path
|
|
203
|
+
bot-todo repos list
|
|
204
|
+
cd ~/Programming/new-repo
|
|
205
|
+
bot-todo repos add
|
|
206
|
+
bot-todo repos add --name ledger
|
|
207
|
+
bot-todo repos remove ledger
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
`repos add` stores `~/...` when the path is under home, otherwise an absolute
|
|
211
|
+
path. A missing default file is created on the first add. A missing `--config`
|
|
212
|
+
path is an error. Duplicate names and resolved paths are rejected.
|
|
213
|
+
|
|
214
|
+
## JSON output
|
|
215
|
+
|
|
216
|
+
`--json` is the stable automation interface. Agents should pass it on every
|
|
217
|
+
command that returns data. Humans typing in a terminal can omit it.
|
|
218
|
+
|
|
219
|
+
Success writes one JSON document to stdout:
|
|
220
|
+
|
|
221
|
+
```json
|
|
222
|
+
{
|
|
223
|
+
"schema_version": 2,
|
|
224
|
+
"command": "list",
|
|
225
|
+
"data": {
|
|
226
|
+
"tasks": []
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
JSON task objects include `state` (`open`, `review`, `completed`, or
|
|
232
|
+
`cancelled`), `reviewed_on` (an ISO date while in Review, otherwise `null`),
|
|
233
|
+
and `closed_on`.
|
|
234
|
+
|
|
235
|
+
Expected failure writes nothing to stdout and one error document to stderr:
|
|
236
|
+
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"schema_version": 2,
|
|
240
|
+
"error": {
|
|
241
|
+
"code": "unknown_task",
|
|
242
|
+
"message": "unknown task ID T999"
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Exit statuses: `0` success (including empty queries), `1` operational or data
|
|
248
|
+
failure, `2` usage error, `3` aggregate partial failure.
|
|
249
|
+
|
|
250
|
+
## Agent skill
|
|
251
|
+
|
|
252
|
+
Install the bundled `todo` skill for one agent at a time:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
bot-todo install-skill --target cursor
|
|
256
|
+
bot-todo install-skill --target claude
|
|
257
|
+
bot-todo install-skill --target grok
|
|
258
|
+
bot-todo install-skill --target codex
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Default skill roots:
|
|
262
|
+
|
|
263
|
+
| Target | Skill root | Installed path |
|
|
264
|
+
| --- | --- | --- |
|
|
265
|
+
| `cursor` | `~/.cursor/skills` | `~/.cursor/skills/todo` |
|
|
266
|
+
| `claude` | `~/.claude/skills` | `~/.claude/skills/todo` |
|
|
267
|
+
| `grok` | `~/.grok/skills` | `~/.grok/skills/todo` |
|
|
268
|
+
| `codex` | `~/.agents/skills` | `~/.agents/skills/todo` |
|
|
269
|
+
|
|
270
|
+
`--destination PATH` replaces the skill root, not the final `todo` directory.
|
|
271
|
+
`--dry-run` classifies the action without writing. `--force` replaces a
|
|
272
|
+
conflicting tree after moving it to a `todo.backup-*` sibling.
|
|
273
|
+
|
|
274
|
+
Codex receives `SKILL.md` plus `agents/openai.yaml`. The other targets receive
|
|
275
|
+
`SKILL.md` only. A managed install is marked with `.bot-todo-install.json`.
|
|
276
|
+
Unknown or modified files are a conflict unless `--force` is given.
|
|
277
|
+
|
|
278
|
+
The installer only writes files. It does not reload the agent.
|
|
279
|
+
|
|
280
|
+
## Task files
|
|
281
|
+
|
|
282
|
+
Each Task Repository is a directory with `TODO.md` and `TODO.archive.md`. Treat
|
|
283
|
+
`TODO.md` as the human-readable source of truth, but do not rewrite it by hand
|
|
284
|
+
except to resolve a sequential-ID merge collision.
|
|
285
|
+
|
|
286
|
+
Open tasks live under `P0`, `P1`, and `P2`. Completed and cancelled tasks move
|
|
287
|
+
to Done; the newest 20 stay there, and older closed tasks are appended to the
|
|
288
|
+
archive. A closed task that still blocks an open task stays in Done until
|
|
289
|
+
nothing depends on it. Cancellation does not satisfy dependents.
|
|
290
|
+
|
|
291
|
+
Every mutation takes an exclusive lock (`.bot-todo.lock`), validates before and
|
|
292
|
+
after the write, and replaces the canonical files atomically. Reads take a
|
|
293
|
+
shared lock. Lock acquisition waits up to five seconds, then fails with
|
|
294
|
+
`conflict`.
|
|
295
|
+
|
|
296
|
+
## Development
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
uv sync
|
|
300
|
+
source .venv/bin/activate
|
|
301
|
+
make pytest
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Quality gates used in this repository:
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
uv run ruff check src tests
|
|
308
|
+
uv run mypy src
|
|
309
|
+
make napoleon-gate
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Pass extra pytest arguments with `make pytest ARGS="tests/test_cli.py -q"`.
|
|
313
|
+
|
|
314
|
+
## Further reading
|
|
315
|
+
|
|
316
|
+
- [`CONTEXT.md`](CONTEXT.md) — domain vocabulary
|
|
317
|
+
- [`.scratch/installable-bot-todo/spec.md`](.scratch/installable-bot-todo/spec.md) — architecture and public contract
|
|
318
|
+
- [`docs/adr/`](docs/adr/) — architecture decisions
|
bot_todo-0.2.1/README.md
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# bot-todo
|
|
2
|
+
|
|
3
|
+
`bot-todo` is a command-line tool for a canonical, Git-friendly task backlog.
|
|
4
|
+
Humans and coding agents share one `TODO.md` per repository and mutate it only
|
|
5
|
+
through this CLI.
|
|
6
|
+
|
|
7
|
+
The package also ships a thin `todo` skill that teaches Codex, Claude, Cursor,
|
|
8
|
+
and Grok to call `bot-todo` instead of editing the task files by hand.
|
|
9
|
+
|
|
10
|
+
## Requirements
|
|
11
|
+
|
|
12
|
+
- Python 3.11 or newer
|
|
13
|
+
- [uv](https://docs.astral.sh/uv/) for installation (recommended)
|
|
14
|
+
|
|
15
|
+
The only runtime dependency is `portalocker`, used for per-repository locking.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
uv tool bot-todo
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
That puts `bot-todo` on your `PATH` in an isolated environment. While hacking
|
|
24
|
+
on the CLI itself, keep the checkout live:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
uv tool install --editable .
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
One-shot use without a persistent install:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uvx --from . bot-todo --help
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Confirm the install:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
bot-todo --version
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Quick start
|
|
43
|
+
|
|
44
|
+
From a project directory:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
bot-todo init
|
|
48
|
+
bot-todo add "Write the README" --type docs --priority P1 --acceptance "README covers install and usage"
|
|
49
|
+
bot-todo list
|
|
50
|
+
bot-todo claim T001 --actor glenn
|
|
51
|
+
bot-todo complete T001
|
|
52
|
+
bot-todo validate
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`init` always targets the current directory (or `--root`). Omit `--name` to use
|
|
56
|
+
the repository directory basename as the project heading. Successful human
|
|
57
|
+
`init` prints a copy-paste Task Management section for `AGENTS.md` or
|
|
58
|
+
`CLAUDE.md`; JSON `init` includes that text as `data.snippet`. `bot-todo`
|
|
59
|
+
never writes those instruction files. Other commands without a selector walk
|
|
60
|
+
from the current directory toward the filesystem root and use the nearest
|
|
61
|
+
`TODO.md`.
|
|
62
|
+
|
|
63
|
+
## Usage
|
|
64
|
+
|
|
65
|
+
Global options precede the command:
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
bot-todo [--json] [--config PATH] [--root PATH | --repo NAME | --all] COMMAND ...
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`--help` and `--version` always print human text and succeed, including when
|
|
72
|
+
`--json` is present. Commands never prompt, page, or colorize output.
|
|
73
|
+
|
|
74
|
+
### Commands
|
|
75
|
+
|
|
76
|
+
| Command | Purpose |
|
|
77
|
+
| --- | --- |
|
|
78
|
+
| `init [--name NAME]` | Create `TODO.md` and `TODO.archive.md` |
|
|
79
|
+
| `validate` | Check the canonical files |
|
|
80
|
+
| `list` | List open and review tasks |
|
|
81
|
+
| `show TASK_ID` | Print one task |
|
|
82
|
+
| `critical` | Highest-priority open task (even if blocked or claimed) |
|
|
83
|
+
| `actionable` | First unclaimed open task whose blockers are completed |
|
|
84
|
+
| `add TITLE --type TYPE` | Create an open task |
|
|
85
|
+
| `edit TASK_ID ...` | Change an open or review task |
|
|
86
|
+
| `claim TASK_ID --actor NAME` | Take an advisory claim on an open task |
|
|
87
|
+
| `release TASK_ID` | Drop a claim |
|
|
88
|
+
| `review TASK_ID` | Move an open task into review |
|
|
89
|
+
| `reopen TASK_ID` | Return a review task to open |
|
|
90
|
+
| `complete TASK_ID` | Mark an open or review task completed |
|
|
91
|
+
| `cancel TASK_ID --reason TEXT` | Mark an open or review task cancelled |
|
|
92
|
+
| `archive` | Move older Done tasks into the archive |
|
|
93
|
+
| `migrate` | Upgrade the task data format to 2 |
|
|
94
|
+
| `repos path` | Show the active configuration path |
|
|
95
|
+
| `repos list` | List configured repositories |
|
|
96
|
+
| `repos add [PATH]` | Add a repository entry; PATH defaults to `.` |
|
|
97
|
+
| `repos remove TARGET` | Remove a repository entry by name or path |
|
|
98
|
+
| `install-skill --target TARGET` | Install the bundled `todo` skill |
|
|
99
|
+
| `snippet` | Print the Task Management section for `AGENTS.md` or `CLAUDE.md` |
|
|
100
|
+
|
|
101
|
+
Task IDs look like `T001` and are never reused. Types are `bug`, `chore`,
|
|
102
|
+
`docs`, `feature`, and `ops`. Priorities are `P0`, `P1`, and `P2` (default
|
|
103
|
+
`P2`).
|
|
104
|
+
|
|
105
|
+
`add` requires either `--acceptance` or `--simple`. Repeatable options are
|
|
106
|
+
`--tag` and `--blocked-by`. `claim` records the actor, today's date, and the
|
|
107
|
+
current Git branch unless `--branch` is given. `review` clears that claim and
|
|
108
|
+
records today's date; `reopen` returns the task to open. `complete` and
|
|
109
|
+
`cancel` accept open or review tasks.
|
|
110
|
+
|
|
111
|
+
`init` writes Task Data Format 2. Format 1 files still load for queries;
|
|
112
|
+
mutations require `bot-todo migrate` first.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
bot-todo add "Fix the lock timeout" --type bug --priority P0 \
|
|
116
|
+
--acceptance "Conflict errors after five seconds, no partial writes" \
|
|
117
|
+
--tag locking --blocked-by T002
|
|
118
|
+
|
|
119
|
+
bot-todo edit T003 --title "Clarify lock timeout" --priority P1 --clear-blockers
|
|
120
|
+
bot-todo cancel T004 --reason "Superseded by T003"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`edit` is a usage error if it requests no change. It also accepts `--simple`,
|
|
124
|
+
`--clear-context`, `--clear-related`, and `--clear-blockers`.
|
|
125
|
+
|
|
126
|
+
### Selecting a repository
|
|
127
|
+
|
|
128
|
+
| Selector | Meaning | Allowed commands |
|
|
129
|
+
| --- | --- | --- |
|
|
130
|
+
| *(none)* | Nearest ancestor `TODO.md`; `init` uses the current directory | Task commands |
|
|
131
|
+
| `--root PATH` | Exact directory | Task commands |
|
|
132
|
+
| `--repo NAME` | One named entry from configuration | Task commands |
|
|
133
|
+
| `--all` | Every configured repository | `list`, `critical`, `actionable` only |
|
|
134
|
+
|
|
135
|
+
`--root`, `--repo`, and `--all` are mutually exclusive. `install-skill` and
|
|
136
|
+
`snippet` accept none of them. `repos` accepts `--config` and rejects the other
|
|
137
|
+
selectors.
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
bot-todo --root ~/Programming/bot_todo list
|
|
141
|
+
bot-todo --repo bot-todo show T001
|
|
142
|
+
bot-todo --all critical
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Configuration
|
|
146
|
+
|
|
147
|
+
`--repo`, `--all`, and `repos` read a TOML file. `--config PATH` overrides
|
|
148
|
+
`BOT_TODO_CONFIG`, which overrides the platform default:
|
|
149
|
+
|
|
150
|
+
- Unix: `${XDG_CONFIG_HOME:-~/.config}/bot-todo/config.toml`
|
|
151
|
+
- Windows: `%APPDATA%\bot-todo\config.toml`
|
|
152
|
+
|
|
153
|
+
```toml
|
|
154
|
+
schema_version = 1
|
|
155
|
+
|
|
156
|
+
[[repositories]]
|
|
157
|
+
name = "bot-todo"
|
|
158
|
+
path = "~/Programming/bot_todo"
|
|
159
|
+
|
|
160
|
+
[[repositories]]
|
|
161
|
+
name = "ledger"
|
|
162
|
+
path = "~/Programming/ledger"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Names are unique lowercase slugs matching `[a-z0-9][a-z0-9._-]*`. Paths may be
|
|
166
|
+
absolute, start with `~`, or be relative to the configuration file. A missing
|
|
167
|
+
path is valid so `init --repo NAME` can create it.
|
|
168
|
+
|
|
169
|
+
`--all` orders JSON results, `critical`, and `actionable` by priority, then
|
|
170
|
+
configuration order, then file order. Human `--all list` groups tasks by
|
|
171
|
+
Repository Name in collection order, omits repositories with no open tasks,
|
|
172
|
+
and omits the name from task lines.
|
|
173
|
+
|
|
174
|
+
If any configured repository cannot be read, the command prints no task data
|
|
175
|
+
and exits `3`.
|
|
176
|
+
|
|
177
|
+
A missing default config is an empty collection. Local discovery and `--root`
|
|
178
|
+
never load configuration.
|
|
179
|
+
|
|
180
|
+
Manage the collection without editing the file by hand:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
bot-todo repos path
|
|
184
|
+
bot-todo repos list
|
|
185
|
+
cd ~/Programming/new-repo
|
|
186
|
+
bot-todo repos add
|
|
187
|
+
bot-todo repos add --name ledger
|
|
188
|
+
bot-todo repos remove ledger
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
`repos add` stores `~/...` when the path is under home, otherwise an absolute
|
|
192
|
+
path. A missing default file is created on the first add. A missing `--config`
|
|
193
|
+
path is an error. Duplicate names and resolved paths are rejected.
|
|
194
|
+
|
|
195
|
+
## JSON output
|
|
196
|
+
|
|
197
|
+
`--json` is the stable automation interface. Agents should pass it on every
|
|
198
|
+
command that returns data. Humans typing in a terminal can omit it.
|
|
199
|
+
|
|
200
|
+
Success writes one JSON document to stdout:
|
|
201
|
+
|
|
202
|
+
```json
|
|
203
|
+
{
|
|
204
|
+
"schema_version": 2,
|
|
205
|
+
"command": "list",
|
|
206
|
+
"data": {
|
|
207
|
+
"tasks": []
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
JSON task objects include `state` (`open`, `review`, `completed`, or
|
|
213
|
+
`cancelled`), `reviewed_on` (an ISO date while in Review, otherwise `null`),
|
|
214
|
+
and `closed_on`.
|
|
215
|
+
|
|
216
|
+
Expected failure writes nothing to stdout and one error document to stderr:
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"schema_version": 2,
|
|
221
|
+
"error": {
|
|
222
|
+
"code": "unknown_task",
|
|
223
|
+
"message": "unknown task ID T999"
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Exit statuses: `0` success (including empty queries), `1` operational or data
|
|
229
|
+
failure, `2` usage error, `3` aggregate partial failure.
|
|
230
|
+
|
|
231
|
+
## Agent skill
|
|
232
|
+
|
|
233
|
+
Install the bundled `todo` skill for one agent at a time:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
bot-todo install-skill --target cursor
|
|
237
|
+
bot-todo install-skill --target claude
|
|
238
|
+
bot-todo install-skill --target grok
|
|
239
|
+
bot-todo install-skill --target codex
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Default skill roots:
|
|
243
|
+
|
|
244
|
+
| Target | Skill root | Installed path |
|
|
245
|
+
| --- | --- | --- |
|
|
246
|
+
| `cursor` | `~/.cursor/skills` | `~/.cursor/skills/todo` |
|
|
247
|
+
| `claude` | `~/.claude/skills` | `~/.claude/skills/todo` |
|
|
248
|
+
| `grok` | `~/.grok/skills` | `~/.grok/skills/todo` |
|
|
249
|
+
| `codex` | `~/.agents/skills` | `~/.agents/skills/todo` |
|
|
250
|
+
|
|
251
|
+
`--destination PATH` replaces the skill root, not the final `todo` directory.
|
|
252
|
+
`--dry-run` classifies the action without writing. `--force` replaces a
|
|
253
|
+
conflicting tree after moving it to a `todo.backup-*` sibling.
|
|
254
|
+
|
|
255
|
+
Codex receives `SKILL.md` plus `agents/openai.yaml`. The other targets receive
|
|
256
|
+
`SKILL.md` only. A managed install is marked with `.bot-todo-install.json`.
|
|
257
|
+
Unknown or modified files are a conflict unless `--force` is given.
|
|
258
|
+
|
|
259
|
+
The installer only writes files. It does not reload the agent.
|
|
260
|
+
|
|
261
|
+
## Task files
|
|
262
|
+
|
|
263
|
+
Each Task Repository is a directory with `TODO.md` and `TODO.archive.md`. Treat
|
|
264
|
+
`TODO.md` as the human-readable source of truth, but do not rewrite it by hand
|
|
265
|
+
except to resolve a sequential-ID merge collision.
|
|
266
|
+
|
|
267
|
+
Open tasks live under `P0`, `P1`, and `P2`. Completed and cancelled tasks move
|
|
268
|
+
to Done; the newest 20 stay there, and older closed tasks are appended to the
|
|
269
|
+
archive. A closed task that still blocks an open task stays in Done until
|
|
270
|
+
nothing depends on it. Cancellation does not satisfy dependents.
|
|
271
|
+
|
|
272
|
+
Every mutation takes an exclusive lock (`.bot-todo.lock`), validates before and
|
|
273
|
+
after the write, and replaces the canonical files atomically. Reads take a
|
|
274
|
+
shared lock. Lock acquisition waits up to five seconds, then fails with
|
|
275
|
+
`conflict`.
|
|
276
|
+
|
|
277
|
+
## Development
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
uv sync
|
|
281
|
+
source .venv/bin/activate
|
|
282
|
+
make pytest
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Quality gates used in this repository:
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
uv run ruff check src tests
|
|
289
|
+
uv run mypy src
|
|
290
|
+
make napoleon-gate
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Pass extra pytest arguments with `make pytest ARGS="tests/test_cli.py -q"`.
|
|
294
|
+
|
|
295
|
+
## Further reading
|
|
296
|
+
|
|
297
|
+
- [`CONTEXT.md`](CONTEXT.md) — domain vocabulary
|
|
298
|
+
- [`.scratch/installable-bot-todo/spec.md`](.scratch/installable-bot-todo/spec.md) — architecture and public contract
|
|
299
|
+
- [`docs/adr/`](docs/adr/) — architecture decisions
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build>=0.9,<0.13"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "bot-todo"
|
|
7
|
+
version = "0.2.1"
|
|
8
|
+
description = "Manage canonical repository task files."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
dependencies = ["portalocker>=2.7"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 4 - Beta",
|
|
14
|
+
"Intended Audience :: Developers",
|
|
15
|
+
"Operating System :: OS Independent",
|
|
16
|
+
"Programming Language :: Python",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Programming Language :: Python :: 3.13",
|
|
20
|
+
"Natural Language :: English",
|
|
21
|
+
"Topic :: Utilities",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://github.com/caltechads/bot-todo"
|
|
26
|
+
Repository = "https://github.com/caltechads/bot-todo"
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
bot-todo = "bot_todo.cli:main"
|
|
30
|
+
|
|
31
|
+
[tool.setuptools]
|
|
32
|
+
include-package-data = true
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.packages.find]
|
|
35
|
+
exclude = [
|
|
36
|
+
"*.tests",
|
|
37
|
+
"*.tests.*",
|
|
38
|
+
"tests.*",
|
|
39
|
+
"tests",
|
|
40
|
+
"htmlcov",
|
|
41
|
+
"bin",
|
|
42
|
+
]
|
|
43
|
+
where = ["."]
|
|
44
|
+
|
|
45
|
+
[tool.pytest.ini_options]
|
|
46
|
+
testpaths = ["tests"]
|
|
47
|
+
|
|
48
|
+
[tool.mypy]
|
|
49
|
+
python_version = "3.11"
|
|
50
|
+
strict = true
|
|
51
|
+
|
|
52
|
+
[[tool.mypy.overrides]]
|
|
53
|
+
module = "tests.*"
|
|
54
|
+
disallow_untyped_defs = false
|
|
55
|
+
|
|
56
|
+
[tool.ruff]
|
|
57
|
+
target-version = "py311"
|
|
58
|
+
|
|
59
|
+
[tool.bumpversion]
|
|
60
|
+
current_version = "0.2.1"
|
|
61
|
+
commit = true
|
|
62
|
+
tag = true
|
|
63
|
+
tag_name = "{new_version}"
|
|
64
|
+
parse = '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(-dev(?P<dev>\d+))?'
|
|
65
|
+
serialize = [
|
|
66
|
+
"{major}.{minor}.{patch}-dev{dev}",
|
|
67
|
+
"{major}.{minor}.{patch}",
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
[[tool.bumpversion.files]]
|
|
71
|
+
filename = "Makefile"
|
|
72
|
+
|
|
73
|
+
[[tool.bumpversion.files]]
|
|
74
|
+
filename = "pyproject.toml"
|
|
75
|
+
search = 'version = "{current_version}"'
|
|
76
|
+
replace = 'version = "{new_version}"'
|
|
77
|
+
|
|
78
|
+
[dependency-groups]
|
|
79
|
+
dev = [
|
|
80
|
+
"mypy>=1.11",
|
|
81
|
+
"pytest>=8",
|
|
82
|
+
"ruff>=0.6",
|
|
83
|
+
"build>=1.2.2.post1",
|
|
84
|
+
]
|