# Commit

> Stage, verify, commit, and push geobr changes. Use ONLY on explicit commit intent — user says "commit", "ship it", "push this", "let's commit this", or prefixes with `/commit`. Do NOT auto-invoke on vague end-of-task phrases ("we're done", "wrap up") — those require explicit confirmation first. Runs the touched-package test gate first; never force-pushes, never skips hooks, never auto-merges.

- Skill: `ipea/commit` (Agent Skill)
- Install (CLI): `npx skillmds@latest add ipea/commit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/ipea/commit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Productivity
- Author: ipea (https://skillmd.com/u/ipea)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/ipea/commit

---


# Commit

Stage changes, run the gate for whichever package was touched, commit, and push.

**Repo facts this skill depends on:** default branch is `master` (not `main`); remote is
`ipea/geobr`; `gh` is **not installed** on the maintainer's machine; `python`/`uv` are **not
installed** either. Nothing here may assume otherwise.

---

## Step 0: Scope

```bash
git status --short
git diff --stat
git log --oneline -5
git branch --show-current
```

Classify every changed path:

| Bucket | Gate |
|---|---|
| `r-package/**` | R gate (Step 1a) |
| `python-package/**` | Python gate (Step 1b) |
| `.claude/**`, `CLAUDE.md`, `MEMORY.md`, `quality_reports/**`, `templates/**` | config — no test gate |
| `.github/**` | CI — read the diff, no local gate |
| `docs/**` | generated by pkgdown — **do not hand-commit** unless the user is deliberately publishing |

If nothing outside the config bucket changed, skip to Step 2 and say so.

## Step 1a: R gate (only if `r-package/` changed)

```bash
Rscript -e 'devtools::document("r-package")' 2>&1 | tail -20
git status --short r-package/man r-package/NAMESPACE
Rscript -e 'devtools::test("r-package")' 2>&1 | tail -40
```

- **Doc drift** — any diff in `man/` or `NAMESPACE` after documenting means the committed generated
  docs were stale. Stage the regenerated files with the commit; mention it.
- **Test failures** — halt. Report the failing output verbatim. The user either fixes them or
  explicitly overrides ("commit anyway").
- **Skips** — report the count. A jump in skips usually means tests opted out rather than passed.

**The R suite needs network — by design.** geobr does not use `skip_if_offline()`, so an outage
produces failures that look like regressions. Before blaming the diff, confirm connectivity:

```powershell
# PowerShell — libcurl ignores the WinINET proxy this machine uses
$env:http_proxy  = "http://cache.ipea.gov.br:3128"
$env:https_proxy = "http://cache.ipea.gov.br:3128"
```

The sandboxed Bash tool has no outbound network at all — run the R gate through PowerShell.
Baseline with the proxy set: **FAIL 0 | WARN 0 | SKIP 1 | PASS 323**. A result matching that
baseline is a pass; a wholesale collapse to `NULL` metadata errors is a network problem, not a
code problem, and must be reported as `INCONCLUSIVE`, never as a failure of the diff.

## Step 1b: Python gate (only if `python-package/` changed)

```bash
command -v uv || echo "uv: ABSENT"
```

**If `uv` is present:**

```bash
cd python-package && uv sync --frozen 2>&1 | tail -10
cd python-package && uv run pytest -n 2 -m "not network" 2>&1 | tail -40
```

**If `uv` is absent** — the expected case — do **not** substitute `pip` or a system interpreter.
Report exactly:

```
Python gate: SKIPPED — no local toolchain (uv absent).
Covered by .github/workflows/Python-CMD-check.yaml on push.
```

Then run the static checks that need no interpreter, and report them as the gate result:

- `pyproject.toml` changed without `uv.lock` → **halt**; CI installs `--frozen` and will fail.
- A new/changed test that touches the network without `@pytest.mark.network`.
- A new public name missing from `geobr/__init__.py`.
- A hardcoded release tag, or a download path built by hand instead of via `_cache.cached_path()`.

For a non-trivial Python diff, spawn the **python-package-reviewer** agent (`Task`) before
committing. On this machine it is the only real review the code will get before CI.

## Step 1c: Parity check (if a public `read_*` signature changed)

If the diff changes an exported reader's arguments on one side only, say so plainly and ask whether
to proceed. A deliberate lag is fine when `NEWS.md` / `CHANGELOG.md` records it; a silent one is not.
See [`../../rules/cross-language-parity.md`](../../rules/cross-language-parity.md).

## Step 2: Branch (only if asked)

Default: **commit on the current branch.** This matches the repo's history, which lands work directly
on `master`.

With `--branch`, or if the user asks for a PR:

```bash
git checkout -b <short-descriptive-name>
```

Never rename or reset an existing branch.

## Step 3: Stage

Add specific files — **never `git add -A`**:

```bash
git add <file1> <file2> ...
```

Never stage: `.claude/settings.local.json`, credentials, `.Rhistory`, `.Rproj.user/`,
`__pycache__/`, `.pytest_cache/`, or anything under `docs/` unless publishing deliberately.

## Step 4: Commit

Use `$ARGUMENTS` as the message if given. Otherwise write one that explains **why**, not just what.
Apply [`../../rules/summary-parity.md`](../../rules/summary-parity.md) to the summary line.

```bash
git commit -m "$(cat <<'EOF'
<message>
EOF
)"
```

If the user overrode a failing gate, record the override and their reason in the message body.

## Step 5: Push

Unless `--no-push`:

```bash
git push origin HEAD
```

For a new branch: `git push -u origin <branch-name>`.

**Never force-push. Never `--no-verify`. Never auto-merge.**

## Step 6: PR (only when asked, and only if `gh` exists)

```bash
command -v gh || echo "gh: ABSENT"
```

If present:

```bash
gh pr create --base master --title "<title>" --body "$(cat <<'EOF'
## Summary
<1-3 bullets>

## Test plan
<what was verified, and what was skipped and why>
EOF
)"
```

If absent, do not attempt to install it. Print the compare URL for the user to open:

```
https://github.com/ipea/geobr/compare/master...<branch>
```

Merging is the maintainer's action, not this skill's.

## Step 7: Report

State: which gate ran, its real result, what was skipped and why, the commit SHA, and the push
target. Never report a skipped gate as a pass.

---

## Important

- **The gate is the test suite.** There is no `quality_score.py` in this repo and no installed
  pre-commit hook — a direct `git commit` bypasses this skill entirely. That gap is known and
  accepted; do not describe this gate as enforcement.
- **Base branch is `master`.**
- **A missing toolchain is a SKIP, never a PASS.**
- **This skill does not merge and does not release.** For a release, run `/r-package-check` or
  `/py-package-check` first.

