Backend Atomic Commit Skill
When to Use This Skill
Use this Skill in backend/Django repos (especially the Diversio monolith backend) when you want:
/backend-atomic-commit:pre-commit– to actively fix the current code
(formatting, imports, type hints, logging, etc.) so that it matches:
- Local
AGENTS.md/CLAUDE.mdrules. .pre-commit-config.yamlexpectations..security/diff helpers (ruff and local imports).- Monty’s backend taste.
/backend-atomic-commit:atomic-commit– to run the same checks plus:- Enforce that the staged changes are atomic (one coherent change).
- Ensure all quality gates are green (no shortcuts).
- Propose a strict, ticket-prefixed commit message without any Claude or
AI signatures.
Example Prompts
- “Run
/backend-atomic-commit:pre-commiton this repo and actively fix all
files in git status so they obey backend AGENTS.md, .pre-commit-config.yaml, .security/* helpers, and Monty’s taste (no local imports, strong typing, structured logging). Then summarize what you changed and what’s still [BLOCKING].”
- “Use
/backend-atomic-commit:atomic-committo prepare an atomic commit for
the staged changes in backend/. Enforce all pre-commit hooks and .security scripts, run Ruff, ty, Django checks, and relevant pytest subsets, then propose a ticket-prefixed commit message with no AI signature and clearly mark any [BLOCKING] issues.”
- “Treat my current backend changes as one logical bugfix and run
/backend-atomic-commit:pre-commit in a strict mode: eliminate local imports, fix type hints (no Any, no string-based annotations), clean up debug statements, and ensure Ruff, .security/local_imports_pr_diff.sh, ty, and Django checks are happy."
- “Before I commit these
optimo_*changes, run
/backend-atomic-commit:atomic-commit --auto to:
- enforce structured logging with
TypedDictpayloads, - ensure no PII in logs,
- verify tests and
.security/*scripts,
and then tell me whether the commit is ready and what the commit message should be.”
If you’re not in a backend repo (no manage.py, no backend-style AGENTS.md, no .pre-commit-config.yaml), this Skill should say so explicitly and fall back to a lighter “generic Python pre-commit” behavior.
Modes
This Skill behaves differently based on how it is invoked:
pre-commitmode – invoked via/backend-atomic-commit:pre-commit:- Actively applies changes to make the working tree and staged files conform
to repo standards and pre-commit requirements.
- Runs all relevant static checks and auto-fixers.
- Does not propose or drive a commit.
atomic-commitmode – invoked via/backend-atomic-commit:atomic-commit:- Runs everything from
pre-commitmode. - Enforces atomicity of staged changes.
- Requires all gates to be green.
- Proposes a commit message, but must never add AI signatures or plugin
branding to the message.
The command markdown sets the mode. You should detect the mode from the command description/context and adjust behavior accordingly.
Core Priorities
Emulate Monty’s backend engineering and review taste, tuned for pre-commit:
- Correctness & invariants – multi-tenancy, time dimensions, and security
constraints come first.
- Safety & reviewability – avoid dangerous schema changes, large risky
try/except blocks, hidden PII, or untyped payloads.
- Atomic commits – one commit should represent one coherent change; split
unrelated work.
- Local repo rules first – treat
AGENTS.mdandCLAUDE.mdas the source
of truth when present; this Skill is a default baseline.
- Tooling alignment – use uv wrappers,
.security/*helpers, and
.pre-commit-config.yaml hooks as documented, not ad-hoc commands.
- Type and structure – prefer precise type hints,
TypedDict/dataclasses,
and structured logging over untyped dicts and log soup.
- No AI signatures in commits – commit messages must look like a human
wrote them; this Skill should be invisible from git log.
Always prioritize [BLOCKING] issues over style and nits.
Environment & Context Gathering
When this Skill runs, you should first gather context using Bash, Read, Glob, and Grep:
- Git context:
git status --porcelaingit branch --show-currentgit diff --cached --statgit diff --cached --name-onlygit log --oneline -10- Repo configuration:
- Read
AGENTS.mdandCLAUDE.md(if present) for repo-specific rules. - Detect
.pre-commit-config.yaml. - Detect
.security/scripts, especially: ./.security/ruff_pr_diff.sh./.security/local_imports_pr_diff.sh- Detect
manage.py/ Django project layout. - Tool availability:
uvand.bin/wrappers:.bin/ruff,.bin/ty,.bin/django,.bin/pytest.- Fallback to
uv runor plainpython/pytest/ruffwhere necessary.
If the repo clearly isn’t the Diversio backend / Django4Lyfe style, say so and adjust expectations (but you can still run generic Python pre-commit checks).
Checks in Both Modes
In both pre-commit and atomic-commit modes, follow this pipeline:
- Scope changed files
- Start from files reported by
git statusandgit diff --cached: - Distinguish staged vs unstaged vs untracked.
- Categorize by type:
- Python (src vs tests;
optimo_*,dashboardapp,survey, etc.). - Templates (Django HTML).
- Config (YAML, JSON,
.pre-commit-config.yaml,pyproject.toml,
requirements*.txt).
- Docs/markdown.
- Static formatting/linting
- Ruff:
- Run
./.security/ruff_pr_diff.shif present. - Run
.bin/ruff check --fixon changed Python files. - Run
.bin/ruff formaton those files. - IMPORTANT: For any file you touch, you must resolve ALL ruff
errors in that file—not just the ones you introduced. CI runs ruff on modified files, so pre-existing errors in touched files will cause CI failures. Do not dismiss errors as "pre-existing" if the file is in your diff.
- Templates:
- Run
djlint-reformat-djangoanddjlint-djangoon changed templates
when configured in .pre-commit-config.yaml.
- Generic pre-commit hooks:
- Respect hook definitions in
.pre-commit-config.yaml; run
pre-commit run on relevant files when possible.
- Backend-specific .security gates
- Run
.securityscripts where present: ./.security/ruff_pr_diff.sh– Ruff on changed files vs base branch../.security/local_imports_pr_diff.sh– check for local imports.- Treat failures as at least
[SHOULD_FIX]and usually[BLOCKING]for
atomic-commit.
- Type checking with ty
- Run
tyon modified Python files only to catch type errors before CI:
```bash # For staged files (atomic-commit mode): .bin/ty check $(git diff --cached --name-only --diff-filter=ACMR | grep '\.py$')
# For all modified files (pre-commit mode): .bin/ty check $(git diff --name-only --diff-filter=ACMR | grep '\.py$') ```
- This scoped approach avoids triggering baseline errors in unmodified
files while matching CircleCI's ty check behavior.
- IMPORTANT: For any file you touch, you must resolve ALL
tyerrors
in that file—not just the ones you introduced. CI runs ty on modified files, so pre-existing errors in touched files will cause CI failures. Do not dismiss errors as "pre-existing" if the file is in your diff.
- Common pitfall: Fixing ruff ARG002 (unused argument) by prefixing with
_
may satisfy ruff but break ty if the method signature must match a parent class (e.g., Django admin methods). Always run both checks together.
- Treat any
tyerrors in modified files as[BLOCKING]for
atomic-commit mode or [SHOULD_FIX] for