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.
- Local
/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 ingit statusso they obey backendAGENTS.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 inbackend/. Enforce all pre-commit hooks and.securityscripts, 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-commitin a strict mode: eliminate local imports, fix type hints (noAny, 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 --autoto:- 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.”
- enforce structured logging with
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.
- Runs everything from
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.yamlhooks 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.
- Read
- 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.
- Python (src vs tests;
- Start from files reported by
-
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.
- Run
- 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.
- Run
- Generic pre-commit hooks:
- Respect hook definitions in
.pre-commit-config.yaml; runpre-commit runon relevant files when possible.
- Respect hook definitions in
- Ruff:
-
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]foratomic-commit.
- Run
-
Type checking with ty
- Run
tyon modified Python files only to catch type errors before CI:# 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
tycheck behavior. - IMPORTANT: For any file you touch, you must resolve ALL
tyerrors in that file—not just the ones you introduced. CI runstyon 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 breaktyif 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]foratomic-commitmode or[SHOULD_FIX]for
- Run