diff --git a/AGENTS.md b/AGENTS.md index daf86b0c88d65f7c78ef711cc17fde8b47002fbb..e96c7aee2ea8088b1a310051450875957ca68f9a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,158 +6,152 @@ SPDX-License-Identifier: CC0-1.0 # AGENTS.md -This file provides guidance to AI coding agents when working with code in this repository. +Guidance for AI coding agents working in this repository. Document only reflects what exists in code/docs. -## Development Commands +## Project Type -This project uses `just` for task automation. All commands should be run from the repository root. +- Language: Go +- CLI: Cobra executed via charmbracelet/fang +- Module path: `git.secluded.site/np` +- Binary name: `np` -### Essential Commands +## Development Commands (justfile) -- **Format code**: `just fmt` - Uses gofumpt (not standard go fmt) -- **Lint**: `just lint` - Uses golangci-lint -- **Static analysis**: `just staticcheck` - Uses staticcheck -- **Run tests**: `just test` - Runs all tests with verbose output -- **Vulnerability scan**: `just vuln` - Uses govulncheck -- **License compliance**: `just reuse` - Checks REUSE compliance -- **Full check**: `just` (default) - Runs all checks above in sequence -- **Build binary**: `just build` - Produces `np` binary -- **Run without building**: `just run ` - Runs with ldflags +- Format: `just fmt` (installs and runs gofumpt) +- Lint: `just lint` (golangci-lint) +- Static analysis: `just staticcheck` +- Tests: `just test` (go test -v ./...) +- Vulnerabilities: `just vuln` (govulncheck) +- License compliance: `just reuse` (REUSE) +- Build: `just build` (produces `./np`, injects version via ldflags) +- Run: `just run -- ` (runs with ldflags) +- Docs: `just docs` (generates CLI docs via internal/tools/docgen) +- Pack: `just pack` (UPX compresses `np`) +- Clean: `just clean` / `just clean-all` +- Full check: `just` (default target runs fmt, lint, staticcheck, test, vuln, reuse) -### Running Single Tests +Single test: ```bash go test -v -run TestName ./path/to/package ``` -## Project Purpose & Architecture +## Repository Layout -**nasin pali** (installed as `np`) is a CLI tool that guides LLM coding agents through structured task planning workflows. It's designed to encourage planning before code changes, reducing context waste and preventing tasks from being silently dropped. +- `main.go`: wires fang.Execute(RootCmd) and sets version from build info +- `cmd/`: Cobra commands + - Root and top-level: `a` (archive), `m` (monitor/TUI stub), `p` (plan printout stub), `r` (resume), `s` (start) + - `cmd/g/`: goal command group; `g` (show stub), `g s` (set goal stub with -t/-d) + - `cmd/t/`: task command group; `t` (list stub with status filter flag), `t a` (add stub), `t u` (update stub) +- `internal/`: + - `db/`: Badger wrapper: options, tx helpers, key builders, path hashing + - `goal/`: goal document + store + - `task/`: task types + store (status index, deterministic IDs) + - `event/`: event types + store + payload builders + - `timeutil/`: clocks and UTC helpers + - `testutil/`: temp DB and test clocks + - `tools/docgen/`: CLI doc generator +- `docs/`: additional design docs (e.g., `Potential schema.md`) -### Core Design Principles +## CLI Commands (current state) -1. **Working-directory scoping**: One active session per directory. Use git worktrees for parallel sessions. -2. **Token efficiency**: Uses single unicode symbols for task status (☐ ⟳ ☑ ☒ ⊗) instead of verbose markdown checkboxes or words. -3. **Immediate feedback**: Commands that modify state output the full changed plan immediately, avoiding extra commands like `git status` after every change. -4. **Event tracking**: All LLM-oriented commands are tracked with reasons in a Badger database at `$XDG_CONFIG_HOME/nasin-pali/`. - -### Command Structure - -Commands are organized using Cobra with subcommands in subdirectories: - -- **Root commands** (`cmd/*.go`): Session lifecycle (s, a, p, r) -- **Goal commands** (`cmd/g/*.go`): `np g` and subcommands for goal management -- **Task commands** (`cmd/t/*.go`): `np t` and subcommands for task management - -Each command is a separate file. Subcommands are in their own package/directory. - -### Command Reference +Commands exist and are registered, but most are stubs that print placeholder output: ```bash -# Session management -np s # Start new session -np a # Archive current session -np p # Check plan (goal + tasks) -np r # Resume interrupted session - -# Goal management -np g # View current goal -np g s -t "title" -d "description" # Set goal - -# Task management -np t # View all tasks -np t -s pending # Filter by status (pending, in_progress, completed, all) -np t a -t "title1" -d "desc1" \ # Add tasks (repeatable flags) - -t "title2" -d "desc2" -np t u -i task-id -s status # Update task status +np s # start session (stub) +np a # archive session (stub) +np p # print plan (stub) +np r # resume session (stub) +np m # monitor TUI (stub) +np g # goal (stub); np g s -t -d flags defined +np t # tasks (stub); -s status flag defined; t a/u files exist as stubs ``` -### Multi-line Input Pattern - -For multi-line descriptions/bodies, use heredoc syntax: - -```bash -np g s -t "Title" -d "$(cat <<'EOF' -Multi-line -- Description -- Here -EOF -)" -``` - -### Task Status Values - -- `pending` → ☐ -- `in_progress` → ⟳ -- `completed` → ☑ -- `failed` → ☒ -- `cancelled` → ⊗ - -Only failed and cancelled icons appear in legend when those statuses exist in the task list. - -### Output Format for LLMs - -Commands produce token-efficient output: - -``` -Goal Title - -Legend: ☐ pending ⟳ in progress ☑ completed -☑ Completed task [a1b2c3d4] - Task description with context -⟳ Current work [e5f6g7h8] - More description -☐ Pending task [i9j0k1l2] - References: main.go, cmd/root.go -``` - -## Code Style & Conventions - -### Go-Specific - -- **Formatting**: Use `gofumpt`, not standard `go fmt` -- **Error handling**: Follow idiomatic Go patterns visible in existing code -- **CLI framework**: Uses Cobra + Fang (charmbracelet/fang wraps Cobra execution) -- **Module path**: `git.secluded.site/np` - -### Adding New Commands - -1. Create file in appropriate directory (`cmd/` for root commands, `cmd/g/` or `cmd/t/` for subcommands) -2. Define cobra.Command with Use, Short, Long, and Run -3. Register in init() or parent command -4. Add flags using cobra's flag methods -5. Mark required flags explicitly -6. Stub implementation should print a clear message indicating it's a stub - -Example stub pattern: -```go -fmt.Println("[STUB] What this command will do") -``` - -### License Compliance - -All files must include SPDX license headers. Check with `just reuse`. All source files use AGPLv3 and all documentation, configuration, task runner config, etc. is CC0-1.0. - -``` -SPDX-FileCopyrightText: Amolith -SPDX-License-Identifier: AGPL-3.0-or-later -``` +Fang is used for execution/versioning; Cobra provides the command tree. + +## Data Layer and Storage + +Implemented under `internal/db`, `internal/goal`, `internal/task`, `internal/event`. + +- Database options (internal/db/options.go) + - Default path: `os.UserConfigDir()/nasin-pali` + - Retries: `MaxTxnRetries` (default 5) with exponential `ConflictBackoff` (default 10ms) + - `SyncWrites` defaults to true when not ReadOnly + - No-op logger by default; Badger logger bridged via adapter +- Database helpers (internal/db/db.go) + - `View(ctx, fn)` for read-only; `Update(ctx, fn)` for read-write with retries + - Txn helpers: `Get`, `Set`, `Delete`, `GetJSON`, `SetJSON`, `Exists`, `Iterate`, `IncrementUint64` + - Errors normalized: `ErrClosed`, `ErrReadOnly`, `ErrKeyNotFound`, `ErrTxnAborted` + - Iterator uses prefix scans; `IterateOptions{Prefix, Reverse, PrefetchValues}` + - Value log size set to 64 MiB when writable +- Keyspace builders (internal/db/keys.go) + - Meta/schema: `meta/schema_version` + - Per-directory: `dir/{dir_hash}/active`, `dir/{dir_hash}/archived/{ts_hex}/{sid}` + - Global indexes: `idx/active/{sid}`, `idx/archived/{ts_hex}/{sid}` + - Per-session: `s/{sid}/meta`, `s/{sid}/goal`, `s/{sid}/task/{id}` + - Status index: `s/{sid}/idx/status/{status}/{id}` + - Events: `s/{sid}/meta/evt_seq` (counter), `s/{sid}/evt/{seq_hex}`; prefixes for scans exist +- Path handling (internal/db/path.go) + - `CanonicalizeDir`: abs + EvalSymlinks + Clean + ToSlash; lowercase on Windows + - `DirHash`: blake3-256 of canonical path (hex) + - `ParentWalk`: yields canonical parents up to root +- Encoding helpers (internal/db/encoding.go) + - Big-endian u64 encode/decode; `Uint64Hex` for zero-padded lower-hex + +## Domain Stores + +- Goal (internal/goal) + - Document: `{title, description, updated_at}` (UTC) + - Store: `Get`, `Exists`, `Set`; title is trimmed and required + - Transaction-scoped `TxnStore` mirrors operations +- Task (internal/task) + - Status: `pending`, `in_progress`, `completed`, `failed`, `cancelled` with validation helpers + - Task: `{id, title, description, status, created_at, updated_at, created_seq}` (UTC) + - ID: `GenerateID(sid, title, description)` uses blake3 of normalized (trim + squash spaces) title/description + sid; first 6 hex + - Store: `Create`, `Get`, `Update`, `UpdateStatus`, `Delete`, `List`, `ListByStatus`, `Exists` + - Maintains status membership keys; sorts by `created_seq`, then `created_at`, then `id` +- Event (internal/event) + - Types: `goal_set`, `goal_updated`, `task_added`, `task_updated`, `task_status_changed` + - Record: `{seq, at, type, reason?, cmd, payload}`; `reason` optional; `cmd` required and trimmed + - Store: `Append`, `List` (supports `After` and `Limit`), `LatestSequence` + - Sequence stored as 8-byte big-endian counter at `s/{sid}/meta/evt_seq`; keys use hex-encoded seq + - Payload helpers in `payloads.go` build stable snapshots for events + +All stores accept an optional `timeutil.Clock`; default is a UTC system clock. `timeutil.EnsureUTC` normalizes timestamps. + +## Testing + +- Tests live under `internal/*_test.go` (goal, task, event) +- Helpers: `testutil.OpenDB(t)` opens a temp Badger DB with cleanup; `testutil.SequenceClock` yields deterministic times +- Run: `just test` or `go test -v ./...` +- Example single test pattern: `go test -v -run TestName ./internal/task` + +## Doc Generation + +- Tool: `internal/tools/docgen` (cobra/doc based) +- `just docs` runs two invocations: one tree under `docs/cli/`, and a single-file reference `docs/llm-reference.md` +- Note: the justfile passes `-exclude m` but `docgen` has no `-exclude` flag; adjust the recipe if this causes failures + +## Output Format for LLMs + +- Status icons: ☐ pending, ⟳ in progress, ☑ completed, ☒ failed, ⊗ cancelled (only show failed/cancelled in legend when present) +- Commands that change state should print the full plan immediately (current CLI commands are stubs) + +## Conventions + +- Formatting: gofumpt (not `go fmt`) +- Errors and validation follow idiomatic Go patterns visible in stores +- All source files include SPDX headers; source is AGPL-3.0-or-later; docs/config are CC0-1.0 + +## Gotchas + +- `just docs` may fail due to `-exclude` flag unsupported by docgen +- `db.Options` sets `SyncWrites=true` by default when not read-only (durability over throughput) +- Event sequence counter is raw 8-byte big-endian; do not store decimal strings +- Windows: directory canonicalization lowercases paths; hashes derive from canonicalized form ## Implementation Status -**This project is in early development.** Most commands are stubs that print placeholder output. The README is intentionally aspirational, documenting the intended behavior. When implementing features: - -1. Read the README to understand intended workflow -2. Check cmd files to see current stub state -3. Implement according to design principles above -4. Maintain token-efficient output format -5. Ensure event tracking for state changes (when implemented) - -## Future Features Not Yet Implemented - -- Badger database for event tracking -- Interactive TUI for watching events in real-time -- Actual session storage/retrieval -- Task ID generation and management -- Goal modification commands -- Task modification beyond status updates +- CLI commands exist but are stubs that print placeholders +- Data layer (db, goal, task, event) is implemented with tests; session orchestration and wiring from CLI to stores is not yet implemented +- `docs/Potential schema.md` captures intended end-state for sessions, indexes, and events; use as design context, not as a guarantee