Agent Harness · Reference sheet

The commit skill

Eight steps the agent runs before every commit, each tied to the incident it prevents. Print it and tick it while you test your own skill. These are one working set of steps; keep the ones your team needs and add your own.

The 8 steps

Run in order; any failure means stop and report, not work around. Tick them while you test the skill on a real slice.

  • 1. See what is staged
    git status --short then git diff --cached --stat. Nothing staged: list changed files, propose the slice, ask before git add. Never git add -A or git add .
    Prevents: one real session put 1,089 files in one "Initial commit"; another put the whole project, 60 files, in one commit
  • 2. Refuse build output and local files
    git diff --cached --name-only | grep -E '(^|/)(bin|obj|tmp)/|\.db$|(^|/)\.env$'. Any match: stop, list, propose git restore --staged and a .gitignore entry
    Prevents: that 1,089-file commit was mostly junk: a vendored tmp/ toolchain and obj/ build output
    Backed by: .githooks/pre-commit step 1
  • 3. Refuse secrets
    Run both: the pattern check git diff --cached | grep -nEi '(key|secret|password|pwd|token)["' ]*[:=] *["'][^"' ]{8,}' and gitleaks git --pre-commit --staged --redact (if installed). gitleaks misses readable config secrets; the pattern catches them. On a hit: stop, show file and line redacted, point to an env var and .env.example
    Prevents: a real session that committed "Jwt":{"Key":"SuperSecretAuthenticationKeyForFulfillmentService2026!"} in appsettings.json. gitleaks 8.23.3 and 8.30.1 both did not flag this low-entropy value (measured 2026-09-30); the pattern check does
    Backed by: .githooks/pre-commit step 3
  • 4. Check identity
    git config user.email must be your work address (@yourcompany.com; change it to your own domain). If not, ask the human to fix it; never set it yourself
    Prevents: commits authored under a personal address
    Backed by: .githooks/pre-commit step 2; deny git config user.email *@*
  • 5. Draft the message from the diff, not from memory
    git diff --cached then type(scope): summary, imperative, 72 characters or fewer. No AI co-author or "Generated with" line. More than one slice in the diff: propose splitting
    Prevents: "Update the changes"; "First commit"; a 60-file commit described as "add tests"; AI co-author trailers on most of a session's commits
    Backed by: .githooks/commit-msg; attribution setting
  • 6. Show and wait
    Print the staged file list and the full message, ask "Commit with this message?" and wait for an explicit yes. If the human edits it, use their version verbatim
    Prevents: one real session where the agent committed unasked; the developer: "i did not want u to commit anything until I say so"
    Backed by: ask on Bash(git commit *)
  • 7. Commit
    git commit -m "<subject>" -m "<body>" then report the short hash. One slice, one commit, made when the slice is green
    Prevents: 56 commits sharing one timestamp, a history replayed after the work, so it no longer shows the order of work (lesson 10)
  • 8. Never push
    Never push, never amend a pushed commit, never rebase. Pushing is the human's job
    Prevents: a session where the developer asked the agent to force-push and it ran it; only the git server's branch protection refused. Another developer committed a clicked-together allow list holding git rebase *
    Backed by: deny git push --force*; the destructive guard

Skill and guard, togetherThe skill is the agent's checklist; .githooks/pre-commit and commit-msg run the same checks when anyone commits. The skill keeps the agent from trying; the hooks stop it if it tries.

Conventional Commit types

TypeUse for
featA new capability (an endpoint, a rule)
fixA bug fix
docsDocs only, including docs(plan): ...
testTests only
refactorRestructure, no behaviour change
perfFaster, same behaviour
buildBuild system, packages, Directory.Build.props
ciCI configuration
choreHousekeeping, harness files: chore(harness): ...
styleFormatting only
revertUndo an earlier commit, as a new commit

Subject: type(scope): summary, imperative, at most 72 characters after the colon. Scope is the area: products, orders, harness, plan. Body (optional): why, in 1-3 lines, and any 1-3-1 decision the human made. The commit-msg hook enforces this with a shell regex; Merge and Revert subjects pass.

Where it lives

  • .agents/skills/commit/SKILL.md: the tool-neutral home (Codex and Antigravity read it).
  • .claude/skills/commit: a per-skill symlink to it, for Claude Code.
  • Invoke with /commit (Claude Code, Antigravity) or $commit (Codex), or let the description trigger it.
  • In Claude Code a personal skill beats a project skill with the same name, so check ~/.claude/skills/ for a clashing commit.

Good and bad messages

Bad (from real sessions)WhyGood
Initial commit (1,089 files)Says nothing; carries junkchore: scaffold solution with .gitignore for bin/, obj/ and tmp/
First commit (the entire API)Nobody can review, bisect or revert a slicefeat(products): CRUD endpoints with SKU uniqueness
Update the changesWhich changes?feat(orders): atomic placement with stock check
Add ppt and pdfNot a change to the productdocs: README, AI process log
add tests (60 files, the whole project)Describes a sliver of the diff; misleadingOne commit per slice, each message describing that slice
One commit holding the plan and the codeGit cannot show the plan came firstdocs(plan): low-stock endpoint, alone, first
Appendix: the SKILL.md, verbatim
reference-solution/.agents/skills/commit/SKILL.md
---
name: commit
description: Commit the current slice. Use whenever a slice has passed the quality gate and review and the work should be committed, or when the user says "commit". Drafts a Conventional Commit message from the staged diff, refuses secrets and build output, checks your work identity, and waits for human approval. Never pushes.
---

# Commit

Follow every step in order. If any check fails, stop and report; do not work around it.

1. **See what is staged.**
   `git status --short` and `git diff --cached --stat`.
   If nothing is staged, list the changed files, propose which belong to this slice, and ask the human
   before running `git add`. Never use `git add -A` or `git add .`.

2. **Refuse build output and local files.**
   `git diff --cached --name-only | grep -E '(^|/)(bin|obj|tmp)/|\.db$|(^|/)\.env$'`
   If anything matches: stop, list the paths, and propose `git restore --staged <path>` plus a `.gitignore` entry.

3. **Refuse secrets.**
   Run BOTH checks. gitleaks finds known key formats but misses readable config secrets (a JWT signing key
   spelled as a plain English phrase, for example), and the pattern catches those:
   - `git diff --cached -- . ':(exclude)ai-session' | grep -nEi '(key|secret|password|pwd|token)["'\'' ]*[:=] *["'\''][^"'\'' ]{8,}'`
   - `gitleaks git --pre-commit --staged --redact` (if installed; it also scans `ai-session/` transcripts)
   On any finding: stop, show the file and line (redacted), and explain where the value should live
   (environment variable, documented in `.env.example`). Continue only if the human confirms it is not a secret.

4. **Check identity.**
   `git config user.email` must be your work address (`@yourcompany.com`; change this to your own domain).
   If not, stop and ask the human to run `git config user.email <their work email>`. Do not set it yourself.

5. **Draft the message from the diff, not from memory.**
   Read `git diff --cached`. Write:
   - Subject: `type(scope): summary`, imperative, 72 characters or fewer.
     Types: feat, fix, docs, test, refactor, perf, build, ci, chore, style, revert.
     Scope: the area (products, orders, harness, plan …).
   - Body (optional): why, in 1–3 lines; mention any 1-3-1 decision the human made.
   - **No** `Co-Authored-By`, "Generated with" or any other AI attribution line.
   If the diff holds more than one slice, say so and propose splitting it instead of writing one message.

6. **Show and wait.** Print the staged file list and the full message. Ask: "Commit with this message?"
   Wait for an explicit yes. If the human edits the message, use their version verbatim.

7. **Commit.** `git commit -m "<subject>" -m "<body>"`. Report the short hash.

8. **Never push**, never amend a pushed commit, never rebase. Pushing is the human's job.

Sources: Claude Code skills · Codex skills · Antigravity skills · Conventional Commits 1.0.0 · gitleaks (v8.30.1, git --pre-commit --staged). Last verified 2026-09-30.


Taught in: Lesson 5: Skills · Lesson 7: Guards · Lesson 10: Evidence and honesty
Other sheets: AGENTS.md structure · The four guards · 1-3-1 · Glossary · Tool equivalents