# How the AI Engineering From Scratch Curriculum Enforces "One Commit Per Lesson Directory"

> Learn how the AI Engineering From Scratch curriculum enforces one commit per lesson directory using AGENTS.md, GitHub Actions CI, and a Python audit script to ensure code quality and maintainability.

- Repository: [Rohit Ghumare/ai-engineering-from-scratch](https://github.com/rohitg00/ai-engineering-from-scratch)
- Tags: internals
- Published: 2026-09-04

---

**The "one commit per lesson directory" rule is enforced through a hard policy defined in [`AGENTS.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/AGENTS.md), automated CI checks via GitHub Actions, and a Python audit script that blocks merges when multiple lesson directories are modified in a single commit.**

The `ai-engineering-from-scratch` repository maintains strict git discipline to ensure each educational unit remains atomic and independently reviewable. This policy prevents batching unrelated lessons together, preserving clean history and enabling precise rollbacks. The enforcement operates across three layers: explicit documentation, automated validation, and contributor workflow integration.

## Policy Definition in AGENTS.md

The foundation of this enforcement is a **hard rule** documented in line 45 of [`AGENTS.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/AGENTS.md). The policy explicitly states: "**One commit per lesson directory.** Never batch multiple lessons into one commit. A 10‑lesson PR has 10 commits."

This document serves as the single source of truth for agent behavior and contributor guidelines. By codifying the requirement as a "hard rule" rather than a suggestion, the repository establishes an unambiguous standard that all automation references.

## Automated CI Enforcement via GitHub Actions

The repository implements programmatic validation through the **[`.github/workflows/curriculum.yml`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/.github/workflows/curriculum.yml)** workflow. This GitHub Action triggers on every push and pull request, executing the audit script to validate commit boundaries before code reaches the main branch.

When a contributor opens a PR, the workflow automatically runs [`scripts/audit_lessons.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/scripts/audit_lessons.py) against the proposed changes. If the script detects modifications to more than one lesson directory, the CI job fails with a non-zero exit status, blocking the merge until the contributor splits the changes into separate commits.

### How the Audit Script Validates Commits

The **[`scripts/audit_lessons.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/scripts/audit_lessons.py)** file contains the core validation logic. The script analyzes the git diff between the PR branch and `origin/main` to identify which lesson directories have been touched.

```python

# Collect changed paths from the PR

changed_paths = subprocess.check_output(
    ["git", "diff", "--name-only", "origin/main...HEAD"]
).decode().splitlines()

# Keep only lesson directories (phases/<phase>/<lesson>/)

lesson_dirs = {
    Path(p).parts[0:3] for p in changed_paths
    if p.startswith("phases/")
}

# Enforce exactly one lesson directory per commit

assert len(lesson_dirs) == 1, (
    "PR modifies multiple lesson directories: "
    f"{', '.join('/'.join(d) for d in lesson_dirs)}"
)

```

The script filters changed paths to include only those within `phases/*/*/` directories, extracts the unique lesson directory paths, and asserts that exactly one directory has been modified. When the assertion fails, the script exits with an error code that propagates to the CI runner, immediately failing the build.

### The CI Workflow Configuration

The workflow definition in **[`.github/workflows/curriculum.yml`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/.github/workflows/curriculum.yml)** orchestrates this enforcement:

```yaml
jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run lesson audit
        run: python3 scripts/audit_lessons.py

```

This configuration ensures the audit runs in a consistent Ubuntu environment with proper git history access. The `actions/checkout@v3` step fetches the repository with sufficient depth to compare against `origin/main`, allowing the script to accurately detect which files changed in the current PR.

## Contributor Workflow and Local Testing

Before opening a pull request, contributors are instructed to run the audit script locally to validate their commit structure. The contribution guidelines recommend executing `python3 scripts/audit_lessons.py` from the repository root to catch violations early.

This local testing capability prevents CI failures and review delays. If the script detects multiple lesson directories in the working changes, contributors must reorganize their work into separate branches or commits, each containing changes to only one `phases/<phase>/<lesson>/` directory.

## Summary

- **Policy Layer**: The [`AGENTS.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/AGENTS.md) file codifies the "one commit per lesson directory" requirement as a hard rule at line 45, establishing clear expectations for all contributors.
- **Automation Layer**: The [`.github/workflows/curriculum.yml`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/.github/workflows/curriculum.yml) GitHub Action triggers automatically on every PR, running the audit script to validate commit boundaries.
- **Validation Layer**: The [`scripts/audit_lessons.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/scripts/audit_lessons.py) script programmatically checks git diffs for `phases/*/*/` directories and fails with a non-zero exit code when multiple lessons are detected.
- **Workflow Layer**: Contributors can run the audit locally before submitting PRs, preventing CI failures and ensuring clean commit history from the start.

## Frequently Asked Questions

### What happens if I accidentally commit multiple lessons in one PR?

The CI workflow in [`.github/workflows/curriculum.yml`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/.github/workflows/curriculum.yml) will detect the violation when [`scripts/audit_lessons.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/scripts/audit_lessons.py) runs. The job will fail with an assertion error listing the multiple lesson directories modified, and GitHub will block the merge until you restructure the commits. You must split the changes into separate commits, each touching only one lesson directory under `phases/`.

### Can I bypass the audit script when testing locally?

While you can technically ignore the script output, the repository design assumes you run `python3 scripts/audit_lessons.py` before pushing. Bypassing local checks only delays the failure to the CI environment. Since the script uses the same git diff logic locally and in CI, local verification guarantees the PR will pass automated checks.

### Why does the curriculum require isolated commits per lesson?

According to the [`AGENTS.md`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/AGENTS.md) policy and repository structure, atomic commits ensure each lesson stands as an independent educational unit. This granularity enables precise rollbacks if a specific lesson contains errors, simplifies code review by isolating context to single topics, and maintains a clean git history where each commit hash corresponds to exactly one curriculum module in `phases/*/*/`.

### How does the audit script identify lesson directories?

The script in [`scripts/audit_lessons.py`](https://github.com/rohitg00/ai-engineering-from-scratch/blob/main/scripts/audit_lessons.py) filters changed file paths using the pattern `p.startswith("phases/")`, then extracts the first three path components (`Path(p).parts[0:3]`) to identify unique lesson directories. This captures the `phases/<phase_number>/<lesson_name>/` structure and creates a set of modified lessons, asserting that the set contains exactly one element.