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.md rules.
.pre-commit-config.yaml expectations.
.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-commit on 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-commit to 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
TypedDict payloads,
- 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-commit mode – 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-commit mode – invoked via /backend-atomic-commit:atomic-commit:
- Runs everything from
pre-commit mode.
- 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.md and CLAUDE.md as 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 --porcelain
git branch --show-current
git diff --cached --stat
git diff --cached --name-only
git log --oneline -10
- Repo configuration:
- Read
AGENTS.md and CLAUDE.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:
uv and .bin/ wrappers:
.bin/ruff, .bin/ty, .bin/django, .bin/pytest.
- Fallback to
uv run or plain python / pytest / ruff where 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 status and git 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.sh if present.
- Run
.bin/ruff / ruff check on changed Python files.
- Run
ruff format / .bin/ruff format on those files.
- Templates:
- Run
djlint-reformat-django and djlint-django on 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
.security scripts 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/system checks
- Run
.bin/ty or ./ty_checks.py for type checking (respecting any
documented baseline, but treating new issues seriously).
- Run
.bin/django check or equivalent:
uv run python manage.py check --fail-level WARNING.
- For risky changes (models, migrations, core logic), run targeted
pytest subsets based on changed apps:
- Example:
dashboardapp/ changes → pytest dashboardapp/tests/.
- If tests cannot be run (e.g. env not set up), say so explicitly and treat
“tests not run” as at least
[SHOULD_FIX] and often [BLOCKING] for
atomic-commit.
Interaction with pre-commit hooks
- If
.pre-commit-config.yaml exists:
- Expect hooks to run and modify files (ruff, djlint, interrogate,
custom scripts).
- After hooks run, re-check
git status and restage modified files as
appropriate.
- If a hook executable is missing (e.g.
check_prepare_commit_msg_hook.py
referenced but not present), do not crash:
- Record a
[SHOULD_FIX] issue stating which hook is missing and why it
matters.
Monty Backend Taste – Auto-Fix Rules
When running in pre-commit mode, you are allowed and expected to actively
edit code to align with Monty’s backend taste where it is clearly safe. In
atomic-commit mode, you may still fix things, but be more conservative and
always summarize edits.
Imports & local imports
- Enforce no local imports at any cost:
- Avoid
from myapp.models import MyModel inside functions or methods just
to dodge cyclic imports.
- Use
.security/local_imports_pr_diff.sh as the first line of defense.
- Prefer:
- Module-level imports.
- Refactoring helpers to avoid cycles.
- Type-only imports (e.g.
from __future__ import annotations) when needed.
- If moving imports risks true cyclic import problems:
- Suggest structural changes (splitting modules, relocating helpers).
- Never silently reintroduce local imports; call out unresolved cycles as
[SHOULD_FIX].
Logging (especially in optimo_* apps)
- Enforce structured logging:
- Prefer structured payloads over single log strings:
- Good:
logger.info("optimo_event", extra={"company_uuid": str(company.uuid)}).
- Avoid:
logger.info("Company %s did %s", company.name, something).
- In
optimo_* apps, treat unstructured logging as at least [SHOULD_FIX].
- PII in logs:
- Never log PII such as
assignment.employee.email; this is enforced by
pre-commit hooks already, but you should also conceptually check.
- Prefer logging UUIDs/IDs instead of emails or names.
- Log levels:
- Avoid
logger.exception for expected error paths; use error or warning
with explicit messages.
Try/except and error handling
- Avoid large, catch-all
try/except blocks:
- Shrink the
try body to only the lines that can raise.
- Replace bare
except: or except Exception: with specific exceptions
whenever possible.
- Never swallow exceptions silently:
- Always log or re-raise; returning silently on failure is
[BLOCKING] for
behaviorally important code.
- Avoid overusing
getattr/hasattr as a crutch:
- Only use
hasattr() when truly needed (e.g. cross-version adapters) and
document why.
Types, hints, and data structures
- Be pedantic about type hints:
- Avoid
Any as much as possible; prefer precise types and generics.
- No string-based type hints like
"OptimoRiskQuestionBank"; use real types
and proper imports.
- Add missing annotations on new/changed functions, especially in
optimo_*, dashboardapp, and other core apps.
- Prefer structured data:
- Replace
Dict[str, Any] or ad-hoc dict payloads with TypedDict or
dataclasses when the shape is stable and local.
- Avoid shape-changing dicts where keys appear/disappear across branches;
suggest a typed structure instead.
Tests and fixtures
- Avoid repeating fixtures or introducing fixture collisions:
- Prefer existing rich fixtures described in
AGENTS.md (e.g. responses
in survey tests, company/survey fixtures that respect multi-tenant
relationships).
- Do not introduce new Django
TestCase classes in optimo_* apps; use
pytest + fixtures.
- Watch for multi-tenant fixture mismatches (e.g. survey from one company,
user from another); highlight these as
[BLOCKING] when they affect
correctness.
- When touching tests:
- Prefer pytest fixtures and helper factories.
- Avoid local imports inside tests; use module-level imports.
ORM and query patterns
- Use reverse relations where it reduces imports and improves clarity:
- Prefer
company.surveys.all() to Survey.objects.filter(company=company)
when it avoids extra imports and is idiomatic.
- Watch for N+1 queries in obvious loops:
- Flag them as
[SHOULD_FIX] for hot paths or performance-sensitive code.
Commented / dead code and debug artifacts
- Remove obvious debug leftovers:
print(...), pdb.set_trace(), ipdb.set_trace(), breakpoint() in
non-test code.
- Remove clearly obsolete commented-out blocks:
- Old versions of code commented around a new implementation.
- For ambiguous commented sections:
- Flag them as
[SHOULD_FIX] and suggest either deleting them or moving
rationale into docs.
TODO / FIXME without ticket IDs:
- Suggest converting to ticket-tagged comments (e.g.
TODO(GH-123): ... or
TODO(27pfu0): ...) or moving the note into ClickUp.
String / formatting style
- Migrate to f-strings where it improves clarity:
- Replace old
% formatting or .format() with f-strings when not blocked
by translation/i18n constraints.
- Avoid giant f-strings with logic:
- Suggest splitting into intermediate variables when readability suffers.
Security & secrets
- Detect obvious secrets checked into code or fixtures:
- Hardcoded tokens, passwords, API keys.
- Flag as
[BLOCKING] and suggest using environment variables and 1Password.
- Avoid staging obvious secret-heavy files:
.env, google_creds.json, google_drive_creds.json, etc.
- Recommend un-staging and
.gitignore updates where appropriate.
Migrations and schema changes
- Do not change migration behavior automatically; instead:
- Detect destructive schema changes (dropping fields/tables) combined with
code changes that still expect those fields:
- Mark as
[BLOCKING] and recommend a two-step rollout:
- PR 1: remove usage in code, keep schema.
- PR 2: drop the field/table once code is clean.
- Detect new non-nullable fields with defaults on large/hot tables:
- Mark as
[SHOULD_FIX] or [BLOCKING] depending on risk.
- Suggest the safer pattern:
- Add nullable field with no default.
- Backfill in batches.
- Then add default for new rows only.
- Detect volatile defaults (UUIDs, timestamps) used in migrations:
- Warn against backfilling large tables inside a single atomic migration;
recommend batched or non-atomic backfills.
Critical backend patterns from AGENTS.md
- Watch for new instances of patterns explicitly banned in backend
AGENTS.md:
- Django Ninja
Query() module-level constants that break parameter
resolution (e.g. Q_INCLUDE_INACTIVE = Query(False, ...)).
- Legacy survey models like
OptimoEmployeeSurvey or employee_survey.
- Any other CRITICAL warnings spelled out in that file.
- Treat any new usage of these patterns as
[BLOCKING].
Atomic-Commit Mode – Extra Strictness
In atomic-commit mode (invoked via /backend-atomic-commit:atomic-commit),
you must be very strict:
Atomicity of staged changes
- From
git diff --cached --name-only, determine if staged changes belong
to one coherent change:
- Example of non-atomic:
- Refactor in
survey/ plus an unrelated optimo bugfix and docs tweak.
- Emit:
[BLOCKING] if the staged set is clearly multiple logical changes.
[SHOULD_FIX] for minor opportunistic cleanups that could be split.
- You may suggest a split (e.g. “extract the optimo fix into a separate
commit”) but must not label a non-atomic set as “ready”.
All gates must be green
- The commit is not ready if any of these fail:
./.security/ruff_pr_diff.sh
./.security/local_imports_pr_diff.sh
.bin/ruff / ruff format
.bin/ty / ./ty_checks.py
.bin/django check / manage.py check
- Relevant
pytest subsets for risky changes
- Pre-commit hooks defined in
.pre-commit-config.yaml
- In
--auto style usage, you may skip conversational confirmation, but
you must not relax these gates.
- If tests or checks are skipped for any reason, clearly state that and
treat it as at least
[SHOULD_FIX] and usually [BLOCKING].
Commit message generation (no AI signature)
- Extract ticket ID from branch name using repo conventions:
- For the Diversio backend:
- Branch name:
clickup_<ticket_id>_...
- Commit format per
AGENTS.md: <ticket_id>: Description.
- If commit message hooks like
commit_msg_hook.py exist:
- Avoid double-prefixing ticket IDs.
- If hooks and docs disagree, call that out as
[SHOULD_FIX] and follow
the documented AGENTS.md convention for suggestions.
- Generate a concise, human-looking subject line:
- Summarize what changed and why in one line.
- Do not mention Claude, AI, this Skill, or plugin names.
- Do not add any footer or signature:
- No “via Claude Code”.
- No “Generated by backend-atomic-commit”.
- Commit messages must look like a human wrote them.
- Final preview and verdict
Your atomic-commit output should include:
- A short summary of what was checked.
Checks run – listing each gate and its status.
What’s aligned – strengths and good patterns in the staged changes.
Needs changes – bullets with [BLOCKING], [SHOULD_FIX], [NIT].
Proposed commit – suggested commit message and list of files.
- An explicit verdict:
- “✅ Commit ready” only if there are no
[BLOCKING] items.
- Otherwise:
- “❌ Not ready to commit” with concrete next steps.
You should never encourage the user to run git commit as-is if any
[BLOCKING] issues remain.
Pre-Commit Mode – Fixing Without Committing
In pre-commit mode (invoked via /backend-atomic-commit:pre-commit):
- You may aggressively auto-fix:
- Formatting, linting, local imports, obvious type hints, logging patterns,
removal of debug code, and consistent fixtures.
- You must:
- Run the same gates described above (Ruff,
.security/*, ty, Django
checks, tests as appropriate).
- Re-run or re-stage files modified by tools or hooks.
- You do not propose a commit or check atomicity.
- Your output should focus on:
Fixes applied – concrete edits you made.
Remaining issues – with severity tags.
Checks run – which gates passed/failed.
This mode is the “make my working tree clean and standards-compliant” helper
before running an atomic commit.
Severity Tags & Output Shape
Always structure findings using severity tags and sections:
[BLOCKING] – must be fixed before a commit is considered ready:
- Failing
.security scripts or pre-commit hooks.
- New banned patterns from
AGENTS.md (e.g., Ninja Query constants, legacy
survey models).
- Obvious multi-tenant or security regressions.
- Non-atomic staged changes in
atomic-commit mode.
[SHOULD_FIX] – important, strongly recommended changes:
- Style/structure that harms readability or maintainability.
- Missing type hints where types are clear.
- Ambiguous commented code or TODOs without tickets.
- Missing tests for non-trivial new behavior.
[NIT] – minor cleanups:
- Docstring tone/punctuation.
- Minor naming and formatting nits not covered by Ruff.
Output shape for both modes:
- 1–3 sentence summary of what was checked.
- Sections (when appropriate):
What’s aligned
Needs changes
Checks run
Proposed commit (only in atomic-commit mode)
Be direct, specific, and actionable in each bullet, pointing to file/area and
suggesting concrete corrections. Never hide behind vague "consider improving"
phrases when you can be precise.
Compatibility Notes
This skill is designed to work with both Claude Code and OpenAI Codex.
For Codex users:
- Install via skill-installer with
--repo DiversioTeam/agent-skills-marketplace --path plugins/backend-atomic-commit/skills/backend-atomic-commit.
- Use
$skill backend-atomic-commit to invoke.
For Claude Code users:
- Install via
/plugin install backend-atomic-commit@diversiotech.
- Use
/backend-atomic-commit:atomic-commit or /backend-atomic-commit:pre-commit to invoke.
1---2name: backend-atomic-commit-23description: Pedantic backend pre-commit and atomic commit Skill for Django/Optimo-style repos. Enforces local AGENTS.md / CLAUDE.md, pre-commit hooks, .security/* helpers, and Monty’s backend engineering taste – with no AI signatures in commit messages.4---56# Backend Atomic Commit Skill78## When to Use This Skill910Use this Skill in backend/Django repos (especially the Diversio monolith11backend) when you want:1213- `/backend-atomic-commit:pre-commit` – to **actively fix** the current code14 (formatting, imports, type hints, logging, etc.) so that it matches:15 - Local `AGENTS.md` / `CLAUDE.md` rules.16 - `.pre-commit-config.yaml` expectations.17 - `.security/` diff helpers (ruff and local imports).18 - Monty’s backend taste.19- `/backend-atomic-commit:atomic-commit` – to run the same checks plus:20 - Enforce that the **staged changes are atomic** (one coherent change).21 - Ensure all quality gates are green (no shortcuts).22 - Propose a strict, ticket-prefixed commit message **without** any Claude or23 AI signatures.2425## Example Prompts2627- “Run `/backend-atomic-commit:pre-commit` on this repo and actively fix all28 files in `git status` so they obey backend `AGENTS.md`, `.pre-commit-config.yaml`,29 `.security/*` helpers, and Monty’s taste (no local imports, strong typing,30 structured logging). Then summarize what you changed and what’s still31 `[BLOCKING]`.”32- “Use `/backend-atomic-commit:atomic-commit` to prepare an atomic commit for33 the staged changes in `backend/`. Enforce all pre-commit hooks and34 `.security` scripts, run Ruff, ty, Django checks, and relevant pytest35 subsets, then propose a ticket-prefixed commit message with **no AI36 signature** and clearly mark any `[BLOCKING]` issues.”37- “Treat my current backend changes as one logical bugfix and run38 `/backend-atomic-commit:pre-commit` in a strict mode: eliminate local39 imports, fix type hints (no `Any`, no string-based annotations), clean up40 debug statements, and ensure Ruff, `.security/local_imports_pr_diff.sh`,41 ty, and Django checks are happy."42- “Before I commit these `optimo_*` changes, run43 `/backend-atomic-commit:atomic-commit --auto` to:44 - enforce structured logging with `TypedDict` payloads,45 - ensure no PII in logs,46 - verify tests and `.security/*` scripts,47 and then tell me whether the commit is ready and what the commit message48 should be.”4950If you’re not in a backend repo (no `manage.py`, no backend-style `AGENTS.md`,51no `.pre-commit-config.yaml`), this Skill should say so explicitly and fall52back to a lighter “generic Python pre-commit” behavior.5354## Modes5556This Skill behaves differently based on how it is invoked:5758- `pre-commit` mode – invoked via `/backend-atomic-commit:pre-commit`:59 - Actively applies changes to make the working tree and staged files conform60 to repo standards and pre-commit requirements.61 - Runs all relevant static checks and auto-fixers.62 - Does **not** propose or drive a commit.63- `atomic-commit` mode – invoked via `/backend-atomic-commit:atomic-commit`:64 - Runs everything from `pre-commit` mode.65 - Enforces atomicity of staged changes.66 - Requires all gates to be green.67 - Proposes a commit message, but **must never** add AI signatures or plugin68 branding to the message.6970The command markdown sets the mode. You should detect the mode from the command71description/context and adjust behavior accordingly.7273## Core Priorities7475Emulate Monty’s backend engineering and review taste, tuned for pre-commit:76771. **Correctness & invariants** – multi-tenancy, time dimensions, and security78 constraints come first.792. **Safety & reviewability** – avoid dangerous schema changes, large risky80 try/except blocks, hidden PII, or untyped payloads.813. **Atomic commits** – one commit should represent one coherent change; split82 unrelated work.834. **Local repo rules first** – treat `AGENTS.md` and `CLAUDE.md` as the source84 of truth when present; this Skill is a default baseline.855. **Tooling alignment** – use uv wrappers, `.security/*` helpers, and86 `.pre-commit-config.yaml` hooks as documented, not ad-hoc commands.876. **Type and structure** – prefer precise type hints, `TypedDict`/dataclasses,88 and structured logging over untyped dicts and log soup.897. **No AI signatures in commits** – commit messages must look like a human90 wrote them; this Skill should be invisible from `git log`.9192Always prioritize `[BLOCKING]` issues over style and nits.9394## Environment & Context Gathering9596When this Skill runs, you should first gather context using `Bash`, `Read`,97`Glob`, and `Grep`:9899- Git context:100 - `git status --porcelain`101 - `git branch --show-current`102 - `git diff --cached --stat`103 - `git diff --cached --name-only`104 - `git log --oneline -10`105- Repo configuration:106 - Read `AGENTS.md` and `CLAUDE.md` (if present) for repo-specific rules.107 - Detect `.pre-commit-config.yaml`.108 - Detect `.security/` scripts, especially:109 - `./.security/ruff_pr_diff.sh`110 - `./.security/local_imports_pr_diff.sh`111 - Detect `manage.py` / Django project layout.112- Tool availability:113 - `uv` and `.bin/` wrappers:114 - `.bin/ruff`, `.bin/ty`, `.bin/django`, `.bin/pytest`.115 - Fallback to `uv run` or plain `python` / `pytest` / `ruff` where necessary.116117If the repo clearly isn’t the Diversio backend / Django4Lyfe style, say so and118adjust expectations (but you can still run generic Python pre-commit checks).119120## Checks in Both Modes121122In **both** `pre-commit` and `atomic-commit` modes, follow this pipeline:1231241. **Scope changed files**125 - Start from files reported by `git status` and `git diff --cached`:126 - Distinguish staged vs unstaged vs untracked.127 - Categorize by type:128 - Python (src vs tests; `optimo_*`, `dashboardapp`, `survey`, etc.).129 - Templates (Django HTML).130 - Config (YAML, JSON, `.pre-commit-config.yaml`, `pyproject.toml`,131 `requirements*.txt`).132 - Docs/markdown.1331342. **Static formatting/linting**135 - Ruff:136 - Run `./.security/ruff_pr_diff.sh` if present.137 - Run `.bin/ruff` / `ruff check` on changed Python files.138 - Run `ruff format` / `.bin/ruff format` on those files.139 - Templates:140 - Run `djlint-reformat-django` and `djlint-django` on changed templates141 when configured in `.pre-commit-config.yaml`.142 - Generic pre-commit hooks:143 - Respect hook definitions in `.pre-commit-config.yaml`; run144 `pre-commit run` on relevant files when possible.1451463. **Backend-specific .security gates**147 - Run `.security` scripts where present:148 - `./.security/ruff_pr_diff.sh` – Ruff on changed files vs base branch.149 - `./.security/local_imports_pr_diff.sh` – check for local imports.150 - Treat failures as at least `[SHOULD_FIX]` and usually `[BLOCKING]` for151 `atomic-commit`.1521534. **Type/system checks**154 - Run `.bin/ty` or `./ty_checks.py` for type checking (respecting any155 documented baseline, but treating **new** issues seriously).156 - Run `.bin/django check` or equivalent:157 - `uv run python manage.py check --fail-level WARNING`.158 - For risky changes (models, migrations, core logic), run **targeted**159 `pytest` subsets based on changed apps:160 - Example: `dashboardapp/` changes → `pytest dashboardapp/tests/`.161 - If tests cannot be run (e.g. env not set up), say so explicitly and treat162 “tests not run” as at least `[SHOULD_FIX]` and often `[BLOCKING]` for163 `atomic-commit`.1641655. **Interaction with pre-commit hooks**166 - If `.pre-commit-config.yaml` exists:167 - Expect hooks to run and modify files (ruff, djlint, interrogate,168 custom scripts).169 - After hooks run, re-check `git status` and restage modified files as170 appropriate.171 - If a hook executable is missing (e.g. `check_prepare_commit_msg_hook.py`172 referenced but not present), do **not** crash:173 - Record a `[SHOULD_FIX]` issue stating which hook is missing and why it174 matters.175176## Monty Backend Taste – Auto-Fix Rules177178When running in `pre-commit` mode, you are allowed and expected to **actively179edit code** to align with Monty’s backend taste where it is clearly safe. In180`atomic-commit` mode, you may still fix things, but be more conservative and181always summarize edits.182183### Imports & local imports184185- Enforce **no local imports at any cost**:186 - Avoid `from myapp.models import MyModel` inside functions or methods just187 to dodge cyclic imports.188 - Use `.security/local_imports_pr_diff.sh` as the first line of defense.189 - Prefer:190 - Module-level imports.191 - Refactoring helpers to avoid cycles.192 - Type-only imports (e.g. `from __future__ import annotations`) when needed.193 - If moving imports risks true cyclic import problems:194 - Suggest structural changes (splitting modules, relocating helpers).195 - Never silently reintroduce local imports; call out unresolved cycles as196 `[SHOULD_FIX]`.197198### Logging (especially in optimo_* apps)199200- Enforce structured logging:201 - Prefer structured payloads over single log strings:202 - Good: `logger.info("optimo_event", extra={"company_uuid": str(company.uuid)})`.203 - Avoid: `logger.info("Company %s did %s", company.name, something)`.204 - In `optimo_*` apps, treat unstructured logging as at least `[SHOULD_FIX]`.205- PII in logs:206 - Never log PII such as `assignment.employee.email`; this is enforced by207 pre-commit hooks already, but you should also conceptually check.208 - Prefer logging UUIDs/IDs instead of emails or names.209- Log levels:210 - Avoid `logger.exception` for expected error paths; use `error` or `warning`211 with explicit messages.212213### Try/except and error handling214215- Avoid large, catch-all `try/except` blocks:216 - Shrink the `try` body to only the lines that can raise.217 - Replace bare `except:` or `except Exception:` with specific exceptions218 whenever possible.219- Never swallow exceptions silently:220 - Always log or re-raise; returning silently on failure is `[BLOCKING]` for221 behaviorally important code.222- Avoid overusing `getattr`/`hasattr` as a crutch:223 - Only use `hasattr()` when truly needed (e.g. cross-version adapters) and224 document why.225226### Types, hints, and data structures227228- Be pedantic about type hints:229 - Avoid `Any` as much as possible; prefer precise types and generics.230 - No string-based type hints like `"OptimoRiskQuestionBank"`; use real types231 and proper imports.232 - Add missing annotations on new/changed functions, especially in233 `optimo_*`, `dashboardapp`, and other core apps.234- Prefer structured data:235 - Replace `Dict[str, Any]` or ad-hoc dict payloads with `TypedDict` or236 dataclasses when the shape is stable and local.237 - Avoid shape-changing dicts where keys appear/disappear across branches;238 suggest a typed structure instead.239240### Tests and fixtures241242- Avoid repeating fixtures or introducing fixture collisions:243 - Prefer existing rich fixtures described in `AGENTS.md` (e.g. `responses`244 in survey tests, company/survey fixtures that respect multi-tenant245 relationships).246 - Do not introduce new Django `TestCase` classes in `optimo_*` apps; use247 pytest + fixtures.248 - Watch for multi-tenant fixture mismatches (e.g. survey from one company,249 user from another); highlight these as `[BLOCKING]` when they affect250 correctness.251- When touching tests:252 - Prefer pytest fixtures and helper factories.253 - Avoid local imports inside tests; use module-level imports.254255### ORM and query patterns256257- Use reverse relations where it reduces imports and improves clarity:258 - Prefer `company.surveys.all()` to `Survey.objects.filter(company=company)`259 when it avoids extra imports and is idiomatic.260- Watch for N+1 queries in obvious loops:261 - Flag them as `[SHOULD_FIX]` for hot paths or performance-sensitive code.262263### Commented / dead code and debug artifacts264265- Remove obvious debug leftovers:266 - `print(...)`, `pdb.set_trace()`, `ipdb.set_trace()`, `breakpoint()` in267 non-test code.268- Remove clearly obsolete commented-out blocks:269 - Old versions of code commented around a new implementation.270- For ambiguous commented sections:271 - Flag them as `[SHOULD_FIX]` and suggest either deleting them or moving272 rationale into docs.273- `TODO` / `FIXME` without ticket IDs:274 - Suggest converting to ticket-tagged comments (e.g. `TODO(GH-123): ...` or275 `TODO(27pfu0): ...`) or moving the note into ClickUp.276277### String / formatting style278279- Migrate to f-strings where it improves clarity:280 - Replace old `%` formatting or `.format()` with f-strings when not blocked281 by translation/i18n constraints.282- Avoid giant f-strings with logic:283 - Suggest splitting into intermediate variables when readability suffers.284285### Security & secrets286287- Detect obvious secrets checked into code or fixtures:288 - Hardcoded tokens, passwords, API keys.289 - Flag as `[BLOCKING]` and suggest using environment variables and 1Password.290- Avoid staging obvious secret-heavy files:291 - `.env`, `google_creds.json`, `google_drive_creds.json`, etc.292 - Recommend un-staging and `.gitignore` updates where appropriate.293294### Migrations and schema changes295296- Do **not** change migration behavior automatically; instead:297 - Detect destructive schema changes (dropping fields/tables) combined with298 code changes that still expect those fields:299 - Mark as `[BLOCKING]` and recommend a two-step rollout:300 - PR 1: remove usage in code, keep schema.301 - PR 2: drop the field/table once code is clean.302 - Detect new non-nullable fields with defaults on large/hot tables:303 - Mark as `[SHOULD_FIX]` or `[BLOCKING]` depending on risk.304 - Suggest the safer pattern:305 - Add nullable field with no default.306 - Backfill in batches.307 - Then add default for new rows only.308 - Detect volatile defaults (UUIDs, timestamps) used in migrations:309 - Warn against backfilling large tables inside a single atomic migration;310 recommend batched or non-atomic backfills.311312### Critical backend patterns from AGENTS.md313314- Watch for new instances of patterns explicitly banned in backend `AGENTS.md`:315 - Django Ninja `Query()` module-level constants that break parameter316 resolution (e.g. `Q_INCLUDE_INACTIVE = Query(False, ...)`).317 - Legacy survey models like `OptimoEmployeeSurvey` or `employee_survey`.318 - Any other CRITICAL warnings spelled out in that file.319- Treat any new usage of these patterns as `[BLOCKING]`.320321## Atomic-Commit Mode – Extra Strictness322323In `atomic-commit` mode (invoked via `/backend-atomic-commit:atomic-commit`),324you must be **very strict**:3253261. **Atomicity of staged changes**327 - From `git diff --cached --name-only`, determine if staged changes belong328 to one coherent change:329 - Example of non-atomic:330 - Refactor in `survey/` plus an unrelated optimo bugfix and docs tweak.331 - Emit:332 - `[BLOCKING]` if the staged set is clearly multiple logical changes.333 - `[SHOULD_FIX]` for minor opportunistic cleanups that could be split.334 - You may suggest a split (e.g. “extract the optimo fix into a separate335 commit”) but must not label a non-atomic set as “ready”.3363372. **All gates must be green**338 - The commit is **not** ready if any of these fail:339 - `./.security/ruff_pr_diff.sh`340 - `./.security/local_imports_pr_diff.sh`341 - `.bin/ruff` / `ruff format`342 - `.bin/ty` / `./ty_checks.py`343 - `.bin/django check` / `manage.py check`344 - Relevant `pytest` subsets for risky changes345 - Pre-commit hooks defined in `.pre-commit-config.yaml`346 - In `--auto` style usage, you may skip conversational confirmation, but347 you **must not** relax these gates.348 - If tests or checks are skipped for any reason, clearly state that and349 treat it as at least `[SHOULD_FIX]` and usually `[BLOCKING]`.3503513. **Commit message generation (no AI signature)**352353- Extract ticket ID from branch name using repo conventions:354 - For the Diversio backend:355 - Branch name: `clickup_<ticket_id>_...`356 - Commit format per `AGENTS.md`: `<ticket_id>: Description`.357 - If commit message hooks like `commit_msg_hook.py` exist:358 - Avoid double-prefixing ticket IDs.359 - If hooks and docs disagree, call that out as `[SHOULD_FIX]` and follow360 the documented `AGENTS.md` convention for suggestions.361- Generate a concise, human-looking subject line:362 - Summarize what changed and why in one line.363 - Do **not** mention Claude, AI, this Skill, or plugin names.364- Do **not** add any footer or signature:365 - No “via Claude Code”.366 - No “Generated by backend-atomic-commit”.367 - Commit messages must look like a human wrote them.3683694. **Final preview and verdict**370371Your `atomic-commit` output should include:372373- A short summary of what was checked.374- `Checks run` – listing each gate and its status.375- `What’s aligned` – strengths and good patterns in the staged changes.376- `Needs changes` – bullets with `[BLOCKING]`, `[SHOULD_FIX]`, `[NIT]`.377- `Proposed commit` – suggested commit message and list of files.378- An explicit verdict:379 - “✅ Commit ready” only if there are **no `[BLOCKING]` items**.380 - Otherwise:381 - “❌ Not ready to commit” with concrete next steps.382383You should **never** encourage the user to run `git commit` as-is if any384`[BLOCKING]` issues remain.385386## Pre-Commit Mode – Fixing Without Committing387388In `pre-commit` mode (invoked via `/backend-atomic-commit:pre-commit`):389390- You may aggressively auto-fix:391 - Formatting, linting, local imports, obvious type hints, logging patterns,392 removal of debug code, and consistent fixtures.393- You must:394 - Run the same gates described above (Ruff, `.security/*`, ty, Django395 checks, tests as appropriate).396 - Re-run or re-stage files modified by tools or hooks.397- You do **not** propose a commit or check atomicity.398- Your output should focus on:399 - `Fixes applied` – concrete edits you made.400 - `Remaining issues` – with severity tags.401 - `Checks run` – which gates passed/failed.402403This mode is the “make my working tree clean and standards-compliant” helper404before running an atomic commit.405406## Severity Tags & Output Shape407408Always structure findings using severity tags and sections:409410- `[BLOCKING]` – must be fixed before a commit is considered ready:411 - Failing `.security` scripts or pre-commit hooks.412 - New banned patterns from `AGENTS.md` (e.g., Ninja Query constants, legacy413 survey models).414 - Obvious multi-tenant or security regressions.415 - Non-atomic staged changes in `atomic-commit` mode.416- `[SHOULD_FIX]` – important, strongly recommended changes:417 - Style/structure that harms readability or maintainability.418 - Missing type hints where types are clear.419 - Ambiguous commented code or TODOs without tickets.420 - Missing tests for non-trivial new behavior.421- `[NIT]` – minor cleanups:422 - Docstring tone/punctuation.423 - Minor naming and formatting nits not covered by Ruff.424425Output shape for both modes:426427- 1–3 sentence summary of what was checked.428- Sections (when appropriate):429 - `What’s aligned`430 - `Needs changes`431 - `Checks run`432 - `Proposed commit` (only in atomic-commit mode)433434Be direct, specific, and actionable in each bullet, pointing to file/area and435suggesting concrete corrections. Never hide behind vague "consider improving"436phrases when you can be precise.437438## Compatibility Notes439440This skill is designed to work with both **Claude Code** and **OpenAI Codex**.441442For Codex users:443- Install via skill-installer with `--repo DiversioTeam/agent-skills-marketplace444 --path plugins/backend-atomic-commit/skills/backend-atomic-commit`.445- Use `$skill backend-atomic-commit` to invoke.446447For Claude Code users:448- Install via `/plugin install backend-atomic-commit@diversiotech`.449- Use `/backend-atomic-commit:atomic-commit` or `/backend-atomic-commit:pre-commit` to invoke.