AGENTS.md

 1# AGENTS.md
 2
 3## What this repo is
 4- Rust CLI app (`td`) for local task tracking aimed at agent workflows.
 5- Storage is Loro CRDT in central storage (`~/.local/share/td/projects/<name>/`). Directory bindings map working directories to projects.
 6- Entry flow is `src/main.rs``yatd::run()` (`src/lib.rs`) → `cmd::dispatch()` (`src/cmd/mod.rs`).
 7- We use jj for version control, not git. DO NOT use Conventional Commits. Do use imperative, Linux kernel-style commits. Always check `jj st` before starting. If there are changes in progress, run `jj new -m ...` to create a new working copy describing the pending work. If there are no changes in the working copy, run `jj desc -m ...` to describe the pending work. `jj diff --git` is more understandable.
 8- JSON mode is not for "agent consumers". It's for wiring things together, whether the wirer is human or LLM.
 9- Contributions are through pr.pico.sh. If you're asked to open a PR or contribute or review a PR or similar and you have the skill, read that. If you don't have the skill, somehow fetch the contents of `https://git.secluded.site/agent-skills/blob/main/skills/collaborating-through-pr-pico-sh/SKILL.md?raw=1`. It's markdown, but served as raw plain text, so curl or any other UA will do fine. If you're not contributing/reviewing yet, don't read it yet.
10
11## Essential commands
12- Format: `jj fix` (rustfmt via repo-level jj config)
13- Lint (warnings are errors): `cargo clippy --quiet -- -D warnings`
14- Verify after changes: `make verify` (formats, typechecks, lints, and tests in one pass)
15
16## Implementation details
17- Project resolution: most commands resolve the project via `db::resolve_project_name()` which checks `--project` flag, `TD_PROJECT` env var, or the directory binding in `~/.local/share/td/bindings.json`. Without a resolved project, commands fail with "no project selected". Only `project` and `skill` subcommands avoid this check.
18- Storage is Loro CRDT documents (`base.loro` + incremental changes in `changes/`). There is no SQL database; `src/db.rs` is the Loro document store and task model, not a database layer.
19- Schema versioning lives in `src/migrate.rs` (`CURRENT_SCHEMA_VERSION`); migrations operate on the Loro document structure.
20- Task IDs: all tasks (top-level and subtasks) get ULIDs via `db::gen_id()`, displayed to the user as short `td-XXXXXXX` forms. Subtasks link to their parent via a `parent` field.
21
22## Command/module map
23- CLI definition and argument shapes: `src/cli.rs`
24- Dispatch wiring: `src/cmd/mod.rs`
25- Command implementations live in `src/cmd/*.rs` (one module per subcommand: `create`, `dep`, `doctor`, `done`, `export`, `import`, `label`, `list`, `log`, `next`, `project`, `ready`, `reopen`, `rm`, `search`, `show`, `skill`, `stats`, `sync`, `tidy`, `update`).
26- Loro document store, task model, and domain helpers (`Task`, `TaskId`, `Status`, etc.): `src/db.rs`
27- Schema migrations for the Loro document structure: `src/migrate.rs`
28- Priority/readiness scoring logic: `src/score.rs`
29- Terminal colour helpers: `src/color.rs`
30
31## Testing approach
32- Integration-style CLI tests in `tests/cli_*.rs` using:
33  - `assert_cmd` for invoking `td`
34  - `tempfile::TempDir` for isolated workdirs
35  - `predicates` for stdout/stderr assertions
36- Typical pattern:
37  1. create temp dir
38  2. run `td project init`
39  3. invoke command under test
40  4. assert output and/or inspect central storage in `~/.local/share/td/projects/<name>/` directly
41- When adding/changing behavior, prefer extending these CLI tests rather than only unit tests.
42
43## Conventions and patterns to preserve
44- Error handling uses `anyhow::Result` throughout command functions.
45- Keep command functions shaped as `run(...) -> Result<()>` with argument parsing in `cli.rs` and routing in `cmd/mod.rs`.
46- JSON structs rely on serde naming alignment (notably `Task.task_type` renamed to `"type"`). Maintain compatibility for import/export and tests.
47
48## Gotchas
49- Running commands without a project binding (and without `--project` or `TD_PROJECT`) yields `no project selected`. Tests should set `current_dir` to directories with initialized bindings.
50
51## Contributions
52