diff --git a/.gitignore b/.gitignore index 639e1fa..01b5136 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ .obsidian/ .trash/ +# AGENTS.md is tracked in THIS repo even though ~/.gitignore_global excludes it +!AGENTS.md + # === Rust / Cargo === /target/ debug/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..6bc0e56 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,81 @@ +# AGENTS.md — viexp + +**viexp** is a terminal file manager for Linux written in Rust — a ranger-inspired successor +(async I/O, native image previews, script-first extension model). It is also a **guided +learning project**: the owner is learning Rust from scratch and practicing technical English, +one 20-hour sprint at a time (Josh Kaufman's "First 20 Hours"). License: GPL-3.0-or-later. +Chat with the owner happens in Russian; everything that lands in the repo is English. + +## Repo state: docs only, no Rust code yet + +- This is the planning stage of viexp (a Rust terminal file manager). There is **no `Cargo.toml`** — + cargo commands will fail. Bootstrapping the cargo skeleton is itself the first task + (`docs/tasks/0001`, Gitea issue #1), per Sprint 0 in `docs/roadmap.md`. +- The repo doubles as an Obsidian vault: all project knowledge lives in `docs/` (tracked in git); + `.obsidian/` itself is gitignored. `docs/index.md` is the vault map. +- Detailed workflow docs live in `docs/workflows/` (research, Gitea, English) — read them before + changing vault or issue structure. + +## Language is a hard constraint + +- Everything user-visible — vault notes, issues, commit messages, later code comments — is + **English on purpose** (the project is an English-immersion environment). Never translate + existing English docs or write new ones in Russian. +- Commits: Conventional Commits in English, e.g. `feat(preview): add kitty graphics support`. + +## Vault conventions (docs/) + +- Note filenames: kebab-case English. Frontmatter `type` and `status` are **required** (filtering + depends on them); build new notes from the templates in `TMP/` and keep headings stable per + note type (Obsidian folding assumes identical structure). +- Task statuses: `todo | in-progress | blocked | review | done | cancelled`; priorities `P0–P3`. +- Traceability rule: every `decisions/` ADR must link at least one `research/` note; every + `tasks/` note links a decision or the roadmap. +- Task notes mirror Gitea issues — store the issue number in the task's `gitea-issue` frontmatter + property (see `docs/tasks/0001` for the pattern). + +## Gitea (git.v-port.ru/vaskes/viexp) + +- CLI: `tea` (logged in as `vaskes`). Scripts in `scripts/` read the API token from + `~/.config/tea/config.yml` — never hardcode tokens; `.env`/`*.token` are gitignored. +- **Gitea 1.26.2 quirk: the issues API accepts labels by ID, not by name.** Map names → IDs first + (`scripts/gitea-issues.sh` does this). +- The project board (kanban) has **no API** on this instance — manage it only via the web UI. + Board "Viexp": columns `Backlog → To Do → In Progress → Done`; the active sprint's issues + live in **To Do**, next sprint's in **Backlog**. +- `scripts/gitea-bootstrap.sh` (labels + sprint milestones + seed issues; calls + `gitea-issues.sh`) is re-runnable: existing labels/milestones/issues are detected and reused. +- Milestones = sprints (`Sprint 0 — Setup & deconstruction` …); labels: `type/bug|feature|docs| + research|chore|spike`, `priority/P0–P3`, `lang/english`. + +## Git & verification + +- Single long-lived branch `main`; work in branches named `sprint-N/slug` or `feat/slug`, + squash-merged into `main`. One issue = one demoable outcome. +- Planned CI is a Sprint 0 deliverable and **does not exist yet** (no `.gitea/workflows/`). Once + Rust code lands, CI and the verification order are: + `cargo fmt --check && cargo clippy -- -D warnings && cargo test`. +- Roadmap rule that binds agents too: never leave the repo in a broken state — small commits, + one drill/slice per commit. + +## Rust conventions (apply from Sprint 0 onward) + +- No `unwrap()`/`expect()` outside tests; `thiserror` for domain errors, `anyhow` at the + `main` boundary; prefer `?` with context over match-heavy plumbing. +- **This is a learning codebase**: choose the simplest readable solution over clever idioms. + When introducing a new concept (borrowing, traits, async), explain it briefly — in the PR + description or a `docs/learning/` note. +- Comments explain *why* (constraints), never narrate *what*. + +## Working a sprint session (assistant role) + +1. Start by reading the current sprint note (`docs/sprints/sprint-NN-*.md`) and the latest + DevLog entry; continue from where they point, not from scratch. +2. Pick the next open issue from the sprint's milestone; keep the board column in sync. +3. One drill (20–30 min) ≈ one commit; get each diff reviewed quickly — the review is the + feedback loop the whole method depends on. +4. In code review: point at concrete lines, translate the compiler's complaint into plain + words (Russian in chat, English in artifacts), and for recurring error classes add a + self-correction cue to the ErrorJournal (`TMP/ErrorJournal.md` pattern). +5. Frustration rule: stuck >20 minutes on one error → shrink the drill instead of grinding. +6. Do not commit or push unless the owner asks. Do not close issues without a demoable result.