Framework RecipesImplementation, failure path, check

Django · requirements checked during agent edits

Build a Django update that sends notifications after commit

The notification is deferred until the surrounding transaction commits. Calling notify directly inside the atomic block can tell a customer that an update succeeded even if a later database operation rolls it back. Django drops on_commit callbacks when the transaction rolls back.

Implement the requirement

Save this as orders/services.py:

from django.db import transaction

def confirm_order(order, notify):
    with transaction.atomic():
        order.status = "confirmed"
        order.save(update_fields=["status"])
        transaction.on_commit(lambda: notify(order.pk))
    return order

The requirement is adapted from Perch’s public order-service example at commit 4af67af. The Django implementation below is an illustrative adaptation, not a claim about that source project’s framework.

Create the Django project

mkdir checked-django
cd checked-django
python3 -m venv .venv
. .venv/bin/activate
python -m pip install 'Django>=5.2,<5.3'
django-admin startproject config .
python manage.py startapp orders
git init -b tutorial

Add orders to INSTALLED_APPS in config/settings.py. Replace orders/models.py with:

from django.db import models

class Order(models.Model):
    status = models.CharField(max_length=20, default="pending")

Create the table with python manage.py makemigrations orders and python manage.py migrate. Save the service below in orders/services.py.

Start the development server with python manage.py runserver. Follow the Django setup documentation for platform prerequisites. The framework API used here is documented in the official reference.

Test the broken and corrected behavior

Save this as orders/tests.py:

from unittest.mock import Mock
from django.db import transaction
from django.test import TestCase
from .models import Order
from .services import confirm_order

class ConfirmationTests(TestCase):
    def test_notification_waits_for_commit(self):
        order = Order.objects.create()
        notify = Mock()
        with self.captureOnCommitCallbacks(execute=True) as callbacks:
            confirm_order(order, notify)
            notify.assert_not_called()
        self.assertEqual(len(callbacks), 1)
        notify.assert_called_once_with(order.pk)

    def test_rollback_discards_notification(self):
        order = Order.objects.create()
        notify = Mock()
        with self.captureOnCommitCallbacks(execute=True):
            try:
                with transaction.atomic():
                    confirm_order(order, notify)
                    raise ValueError("abort")
            except ValueError:
                pass
        notify.assert_not_called()
        order.refresh_from_db()
        self.assertEqual(order.status, "pending")

Run python manage.py test orders. Then make this deliberate regression: replace transaction.on_commit(lambda: notify(order.pk)) with notify(order.pk). The boundary test should fail. Restore the original before continuing.

Save the requirement as a Perch rule

Perch is an open-source semantic linter powered by SystemOne decision models. Save the following rule in .perch/rules/perch-guide-django-intro.yaml at the repository root, keeping your existing perch.yaml:

- name: notify-after-commit
  where: "orders/services.py"
  ensure: >-
    Order notification callbacks are registered with transaction.on_commit inside the atomic block, so a rolled-back order update does not send a notification.

Install the CLI and sign in, then check the working file:

npm install -g @lakeday/perch
perch login
perch check orders/services.py --rules notify-after-commit --json

Use Node 22 or newer. perch login opens the authentication workflow. perch check reads the file currently on disk, so the agent can check an uncommitted edit. A rule finding exits 3; exits 1 and 2 mean the check did not complete. Read the JSON and the code before deciding what to change.

Captured Perch check

On October 14, 2026, we ran the rule above through Perch using jev-latest on the deliberately broken and corrected files.

Control Command exit Outcome
Broken implementation 3 Rule finding reported
Corrected implementation 0 No rule finding reported

The rule distinguished these two controls in this captured run. Fresh judgments can vary. Captured command output and the broken and corrected source are available for inspection.

Install the rule pack and configure your agent

Download this rule pack ZIP · Download the YAML rules · Agent task. The pack contains the rule, its example paths and the repair/recheck instructions. Review the where selector before using it in an existing project. Keep your root perch.yaml; install this rule as a separate file under .perch/rules/.

  1. Install Perch using Node 22 or newer and sign in once:
npm install -g @lakeday/perch
perch login
  1. Download the pack, inspect it, and extract it from your repository root. The extraction preserves any existing files:
curl -fL 'https://frameworkrecipes.dev/django/intro/rule-pack.zip' -o 'perch-guide-django-intro.zip'
unzip -n 'perch-guide-django-intro.zip'

The installed rule is .perch/rules/perch-guide-django-intro.yaml. Its selector matches orders/services.py in this example; adapt the selector to your application file before checking an existing project.

  1. Configure the coding agent you use. Run one of these commands:

Claude Code:

perch setup claude-code

Codex:

perch setup codex

Cursor:

perch setup cursor

Pi:

perch setup pi
  1. Ask the agent to edit the implementation and check the saved requirement:

Use the installed Perch skill while editing orders/services.py. Preserve notify-after-commit. Run perch check orders/services.py --rules notify-after-commit --json after the edit. Read each finding and the affected code, fix the implementation, and run the identical check again after the fix. Keep the rule and regression tests intact. Run the application's relevant regression tests and report the commands and actual results. Exit 3 means a rule finding; exit 1 or 2 means the check did not complete. Report an unavailable or incomplete check as blocked. Do not claim the application tests ran if only the Perch check ran.

  1. After repairing a finding, run the same check again and inspect the result:
perch check orders/services.py --rules notify-after-commit --json

Commit the downloaded rule and the installed agent configuration with your application. The rule file adds no guarantee of correctness; keep the regression tests from this guide.

Keep the checks within their scope

An on_commit callback can still fail after the database commit, and it is not a durable delivery queue. Use an outbox and a retrying worker when notification delivery must survive a process crash.

Fresh model judgments can vary. Unchanged requests can reuse cached answers. A passing rule check does not prove the application correct; keep the executable test as a separate check. Relevant source code is sent to the configured analysis service.

Published by Perch / Verglas LLC. Framework names identify the software used; this guide is not an official framework publication.