diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000000000000000000000000000000000..7bbcc0641d2e9a1e5b78d06cc3d793a527942577 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,47 @@ +# AGENTS.md + +## What this repo is +- Rust CLI app (`td`) for local task tracking aimed at agent workflows. +- Storage is SQLite in a per-project `.td/tasks.db` database. +- Entry flow is `src/main.rs` → `yatd::run()` (`src/lib.rs`) → `cmd::dispatch()` (`src/cmd/mod.rs`). +- We use jj for version control, not git. DO NOT use Conventional Commits. Do use imperative, Linux kernel-style commits. + +## Essential commands +- Format: `make fmt` +- Lint (warnings are errors): `cargo clippy --quiet -- -D warnings` +- Full local gate: `make ci` (runs fmt + check + test) + +## Implementation details +- Initialization requirement: most commands call `require_root()` and fail unless `.td/` exists somewhere in current dir ancestry (`db::find_root`). Only `init` and `skill` avoid this path. +- DB schema is created in `src/db.rs` (`SCHEMA`): +- Foreign keys are explicitly enabled on each connection (`PRAGMA foreign_keys = ON`). +- Task IDs: + - top-level: generated short IDs (`td-xxxxxx`) via `db::gen_id()` + - subtasks: `.` generated by counting existing children in `create`. + +## Command/module map +- CLI definition and argument shapes: `src/cli.rs` +- Dispatch wiring: `src/cmd/mod.rs` +- Command implementations live in `src/cmd/*.rs` (one module per subcommand, including `skill`). +- Shared DB/domain helpers and structs (`Task`, `TaskDetail`, loaders): `src/db.rs` + +## Testing approach +- Integration-style CLI tests in `tests/cli_*.rs` using: + - `assert_cmd` for invoking `td` + - `tempfile::TempDir` for isolated workdirs + - `predicates` for stdout/stderr assertions +- Typical pattern: + 1. create temp dir + 2. run `td init` + 3. invoke command under test + 4. assert output and/or inspect `.td/tasks.db` directly with `rusqlite` +- When adding/changing behavior, prefer extending these CLI tests rather than only unit tests. + +## Conventions and patterns to preserve +- Error handling uses `anyhow::Result` throughout command functions. +- Keep command functions shaped as `run(...) -> Result<()>` with argument parsing in `cli.rs` and routing in `cmd/mod.rs`. +- JSON structs rely on serde naming alignment (notably `Task.task_type` renamed to `"type"`). Maintain compatibility for import/export and tests. + +## Gotchas +- Running most commands outside an initialized tree yields `not initialized. Run 'td init'` due to upward root search; tests should set `current_dir` to initialized temp dirs. +- `Cargo.toml` uses `rusqlite` with `bundled` feature, so SQLite is vendored; build behavior differs from system-SQLite setups.