commit-ritual

A governed artifact in the stable bundle. Replacing this file on your machine makes your next attestation come back Drifted, naming this path.

DescriptionRun the full commit ritual end to end — verify, stage with hygiene, conventional message + CHANGELOG, never bypass the pre-commit hook, commit as the final step, push only on standing authorization, PR lifecycle through merge. Fires on the ask AND the act: 'commit', 'commit everything', 'land it/this/the commit', 'push it/this', 'ship it', 'wrap and commit', save/finalize changes, open/merge a PR, update the CHANGELOG — and BEFORE running git add/commit/push yourself mid-task (self-trigger; the hand-rolled dance is the failure mode this skill exists to catch). NOT for session state (use a checkpoint/handoff skill).
Arguments[message-or-intent] (e.g. 'feat: add X' or just describe the change)
Tools it may use[Bash, Read, Grep, Glob, Edit]
Installs atskills/commit-ritual/SKILL.md
Mode0644 — never executable
Size10161 bytes
SHA-25633f96133766e926b50874d436c4b03f0f975495cf27068b10ff735cba8e585d7
fetch the raw bytes

The complete file, verbatim

This is the entire SKILL.md, including its YAML frontmatter: byte-identical to what installs, not rendered and not reformatted. Hash exactly what is below and you get the digest above. The table is only a reading aid; this block is the artifact.

---
name: commit-ritual
description: Run the full commit ritual end to end — verify, stage with hygiene, conventional message + CHANGELOG, never bypass the pre-commit hook, commit as the final step, push only on standing authorization, PR lifecycle through merge. Fires on the ask AND the act: 'commit', 'commit everything', 'land it/this/the commit', 'push it/this', 'ship it', 'wrap and commit', save/finalize changes, open/merge a PR, update the CHANGELOG — and BEFORE running git add/commit/push yourself mid-task (self-trigger; the hand-rolled dance is the failure mode this skill exists to catch). NOT for session state (use a checkpoint/handoff skill).
argument-hint: "[message-or-intent]   (e.g. 'feat: add X' or just describe the change)"
allowed-tools: [Bash, Read, Grep, Glob, Edit]
---

# /commit-ritual — the commit ritual

A mistwire skill, ported for general use.

Committing is the single most-repeated task in an agent-assisted codebase, which
makes it the single most-repeated place to be sloppy. This skill encodes the
workflow so that commits are verified, hygienic, conventional, and honestly
reported rather than improvised.

**Commit is the FINAL step — never the first.**

The self-trigger matters as much as the explicit one. The failure mode worth
guarding against is not "the agent refused to commit"; it is the agent
hand-rolling its own `git add -A && git commit -m "fixes"` dance mid-task,
bypassing every check below because nobody said the word "commit" out loud. If
you are about to run `git add`, `git commit`, or `git push` for any reason, you
are in this ritual.

## 0. Pre-flight

- `git status --short` and `git branch --show-current`. If there is nothing to
  commit, say so and stop. Do not manufacture a commit.
- **Branch rule:** never commit straight to the default branch. If you are on
  `main` (or whatever the shared release branch is), branch first — `feat/…`,
  `fix/…`, `docs/…`, `wip/…` — unless the human explicitly directed otherwise.
- **Know exactly what changed.** Read the diff. Do not commit blind. A commit
  message written from memory of what you intended, rather than from the diff of
  what you did, is how untrue changelogs get written.

## 1. Verify before you commit (one-way ratchet)

Run the verification rungs that are relevant to what changed, and report each
one individually: unit → integration → doctests → cross-package → smoke →
security → CHANGELOG.

The rule that earns its keep here: **the narrowest test command is never
sufficient on its own.** In a Rust repo that means `cargo test --lib` alone does
not close the gate; the equivalent in your stack is whichever command runs only
the unit tier. Unit tests pass while the integration boundary — real processes,
real sockets, real serialization — is broken, and that boundary is exactly what
a commit is about to freeze.

**If a rung was not run, say which and why.** A skipped rung reported as silence
is indistinguishable from a pass, and every reader downstream inherits the
error. "NOT-RUN" is a valid, honest result. A silent skip is not.

**Adversarial gate.** For anything non-trivial, do a hostile read of your own
diff before staging: crypto bypass, bounds, replay, time-of-check/time-of-use,
input trust boundaries, rollback and downgrade paths. Skip this only for pure
docs or genuinely trivial changes — and say that you skipped it.

## 2. Stage with hygiene — no bundling

**One logical change per commit.** Stage the specific files for this change
(`git add <paths>`), not `-A` reflexively.

Two categories must ride alone in their own diff. This is not fussiness; each
has a concrete failure it prevents.

- **Version bumps ride alone.** A version bump in the package manifest commits
  by itself. Allowed ride-alongs are the things that are mechanically the same
  change: the lockfile, the CHANGELOG, docs and other markdown, and any
  container or build file that embeds the version string.

  *Why:* bisect clarity. When you are bisecting a regression across a release
  boundary, a version-bump commit that also carries a behavior change gives you
  a bisect result that points at "the release" instead of at the line that broke
  it. A pure bump commit is a clean, meaningless-by-design landmark that bisect
  can step over.

