| name | commit |
| description | 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. |
| argument-hint | [optional: commit message] [--branch] [--no-push] |
| allowed-tools | ["Bash","Read","Glob","Task"] |
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
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)
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 — 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)
command -v uv || echo "uv: ABSENT"
If uv is present:
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.
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:
git checkout -b <short-descriptive-name>
Never rename or reset an existing branch.
Step 3: Stage
Add specific files — never git add -A:
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 to the summary line.
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:
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)
command -v gh || echo "gh: ABSENT"
If present:
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.