AI-Assisted Coding
Back to Daily Workflow with AI

Build 4 — Debug a Tricky Bug with AI

A real debugging session: provide context, narrow the problem, iterate with AI until you find and fix it.

114 minutesProject submission
🎯 Free Guest Mode: You are learning for free. Sign in to save your completion progress and quiz answers.

Assignment Instructions

🎯 Hands-on Portfolio Deliverable: Execute a structured AI-assisted root cause analysis on non-deterministic and logic bugs, refactor the code for testability, and author rock-solid regression tests.


The brief

Practice the structured debug-with-AI workflow on a non-trivial bug. Find the bug, fix it, write a regression test.

Choose your primary bug

Choose one primary bug: either a real bug from your work or open source, or the sample below. Your own bug replaces the sample; it does not need to use aggregate_clicks or its function signature. In addition, complete exercises A, B and C below for either choice.

Sample: click aggregation

This sample uses naive UTC datetimes consistently. Define the last-24-hour window as cutoff < timestamp ≤ now: an event exactly at the cutoff is excluded, an event at now is included, and future events are excluded.

from datetime import datetime, timedelta
from collections import defaultdict

def aggregate_clicks(clicks: list[dict]) -> dict[str, int]:
    cutoff = datetime.utcnow() - timedelta(hours=24)
    counts = defaultdict(int)
    for click in clicks:
        if click['timestamp'] > cutoff:  # BUG: future events are included
            counts[click['url']] += 1
    return dict(counts)

Reproduce with a controlled clock

Save the sample as buggy.py. Run this pytest test against the original function. It should fail because /future is included:

from datetime import datetime
from unittest.mock import patch
from buggy import aggregate_clicks

def test_window_excludes_future_events():
    clicks = [
        {'url': '/inside', 'timestamp': datetime(2026, 5, 27, 10)},
        {'url': '/future', 'timestamp': datetime(2026, 5, 27, 13)},
    ]
    with patch('buggy.datetime') as clock:
        clock.utcnow.return_value = datetime(2026, 5, 27, 12)
        assert aggregate_clicks(clicks) == {'/inside': 1}

The hidden system clock makes the original code hard to test. The missing upper bound is the actual logic bug. An empty result when running these old sample dates today can be correct; it is not, by itself, proof of a bug.

Discuss, fix and test

Ask the AI to trace the input against the stated window. Make the clock controllable, for example with an optional now parameter, and enforce cutoff < click['timestamp'] <= now. Keep existing callers working where practical. Write deterministic tests for an event inside the window, exactly at cutoff, exactly at now, in the future, and older than the window. Use the same timezone convention throughout.

Record the reproduction, root cause, fix, tests, and how AI helped in DEBUG.md. If using your own primary bug, document and test that bug instead; the sample's code and signature are not required.

More debug exercises

Apply the same workflow to:

Exercise A: Off-by-one

def get_page(items: list, page: int, page_size: int = 10) -> list:
    start = page * page_size  # page is zero-based
    end = start + page_size
    return items[start:end + 1]   # bug: extra item

Bug: returns 11 items, not 10.

Exercise B: Wrong operator

def is_admin_or_owner(user, resource) -> bool:
    return user.is_admin or user.id == resource.owner_id and user.is_active
    # bug: precedence; `is_active` only checked on owner, not admin

Bug: admin without is_active still passes.

Exercise C: Edge case

def average(nums: list[float]) -> float:
    return sum(nums) / len(nums)
    # bug: empty list = ZeroDivisionError

Define the desired contract: raise ValueError for an empty list with a clear message; test both empty and nonempty input.

For each: reproduce → discuss with AI → identify → fix → test.

Deliverables

  • The chosen primary bug and each of exercises A, B, and C reproduced and fixed.
  • Regression test per bug.
  • A DEBUG.md documenting:
    • The original bug behavior.
    • Steps to reproduce.
    • Root cause.
    • Fix.
    • How AI helped (or didn't).

What you'll learn

  • Structured debug-with-AI workflow.
  • The importance of reproduction.
  • Identifying root causes vs symptoms.
  • Writing regression tests.
  • When AI debugging shines and when it stumbles.

Stretch

  • Bring 5 real bugs from your work or open-source; debug each with AI.
  • For each: time spent without AI vs with AI estimate.

📊 100-Point Evaluation Rubric

Evaluation DimensionWeightTarget Standard (Pass ≥ 80%)
1. Reproduction & Root Cause Analysis25 ptsClear isolation of non-deterministic behavior (e.g. datetime.utcnow() clock dependency) and logical flaws rather than patching symptoms.
2. Fix Quality & Determinism25 ptsImplemented clean architectural solution (e.g. dependency injection of now timestamp or fixed window parameters) preserving existing callers where practical.
3. Regression Test Fixtures25 ptsDeterministic pytest regression test that locks in expected behavior and prevents regressions regardless of execution environment or clock time.
4. Multi-Bug Analysis & DEBUG.md25 ptsCompleted DEBUG.md covering root cause analysis, fix documentation, and solutions for exercises A, B, and C. A learner-selected primary bug can replace the sample.

📤 Submission Instructions & Guidelines

  1. Deliverable Formats:
    • Option A (Recommended): Upload a single .zip archive containing your fixed Python scripts, pytest regression tests, and DEBUG.md.
    • Option B: Upload your DEBUG.md and paste your GitHub Gist or repo link in the Submission Notes box below.
  2. Pre-Submission Verification:
    • Run pytest to confirm your regression tests pass consistently across multiple runs.
    • Review your DEBUG.md to ensure root cause explanations are clear and complete.
  3. Submit Your Work:
    • Upload your file via the dropzone below and click Submit Assignment.
Checking your access…