From 6afafbf2efea6ff4edbfc3ad7744d422ebde6cc8 Mon Sep 17 00:00:00 2001 From: Amolith Date: Sun, 21 Dec 2025 21:54:56 -0700 Subject: [PATCH] docs: expand AGENTS.md with non-obvious patterns - Complete architecture section with all internal packages - Document API client builder pattern - Add gotchas: enum validation, date parsing, stdin convention, deep links, config key lookups - Update testing section with actual patterns - Document init wizard navigation Assisted-by: Claude Sonnet 4 via Crush --- AGENTS.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 10 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 898a3bb9f6ad9ba7f2f2bf90bd1d18e3f2f25ef6..ebb1b4c2cff729aca5dabe6f1ad0aeec2ba203aa 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -36,18 +36,25 @@ running their respective tasks. main.go → cmd.Execute() entrypoint cmd/ root.go → Root command, registers all subcommands and groups - init.go, ping.go → Top-level commands + init/ → Interactive setup wizard (huh forms, multi-step navigation) + ping.go → Token verification command add.go, done.go, jrnl.go → Shortcuts (delegate to resource commands) - task/ → task add/list/get/update/delete - note/ → note add/list/get/update/delete - person/ → person add/list/get/update/delete/timeline + task/ → task add/list/show/update/delete + note/ → note add/list/show/update/delete + person/ → person add/list/show/update/delete/timeline + area/ → area list/show (read-only) + goal/ → goal list/show (read-only) journal/ → journal add habit/ → habit track internal/ client/ → Lunatask API client factory (uses system keyring) config/ → TOML config at ~/.config/lune/config.toml - ui/ → Lipgloss styles (Success, Warning, Error, Muted, Bold) - validate/ → Input validation (UUID format) + completion/ → Shell completion helpers (config-based + static values) + dateutil/ → Natural language date parsing via go-dateparser + deeplink/ → Parse/build lunatask:// URLs + stats/ → Usage statistics helpers + ui/ → Lipgloss styles (Success, Warning, Error, H1, H2, FormatDate) + validate/ → Input validation (UUID, enums, deep links → UUID) ``` **Command flow**: `fang.Execute()` wraps Cobra with version/commit info and @@ -55,6 +62,10 @@ signal handling. Resource commands live in subpackages (`cmd/task/`); shortcuts in `cmd/` delegate to resource commands by calling their `RunE` directly and copying their flagset. +**API client pattern**: `client.New()` returns a `*lunatask.Client`. Create +operations use builders: `client.NewTask(name).InArea(id).WithStatus(s).Create(ctx)`. +Update operations use separate builders: `client.UpdateTask(id).WithStatus(s).Update(ctx)`. + ## Command patterns **Resource commands** (task, note, person, etc.): @@ -71,8 +82,9 @@ copying their flagset. - Call resource command's `RunE` directly **Shell completions** registered inline via `RegisterFlagCompletionFunc`; -see `cmd/task/add.go:43-56` for examples. Config-based completions load -from `config.Load()`. +see `cmd/task/add.go:56-63` for examples. Use `completion.Areas`, `completion.Goals`, +etc. for config-based completions, or `completion.Static("val1", "val2")` for +fixed options. ## Core dependencies @@ -99,6 +111,33 @@ Reference docs via context7 or doc-agent when unsure: ## Gotchas +### Enum validation + +Use `validate.TaskStatus()`, `validate.Motivation()`, `validate.RelationshipStrength()` +to parse and validate string inputs to `lunatask.*` types. These normalize +case and return typed values or wrapped errors (`ErrInvalidStatus`, etc.). + +### Date parsing + +`dateutil.Parse()` accepts natural language ("yesterday", "2 days ago", "March 5") +and ISO dates ("2024-01-15"). Empty input returns today's date. Returns +`lunatask.Date` type. + +### Stdin convention + +Many commands accept `-` as an argument or flag value to read from stdin: +- `task add -` reads task name from first stdin line +- `--note -` reads entire stdin as the note content + +The implementations differ: name uses `bufio.Scanner` (single line), note uses +`os.ReadFile("/dev/stdin")` (all content). + +### Deep link support + +Commands accepting IDs also accept `lunatask://` deep links. Use +`validate.Reference()` to normalize either format to a UUID. The `deeplink` +package handles parsing and building these URLs. + ### Linter exclusions for cmd/ The `.golangci.yaml` disables several linters for `cmd/`: @@ -113,6 +152,16 @@ The `.golangci.yaml` disables several linters for `cmd/`: These patterns are intentional. +### Config key lookups + +Areas, goals, notebooks, and habits are stored with user-defined `key` fields +(short aliases like "work", "personal"). Commands accept keys, not UUIDs. +Lookup methods: `cfg.AreaByKey()`, `area.GoalByKey()`, `cfg.NotebookByKey()`, +`cfg.HabitByKey()`. There are also `*ByID()` methods for reverse lookups. + +Goals require their parent area context—use `cfg.FindGoalsByKey()` to find goals +across all areas, which returns `[]GoalMatch{Goal, Area}` pairs. + ### Access token Read from system keyring via `internal/client.New()`. No interactive @@ -126,5 +175,13 @@ colors. ## Testing -Currently stub implementations with `// TODO` markers. When implementing, use -`cmd.SetOut()` / `cmd.SetErr()` to capture output. +Table-driven tests with `t.Parallel()`. Use `_test` package suffix for black-box +testing (see `deeplink_test.go`). When testing commands, use `cmd.SetOut()` / +`cmd.SetErr()` to capture output. + +### Init wizard + +The `cmd/init/` package implements a multi-step wizard using `huh` forms. +Navigation uses `wizardNav` (navNext/navBack/navQuit) with sentinel errors +(`errQuit`, `errReset`). Steps are functions returning navigation direction; +the wizard loops through them allowing back/forward navigation.