diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..9553664 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,91 @@ +# AGENTS.md — how changes are made in this repo + +This file is read by AI agents (via opencode) **and** by human developers. Follow it. + +## What this repo is +A **best-practices reference application** — the canonical example the team builds and points to. It +is a small but realistic multi-container app, built and run with **docker-compose**: + +- **api** — the HTTP service (the app's public surface). +- **worker** — background/async job processor. +- **db** — PostgreSQL, the shared datastore. + +Everything is wired so the whole stack comes up with a single `docker compose up`. The point of this +repo is that every part demonstrates how we like things done: clear structure, tests, and CI. + +## Golden rules +- You may edit **any file** in this repo (app code, `docker-compose.yml`, `.gitea/`, tests, CI). +- **NEVER push to `main`, and NEVER merge a pull request.** All work goes on a branch and becomes a + PR that a human (or `@pm` under the `autopilot` label) merges. You do not have merge authority. +- **Never print, exfiltrate, or invent secret values.** Reference secrets via env vars / compose + `environment:`; never paste real secret values into comments, PRs, logs, or code. Config that + *references* a secret is fine; the value is not. +- Keep changes **minimal** and match the conventions already in the file you're editing. +- Do the work on a **branch** — never paste code or diffs into the issue thread. +- Because this is a reference repo, favor **clarity over cleverness**: small services, obvious names, + comments where a newcomer would need them. + +## Project layout (target — grows as features land via issues) +``` +docker-compose.yml # the whole stack: api + worker + db +api/ # the HTTP service (its own Dockerfile) +worker/ # the background worker (its own Dockerfile) +db/ # schema / migrations / init SQL +tests/ # automated tests (unit + integration) +.gitea/workflows/ # CI (build, test) + the ai-agent caller +``` +Add a service by giving it its own top-level directory and a service entry in `docker-compose.yml`. + +## Local run & tests +- **Run the stack:** `docker compose up --build` — api, worker, and db should all come up healthy. +- **Tests:** every change must keep the test suite green. Run tests the way CI does (e.g. via a + `docker compose run` test service or the documented test command) before you consider work done. +- Prefer **integration tests through compose** for cross-service behavior (api ↔ db, worker ↔ db) + over mocking the whole world. +- Give each service a **healthcheck** in compose and depend on it (`depends_on: condition: + service_healthy`) so startup is deterministic. + +## CI +CI lives under `.gitea/workflows/`. It must, at minimum, **build the images and run the tests** on +every PR. Keep CI green — a PR that breaks the build or tests is not ready for review. When adding a +new service, extend CI to build and test it too. + +## Branches & pull requests +You start on branch `ai/issue-` (N = the issue number). + +**Split independent changes into separate PRs** so each is small and reviewable: +``` +git checkout main +git checkout -b ai/issue-- # e.g. ai/issue-7-api-healthcheck +# make just that one change +git add -A && git commit -m "" && git push -u origin HEAD +``` +- Only keep changes together on one branch if they genuinely must ship as a unit. +- Commit and **push incrementally** so progress is visible on the branch. +- **Do not open pull requests yourself** — the automation opens one PR per branch you push. + +## PR description +End your reply with a clean pull-request description wrapped EXACTLY between these markers. +Everything before `BEGIN_PR_DESCRIPTION` is treated as working notes and discarded: + +``` +BEGIN_PR_DESCRIPTION +## Summary +<1-2 sentences: what changed and why> +## Changes + +END_PR_DESCRIPTION +``` +Do not paste full files or large diffs — the review happens in the PR diff. + +## Database changes & migrations +The datastore is Postgres, and `docker compose up` does **not** magically evolve a schema. For schema +changes: +- Put schema/migrations under `db/` (e.g. `db/migrations/NNNN-description.sql`, applied in order). +- Make migrations **idempotent / forward-only** and safe to re-run. +- Never require a manual, undocumented step — a fresh `docker compose up` on an empty volume must + produce a working schema. + +## When unsure +If the task is genuinely unclear or missing details you cannot reasonably assume, make **no** changes +and reply with specific questions instead. \ No newline at end of file