diff --git a/AGENTS.md b/AGENTS.md index 7ffdcb9..2b9fde3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,6 +18,111 @@ The work is split into issues in the remote Gitea repo: https://git.achmad.dev/a Tooling: the Gitea MCP tools are available (`gitea-mcp_list_issues`, `gitea-mcp_issue_read`, `gitea-mcp_pull_request_write`, etc.) — use them instead of the CLI when interacting with the remote. +### Worktree workflow + +When the user provides an issue number to work on, the agent works in a dedicated git worktree so multiple agents can run in parallel without file conflicts. The main checkout stays on `main` and is used for integration only. + +**Setup, on receiving an issue number:** + +1. Read the issue with `gitea-mcp_issue_read` (owner `admin`, repo `ledgerr`). If the issue is already closed, stop and tell the user. +2. Derive a branch name from the issue labels. The first matching label wins: + - `bug` → `fix/-` + - `enhancement` or `feature` → `feat/-` + - `chore` → `chore/-` + - `refactor` → `refactor/-` + - `documentation` or `docs` → `docs/-` + - No matching label → `feat/-` (default) + + The slug is lowercase, ASCII, dash-separated, max ~40 chars, taken from the issue title. Strip non-ASCII, punctuation, and stop words. Examples: issue `Add chart to dashboard` labeled `enhancement` → `feat/42-add-chart-to-dashboard`; issue `CSV export broken` labeled `bug` → `fix/43-csv-export-broken`. +3. Create the worktree at a sibling path: `../ledgerr-` (slashes in the branch name become dashes in the path). + + ```bash + git fetch origin + git worktree add ../ledgerr-feat-42-add-chart-to-dashboard -b feat/42-add-chart-to-dashboard origin/main + ``` + +4. `cd` into the worktree and continue all subsequent work there. Run `./gradlew`, tests, and the IDE from inside the worktree — never edit files in the main checkout. + +If the worktree for that issue already exists (resuming work, or another agent on the same issue), `cd` into it and `git pull` — do not create a duplicate. + +**Conventions:** + +- Worktree path: `../ledgerr-` (sibling of the main checkout, not nested inside it) +- Branch name: `/-` where prefix comes from the issue's labels (see mapping above) +- Base branch: `origin/main` (fall back to local `main` if `origin/main` is not fetched yet) +- One worktree per issue. If a single issue needs multiple parallel work streams, split it into sub-issues first. +- The main checkout (`./Ledgerr/`) stays on `main` and is for integration only. + +**When work is complete:** + +1. Wait for explicit user sign-off (the No-implementation rule still applies). +2. On "open a PR" or equivalent: commit, push with `git push -u origin `, then `gitea-mcp_pull_request_write` with base `main` and the body filled in from the PR template below. +3. Do **not** merge and do **not** close the issue — the user does that. +4. Leave the worktree in place until the user asks to clean it up: `git worktree remove ../ledgerr---` (slashes in the branch name become dashes in the path). + +**PR body format** — always use this template, filled in from the actual work: + +~~~markdown +## Summary +- + +## Test plan +- [ ] + +Closes # +~~~ + +- Summary bullets come from the diff, not invented. One bullet per logical change, not per file. +- Test plan mirrors the issue's acceptance criteria, or lists the manual steps exercised. +- Do not add extra sections (Screenshots, Breaking changes, etc.) unless they apply. +- `Closes #` must be the last line — it is what auto-closes the issue on merge. + +**Iteration after review:** + +When the user asks to address review feedback, the user asking to address it is the explicit sign-off for that round — the agent commits and pushes as part of the same step, no extra "commit" / "push" prompt needed for review fixes. + +1. Read the review with `gitea-mcp_pull_request_read` (methods `get_reviews`, `get_review_comments`). +2. Make the requested changes in the worktree. +3. Commit and push with plain `git push` — **do not force-push, squash, amend, or rebase**. Add new commits on top so the review history is preserved. "Address the review" is the one exception to the Git rule against committing/pushing without explicit ask; everything else (drive-by edits, "while you're at it" changes) still needs its own sign-off. +4. Force-push is allowed only if the user explicitly asks for a rebase or squash, and only on the agent's own branch — never on `main` or any shared branch. +5. Update the PR description if the scope of the change shifted (e.g. new dependencies, new migration). Reuse the same template. + +**Scope discipline for review commits:** + +A review commit must contain only changes that directly address the reviewer feedback. "Address the review" is **not** a license to bundle unrelated changes — those need their own explicit sign-off. + +In scope (no extra ask needed beyond the review): +- Fix a typo, rename, or comment the reviewer called out +- Adjust logic for an edge case they raised +- Add a test for the case they identified + +Out of scope (needs its own ask, ideally a separate commit): +- Refactors the reviewer didn't request +- Style/formatting cleanups in unrelated files +- "While we're at it" fixes to other bugs +- Dependency bumps, version changes +- Any change the reviewer didn't ask for + +Rule of thumb: if you can't point to a specific review comment that justifies a line in the diff, it doesn't belong in the review commit. + +**After the PR is merged:** + +The user does the merge (per the rule above). `Closes #` auto-closes the issue. Once the merge is visible on `origin/main`, the worktree and local branch are stale — ask the user before cleaning up, then: + +```bash +git worktree remove ../ledgerr--- +git branch -d +git fetch origin --prune +``` + +The remote branch is deleted automatically by Gitea on merge (or the user can do it from the PR page). + +**Coordination across agents:** + +- `git worktree list` shows all active worktrees. +- Never run two agents in the same worktree — they will race on edits and on KSP/Room/Compose generated code. +- Shared state: `~/.gradle/caches` is shared across worktrees (good — no re-downloads). Each worktree has its own `build/` and project-level `.gradle/` (~200–500 MB each). `rm -rf */build` reclaims space when done. + --- ## Package structure