- **Security and gate-policy changes ride alone.** Anything that changes what
  the guardrails do — commit hooks, the hygiene checker itself, policy or
  gate modules, agent-hook definitions — gets its own commit.

  *Why:* review surface. A security-relevant edit buried in a 400-line feature
  diff gets reviewed at the attention level of the feature. On its own diff it
  gets reviewed as a security change, by the right reviewer, with the right
  paranoia. The change that weakens a gate and the change that uses the weakened
  gate must never be the same commit — that is how a bypass ships looking like a
  refactor.

If your staging mixes these categories, **split into multiple commits.** Do not
rationalize the bundle.

## 3. CHANGELOG

Add an entry for the change. Skip only for trivial or non-shipping work — and if
you skip, be able to say why.

Lead with **what** changed and **why**. "Refactored the handler" is not an
entry; "handler no longer retries on 4xx, which was amplifying client errors" is.

## 4. Message

- **Conventional prefix:** `feat:` `fix:` `security:` `refactor:` `docs:`
  `test:` `chore:`.
- **Subject = what. Body = why + blast radius.** No throat-clearing, no
  "this commit makes changes to".
- **Attribute the agent.** End the message with a co-authorship trailer naming
  the assisting agent, in the standard `Co-Authored-By: Name <email>` form your
  project uses. Commit attribution is provenance; an agent-written commit that
  reads as purely human-authored is a small, compounding lie in the history.
- **Author identity is consistent and correct** — the same name and address on
  every commit, product names cased the way the project cases them.
- **Avoid injection-signal vocabulary in the body.** If your project runs a
  content guard over commit messages (a good idea), it scans the message text
  without knowing your intent. Writing a truthful body like "rejects the
  jailbreak attempt in …" will trip it. Reword to describe the mechanism
  ("rejects unauthorized instruction injection in tool output") rather than
  quoting the attack vocabulary. This is a real friction point we have hit more
  than once, not a hypothetical.

## 5. Commit — never bypass the hook

`git commit` runs the pre-commit hygiene hook. **Never `--no-verify`.**

Treat an agent reaching for `--no-verify` as a governance signal in its own
right: the agent has decided its judgment outranks the gate, which is precisely
the capability a compromised or misled agent would exercise first. If the hook
is genuinely wrong, the fix is to change the hook — on its own commit, per §2 —
not to route around it.

If the hook **rejects**, read its output. A well-built hygiene hook names the
mixed files. **Split the commit** per §2 and try again. Do not force it through,
do not disable the hook "just for this one", do not stage a partial workaround.

## 6. Push and PR lifecycle — only on standing authorization

**Establish a standing authorization explicitly, once, with the human**, and
write down its exact edges. A workable shape: direct `git push` to origin and
merging *your own* PRs into the default branch are pre-approved; **force-push,
history rewrites, CI configuration changes, and anything touching secrets still
require explicit confirmation each time.** The point of writing the edges down
is that "I assumed that was covered" stops being available as an excuse.

- **Push** only when the human asked, or when it is the natural close of the
  work they requested.
- **Verify the remote after pushing.** Fetch and compare revisions, or look at
  the hosted view. A clean exit code from `git push` is not proof the remote
  moved — the honest check is that the remote ref now points where you think it
  does.
- **PR open:** body = what + why + blast radius, ending with whatever
  generation/attribution footer your project uses for agent-assisted work.
  Reference issues as full URLs rather than bare `#N` so the link survives being
  read outside its repo. Confirm the CHANGELOG entry actually rode in on the
  branch.
- **PR review request:** name the reviewer by domain. A security-shaped diff
  gets a security review pass *before* it consumes human reviewer attention. For
  a round-close or milestone, prefer several independent isolated review passes
  over one omnibus pass — independent readers find different things; a single
  reader who has already formed a model of the change finds less on the second
  read than a fresh one finds on the first.
- **PR merge:** squash unless the branch history is itself the point.
- **Post-merge:** delete the remote branch unless it is a shared lane, and
  verify the default branch actually moved.

## 7. Report honestly — status precision

**"Pushed", "PR opened", and "merged" are three different states.** Name the one
that is actually true. Never say a PR "landed" or "merged" until the merge call
has returned success — not when you opened it, not when CI went green, not when
you expect it to merge momentarily.

This one has a specific cost: a human who is told something merged stops
tracking it. If it did not merge, nobody is watching it anymore, and the work
sits open for days. Precision here is not pedantry — it is the difference
between a handoff and a dropped item.

If any verification rung was skipped, restate which and why in the final report,
even if you already said it in §1. The commit summary is what gets read.

## Notes

- This skill is the **commit half**. Pair it with a verification-ladder skill
  for §1 — that one runs the tests, this one decides whether the result is
  allowed to become a commit.
- For a mid-feature pause rather than a real commit, prefer a durable session
  checkpoint over a noise commit. "wip: stuff" commits are how a bisectable
  history stops being bisectable.

All skills · Back to the overview