--- name: pr-etiquette description: How to open a complete pull request on overmind-core/overmind — the CI gates, the cross-cutting surfaces a change must carry with it (MCP, blast radius, the docs repo), gh pr edit being broken here, and body conventions. Use when opening a PR, editing a PR title or body, or pushing branch work for review. --- # Pull requests on overmind-core/overmind ## Before you push — what CI will run `.github/workflows/ci.yml` runs four jobs on every non-draft PR. Run the equivalents locally rather than discovering them in CI: | CI job | What it runs | Local equivalent | | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------- | | `lint` | `uv run ruff check .` and `uv run ruff format --check .` | `make lint-backend` | | `frontend` | `bun run check`, `bun run typecheck`, `bun run check:all`, `bun run test` — in parallel, all must pass | same four, from `frontend/` | | `test` | `uv run pytest tests/ -n auto --dist worksteal -q` | `make test` | | `migrations` | `makemigrations --check` on the merge commit plus `scripts/check_migrations.py`; only when `overbae/models/` or `overbae/migrations/` changed | `make check-migrations` | `pre-commit run --files ` before committing substantial work. Note that `mdformat` reflows markdown, so commit its output rather than fighting it. ### SDK changes: bump the bundled release Any change under `overmind/`, including bundled skills or documentation, triggers the SDK version gate. Bump `overmind/pyproject.toml` above the version on the PR's base branch, match `overmind/overmind/__init__.py`, and regenerate `overmind/uv.lock` with `uv lock --project overmind`. Verify the versions agree before pushing. The root `uv.lock` pins the platform's installed SDK dependency; do not change it to an unpublished local release. The merge publishes the bumped version to PyPI (`sdk-publish.yml` runs on every push to `main` that touches `overmind/`). ### Migrations: rebase before you push `make test` runs `--nomigrations`, so a stale branch passes locally and forks the migration graph on main. Main moves fast; a branch that touched a model is usually behind by the time it is ready. Before pushing a model change: 1. `git fetch origin && git rebase origin/main`. 1. If main gained migrations, delete yours and regenerate it: `makemigrations` picks the next number and depends on main's newest leaf. 1. `make check-migrations` — the exact CI check, against `origin/main`. Never resolve a fork with `makemigrations --merge`. A `_merge_` file or a reused number fails the `migrations` job; renumber instead. ## Completeness — the surfaces a PR must carry with it CI cannot catch these. Every one of them has shipped half-done before, so walk the list before opening the PR and say in the body which ones applied. ### 1. MCP MCP is the agent API, with the same completeness bar as the Console. Walk the mcp skill: classify the change (MCP-ready / CLI-guided / frontend-only / out of scope), then tools, resources, prompts, contracts, and tests in `overbae/services/mcp/` and `tests/test_mcp_*.py`. Update the user-facing Overmind skill (`overmind/skills/overmind/`) when the public catalog, prompts, or resources change. A Console-only vertical change that an agent should be able to progress is not complete. The mcp skill itself lives in `.agents/skills/mcp/` and must not be copied into `overmind/skills/`. ### 2. Cross-vertical blast radius Ask what else reads what you changed, and check each one that does: - Celery routing in `CELERY_TASK_ROUTES`, `make worker`, and docker-compose — `tests/test_celery_topology.py` enforces the three agreeing - `manage.py seed_demo` — new tables and states must seed, and must stay terminal (seed-demo-data skill) - the generated OpenAPI client (api-endpoints skill) - `AGENTS.md` and any skill whose statements the change makes untrue ### 3. Docs User-visible behaviour changes ship with a docs change in the sibling repo `overmind-core/docs` (Mintlify, checked out at `../docs`): the relevant `.mdx` page, plus `docs.json` if the navigation moves. Open that PR alongside this one and link the two. A platform PR that changes what a user sees is not complete while the docs still describe the old behaviour. ## Creating `gh pr create --body-file ` works normally. Write the body to a temp file in the scratchpad, never inline via `--body` (quoting breaks on long bodies). Fill in `.github/PULL_REQUEST_TEMPLATE.md` — the Verification section takes the commands you actually ran, not the ones you would run. ## Editing title/body — gh pr edit is BROKEN `gh pr edit --title/--body-file` aborts on this repo with a Projects-classic GraphQL deprecation error (`repository.pullRequest.projectCards`) **and exits looking like it worked**. The PR is left unchanged. Use REST instead: ```bash python3 -c "import json;print(json.dumps({'title':'','body':open('pr.md').read()}))" > pr.json gh api -X PATCH repos/overmind-core/overmind/pulls/<n> --input pr.json --jq .title ``` Always re-read the PR afterwards (`gh pr view <n>`) to confirm the edit landed. ## Conventions - Never push directly to `main`; land work via a PR from a feature branch. A hook blocks the push. - Verify the actual current branch with `git status -sb` before pushing — the session-start banner can be stale. - Commit messages: short subject + at most one body line. No co-author trailers. - For fix-sweep PRs, a before/after table in the body is the house style (see PR #458/#460 for the shape). - If the change makes `AGENTS.md` or a skill wrong, fix it in the same PR. There is one copy of each rule.