"The compiler does not care how confident the autocomplete looked. Your tests, your types, and your code review are the only ground truth."
— Common distillation of senior-engineering mentoring (paraphrased)
Duration: 6–8 hours · Difficulty: Intermediate · Prerequisites: Basic programming in one language (this module uses Python examples), comfort with files and folders, and Git at the level of clone, commit, branch, diff. Install VS Code or Cursor; access to GitHub Copilot (or institution-approved equivalent) and optionally Claude (web or desktop) per your syllabus and license.
Learning Objectives
By the end of this module, you will be able to:
- Configure IDE-integrated assistants (GitHub Copilot, Cursor, JetBrains AI) for navigation, boilerplate, tests, and debugging without abdicating understanding.
- Apply a read–predict–verify loop for every non-trivial suggestion: trace data flow, check edge cases, run tests.
- Author prompt patterns for code: spec-first, test-first, small-scope refactors, debugging traces, and “explain this diff” requests suited to coursework and internships.
- Compare Copilot, Cursor, and Claude-style assistants across context window, repo awareness, and risk profile—and choose the right tool for each task.
- Explain common failure modes: hallucinated APIs, subtle logic bugs, security anti-patterns, dependency drift, and license ambiguity in generated snippets.
- Use Git to isolate experiments, review AI-generated diffs line-by-line, and bisect when something breaks after a broad “agent” edit.
- Conduct AI-assisted code review: request structured feedback, then validate every claim with execution and static analysis.
- Communicate your workflow in a README suitable for a TA, open-source contributor, or internship mentor, including AI disclosure and ethical use of third-party code.
Concept 1: Copilots as Accelerators, Not Oracles
Modern coding assistants predict likely continuations from context: open files, cursor position, linter diagnostics, and sometimes repository-wide indexing (Cursor, Copilot Workspace-style features). They are trained on public code; they do not know your private assignment spec, your runtime environment, or your university’s data-handling rules unless you state them.
Productive mental model: the assistant is a pair programmer who types fast but sometimes confidently wrong. Your job is to supply intent, constraints, and verification.
| Mindset | Risk |
|---|---|
| “It compiled, so it’s fine.” | Logic bugs, wrong library version, silent data loss. |
| “The model used fancy syntax.” | Unreadable code you cannot defend in office hours. |
| “I’ll paste my whole repo into chat.” | Secret leakage, license issues, policy violations. |
Real-world example: A CS student uses Copilot to implement a CSV parser for a sociology group project. The suggestion uses pandas.read_csv with default dtypes; student IDs lose leading zeros. Grades import wrong. Verify with sample rows that mirror real data quirks (leading zeros, mixed encodings, stray commas in text fields).
Comparison: Where each tool shines (high level)
| Dimension | GitHub Copilot (IDE) | Cursor | Claude (chat / API / integrations) |
|---|---|---|---|
| Primary win | Fast inline completions in familiar editors | Repo-wide context, multi-file edits, “agent” flows | Long context, careful explanations, refactoring dialogue |
| Typical risk | Accepting slick one-liners without tests | Broad refactors that break imports globally | Over-trusting narrative explanations of code you have not run |
| Best for | Boilerplate, tests from signatures, docstrings | “Change pattern X across these files” | Architecture discussion, long file review, policy-safe prompting when allowed |
| Verify with | pytest, ruff, local run | Same + smaller scoped tasks | Same; paste minimal excerpts if policy allows |
Vendor features change frequently—treat this table as a thinking scaffold, not a product spec.
Concept 2: GitHub Copilot — Deep Dive
What Copilot sees: Usually the current file, nearby tabs, and sometimes related files—depending on editor integration and your settings. It does not magically know your autograder; put assignment constraints in comments or chat when permitted.
Inline completions: Tab to accept; partial accepts in many setups. Practice: before you hit Tab, say aloud the next line you expect; if the suggestion diverges, slow down.
Copilot Chat (VS Code): Useful for “explain this error,” “generate tests for this function,” “rewrite with type hints.” Risk: chat may encourage pasting large blobs—redact secrets and personal data.
Commit messages and PR text: Copilot can draft summaries from git diff. You must ensure the message matches what you actually changed—misleading messages erode trust in team projects.
Licensing and training: Read your institution’s agreement and GitHub’s current documentation on data retention and code suggestions. Policies evolve; re-check each term.
Configuration habits that pay off:
- Enable format-on-save and a linter so bad suggestions get visible immediately.
- Pin Python version in
pyproject.tomlor.python-versionso suggestions match your environment. - Use
.github/copilot-instructions.mdor editor-level guidance (if available) for team style: “prefer explicit loops,” “noeval,” etc.
Concept 3: Cursor — Repo-Aware Assistance
Cursor emphasizes whole-repository context and agent flows (multi-step edits across files). Useful for: “add error handling across these three modules,” “generate tests matching this interface,” “rename this concept consistently.”
Composer / multi-file edits: Treat like a junior developer with a wide paintbrush. Always:
- Work on a branch.
- Run tests after each coherent chunk of changes.
- Review the full diff before commit—agent flows can “fix” one file while breaking another.
@ symbols and context: Learn how your build of Cursor attaches files, folders, and docs. Prefer narrow folders (e.g., src/parser/) over the entire monorepo for first attempts.
Rules files: Project .cursorrules or team rules can encode style and forbidden patterns. Align them with course style guides so the assistant nudges toward gradable code.
Real-world scenario: Team member uses Cursor to “modernize” imports. CI fails on the campus cluster with older Python. Lock environment in pyproject.toml or environment.yml and run CI locally before push.
Concept 4: Claude for Coding (and When to Prefer It)
Claude (Anthropic) is often used via browser chat, API, or integrations. Strengths:
- Long-context sessions for reading a large module you paste in slices (respect copyright and syllabus).
- Explanations that decompose logic step-by-step—useful when learning algorithms.
- Refactoring dialogue when you describe constraints in natural language.
Cautions:
- Same hallucination risks as any LLM for library APIs—verify against docs.
- Paste discipline: Never upload confidential lab code, student PII, or proprietary internship code without written permission.
- For graded work, follow AI disclosure rules; some courses allow IDE tools but forbid external chat—compliance first.
Sample prompt (spec-first, Claude-friendly):
Role: coding tutor constrained to Python 3.11 stdlib only.
Task: Implement merge_sorted(a: list[int], b: list[int]) -> list[int]
Requirements: O(n) time, O(n) extra space, no imports.
Output: function + 3 doctest examples in docstring. No prose outside the code block.Expected shape of a good response: A single code block with def merge_sorted and doctests you can copy into a .py file and run with python -m doctest file.py.
Concept 5: The Read–Predict–Verify Loop
This loop is the professional backbone of working with any assistant.
- Read the problem and existing code until you can state invariants (what must always be true) and inputs/outputs.
- Predict what a good change would look like before you accept a suggestion—shape of function, edge cases.
- Verify with execution: unit tests,
pytest,mypy, print debugging, minimal repro scripts. - Review the diff line-by-line; reject cleverness you cannot explain to a TA in five sentences.
Table: Verification tools by ecosystem (examples)
| Ecosystem | Fast checks |
|---|---|
| Python | pytest, ruff, mypy |
| JavaScript/TS | eslint, tsc, jest |
| Java | javac, JUnit, SpotBugs (optional) |
| C/C++ | -Wall, Valgrind or sanitizers |
Real-world scenario (internship): You accept a snippet that calls requests.get without timeout=. In production, hung connections freeze workers. Always set timeouts on network calls; add that to your mental checklist before accepting HTTP code.
Pro Tips — IDE copilots
- Comment-driven completion: Write a 2-line docstring with inputs, outputs, and errors before asking for implementation—Copilot uses comments as strong priors.
- Shrink the blast radius: After any agent edit, run
git diff --stat—if more than N files changed, revert and retry with a narrower prompt. - Pin the “source of truth”: Link the assistant to
README.mdorCONTRIBUTING.mdwhen your course publishes style rules; reduces drift between teammates. - Rubber-duck with tests: If you cannot write a failing test, you do not yet understand the bug—avoid asking the model to “fix everything.”
Common mistakes — Module 04
- Accepting imports you have not installed—especially optional extras (
[dev],gpu) that break CI. - Blind trust of type hints generated without
mypy; annotations can lie while code runs. - Mega-prompting entire assignments into chat instead of incremental functions with tests between steps.
- Forgetting license headers when mixing AI snippets with third-party Stack Overflow–style code in one file.
Comparison table: When to use inline completion vs. chat vs. agent
| Situation | Inline (Tab) | Chat / Composer | External long chat |
|---|---|---|---|
| Boilerplate / docstrings | Strong | Overkill | OK if policy allows |
| Rename across files | Weak | Strong | Paste paths carefully |
| Debug stack trace | OK for hints | Strong with @file | Strong for long logs |
| Architecture debate | Weak | Medium | Often strongest |
| Exam-style restrictions | Check syllabus | Often banned | Often banned |
Hands-On A: Prompt Patterns That Survive Review
Vague prompts yield vague code. Use structure.
A.1 Spec-first pattern
You are helping with a homework module. Constraints:
- Language: Python 3.11
- No external deps beyond stdlib
- Function signature must be: def normalize_email(s: str) -> str:
Behavior: strip, lowercase, reject strings without exactly one '@' by raising ValueError.
Do not write main(); provide the function and docstring only.A.2 Test-first (recommended)
You write the signature and failing tests; the assistant fills implementation you then refine.
[object Object],
,[object Object], ,[object Object],(,[object Object],) -> ,[object Object],:
,[object Object],
,[object Object], NotImplementedError[object Object],
,[object Object], pytest
,[object Object], gpa ,[object Object], gpa_from_letter_grades
,[object Object], ,[object Object],():
,[object Object], gpa_from_letter_grades([,[object Object],, ,[object Object],]) == pytest.approx(,[object Object],)
,[object Object], ,[object Object],():
,[object Object], gpa_from_letter_grades([,[object Object],, ,[object Object],]) > ,[object Object],
,[object Object], ,[object Object],():
,[object Object], pytest.raises(ValueError):
gpa_from_letter_grades([])
,[object Object], ,[object Object],():
,[object Object], pytest.raises(ValueError):
gpa_from_letter_grades([,[object Object],, ,[object Object],])Walkthrough: Ask your assistant: “Implement gpa_from_letter_grades to pass these tests; use explicit mapping dict.” Then run pytest -v.
Expected output (excerpt): test_gpa.py::test_simple PASSED … all green. If one fails, read the failure, fix your understanding first, then adjust code.
A.3 Refactor prompts
- “Extract validation into
_parse_grade(token: str) -> floatwithout changing behavior; show diff only forgpa.py.” - “Rename variable
df1toenrollment_by_termacross this file; no logic changes.”
A.4 Debugging with AI
Paste stack trace + minimal file excerpt (not entire assignment).
Hypothesis: off-by-one in loop over CSV rows.
Here is the traceback: [paste]
Here is the function read_rows (40 lines max): [paste]
Suggest two candidate fixes. I will run tests before choosing.Expected assistant behavior: Points to boundary conditions (header row, empty file, final newline). You run pytest on each suggested fix—do not merge both.
A.5 Code review with AI
Review this diff for: (1) logic bugs, (2) security issues, (3) readability.
For each issue, cite file:function and suggest a concrete patch.
If uncertain, say "verify with test" instead of guessing.Mandatory next step: For every claimed bug, either write a failing test that proves it or reject the claim. Models false-positive on review like everyone else.
A.6 “Explain this diff” for learning
After merging AI help:
Explain in plain English what changed and list one edge case I should still test.Use the answer as a comment block or README note if your course encourages learning journals.
Hands-On B: Property-Style Test (Optional Stretch)
Install: pip install hypothesis
[object Object], hypothesis ,[object Object], given, strategies ,[object Object], st
,[object Object], gpa ,[object Object], gpa_from_letter_grades
VALID = st.sampled_from([,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],])
,[object Object],
,[object Object], ,[object Object],(,[object Object],):
g = gpa_from_letter_grades(grades)
,[object Object], ,[object Object], <= g <= ,[object Object],Expected outcome: Test runs; if it fails, you have discovered a normalization bug that unit tests missed.
Hands-On D: Building a Small Project with AI Assistance (End-to-End)
Scenario: A “study hours logger” CLI that appends dated entries to a CSV.
- You write
test_logger.pywith tests for: create file if missing, append row, reject negative hours, reject future dates. - AI implements
logger.pyto pass tests; you reject any use ofevalor shell string formatting with user input. - You add
README.mdwith install, usage, and AI disclosure. - Verify:
pytest -vand manual runpython logger.py add --hours 2 --note "reading".
Expected output (pytest): all tests passed. Expected CSV row: consistent column order and UTF-8 encoding.
Reflection prompt: Which step would have taken longest without AI? Where did AI steer you wrong?
Hands-On C: Git Workflow for AI Collaboration
git checkout -b feature/ai-assisted-refactor
,[object Object],
pytest
git add -p
git commit -m ,[object Object],When things break: git bisect between last good commit and HEAD finds the offending change—useful after a large agentic edit.
Hands-On E: Python — ast guardrail (reject eval / exec in suggestions)
When reviewing AI-generated code programmatically (or building a course autograder), you can scan the AST for dangerous calls. This does not replace human review but catches obvious foot-guns.
[object Object], ast
,[object Object], ,[object Object],(ast.NodeVisitor):
,[object Object], ,[object Object],(,[object Object],) -> ,[object Object],:
,[object Object],.forbidden: ,[object Object],[,[object Object],] = []
,[object Object], ,[object Object],(,[object Object],) -> ,[object Object],:
,[object Object], ,[object Object],(node.func, ast.Name) ,[object Object], node.func.,[object Object], ,[object Object], {,[object Object],, ,[object Object],}:
,[object Object],.forbidden.append(node.func.,[object Object],)
,[object Object],.generic_visit(node)
,[object Object], ,[object Object],(,[object Object],) -> ,[object Object],[,[object Object],]:
tree = ast.parse(code)
v = ForbiddenCallVisitor()
v.visit(tree)
,[object Object], v.forbidden
sample = ,[object Object],
,[object Object],(,[object Object],, scan_source(sample))
,[object Object],Expected use: Run on pasted snippets before merge; extend the visitor with subprocess, os.system, etc., if your threat model requires it.
Hands-On F: Python — Minimal diff summary for study logs
After each coding session, a tiny script helps you document what changed for AI-disclosure appendices (pairs with Module 01 logging).
[object Object], subprocess
,[object Object], sys
,[object Object], ,[object Object],() -> ,[object Object],:
,[object Object], subprocess.check_output(
[,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],, ,[object Object],],
text=,[object Object],,
stderr=subprocess.STDOUT,
)
,[object Object], __name__ == ,[object Object],:
,[object Object],:
,[object Object],(last_commit_stat())
,[object Object], subprocess.CalledProcessError ,[object Object], e:
,[object Object],(,[object Object],, e.output, file=sys.stderr)
sys.exit(,[object Object],)Expected output: git diff --stat lines suitable to paste into a lab notebook “session summary.”
Security, Ethics, and Academic Honesty
Secrets and .env
[object Object], os
api_key = os.environ.get(,[object Object],)
,[object Object], ,[object Object], api_key:
,[object Object], RuntimeError(,[object Object],)Add .env to .gitignore. Check whether chat content is retained or used for training (vendor docs change—re-read each term).
Intellectual property and licenses
Generated code may resemble training data snippets. For commercial release or patent-sensitive work, run legal review. Prefer permissive dependencies and document provenance.
Security anti-patterns to reject
| Bad pattern | Why |
|---|---|
eval(user_input) | Remote code execution |
| SQL string concat with user data | Injection |
shell=True with untrusted strings | Command injection |
| Disabling TLS verification | Man-in-the-middle risk |
Code review checklist (every AI-assisted PR)
- I can explain each new function’s preconditions and postconditions.
- Tests cover happy path, empty input, and one weird input.
- No new dependencies without README note and license check.
- Logging does not print PII or tokens.
OWASP awareness
If your project has login forms or cookies, skim OWASP Top 10. AI often generates demo auth that is not production-safe—label it in README.
Try This Now
- Tab discipline: Open a small Python file. For five completions, predict the suggestion before it appears; log how many you would have accepted blindly vs after prediction.
- Minimal repro: Take one failing test. Strip the production code to the smallest snippet that still fails; use AI only after you can state the failure in one sentence.
- Tool rotation: Solve the same 20-line task with Copilot inline only, then with Cursor chat only, then with Claude—compare time-to-green and number of bad suggestions accepted.
- Review drill: Paste a diff you wrote (not AI) and ask the model to find bugs—fact-check every claim with a test or
grep. - Disclosure draft: Write a 5-sentence AI disclosure paragraph suitable for your course’s honor code; include what you verified manually.
Discussion Prompts / Reflection Questions
- When is accepting AI-generated code more risky than writing code slowly by hand—and why?
- How would you explain to a non-technical stakeholder why “it passed the autograder once” is insufficient for production?
- If your team disagrees on whether AI assistance is allowed for a class project, what process would you propose to align with syllabus and fairness?
- Where should long-term learning live—in your head, in tests, in docs, or in the model—and how do those options trade off?
Practice Exercises
Exercise 1 — Bug garden (20 pts)
Start from intentionally buggy code. Use AI to propose fixes; you select and justify the correct fix in comments or 150 words. Rubric: correct fix (8), justification cites behavior/tests (8), honesty about AI role (4).
Exercise 2 — API hallucination drill (20 pts)
Ask for sample code using a library you know well (e.g., pathlib). Compare against official docs; list every discrepancy. Rubric: completeness (10), accuracy (10).
Exercise 3 — Diff review (20 pts)
Generate a 30-line patch with AI. Without running, predict behavior on three inputs; then run and reconcile mismatches in a short log. Rubric: predictions (8), reconciliation (8), insight (4).
Exercise 4 — Explainer (20 pts)
After accepting help, write five sentences for a non-programmer TA: what changed, why, one residual risk. Rubric: clarity (10), technical correctness (10).
Exercise 5 — No-assistant hour (20 pts)
Implement a small function without tools; repeat with assistance. Reflect in 200 words on time, correctness, and depth of understanding. Rubric: reflection depth (12), specific examples (8).
Mini-Project
CLI Utility with README, Tests, and AI Disclosure
Build a small command-line tool in Python (or your course language) that solves a real campus-adjacent problem you can ethically access: parse a schedule export, summarize club expense CSV, normalize survey codes, or validate bibliography snippets. Avoid identifiable private data about other students.
Requirements
- CLI with
argparse(or equivalent): at least one subcommand or two flags. - ≥8 automated tests including edge cases (empty file, malformed row, wrong encoding).
- Clear error messages for user-fixable mistakes (file not found, bad column name).
Documentation
- README.md: purpose, install (
venv,pip install -r requirements.txt), usage examples, limitations, AI disclosure (which tools, which files/commits, how you verified).
Process
- Git history: ≥5 meaningful commits; avoid single “dump” commits.
- Self-review paragraph: Describe one AI-generated hunk you rejected and why.
Approach (suggested)
- Spec in plain English → 2. tests → 3. minimal implementation → 4. refactor with AI in small steps → 5. README + disclosure.
Mini-project extensions (depth)
- Error catalog: Document three user errors your CLI catches with helpful messages (file not found, bad encoding, wrong column)—and one error you deliberately do not catch with a rationale.
- Performance note: If your tool reads large CSVs, time one run on a synthetic 10k-row file; state Big-O intuition in plain language (O(n) scan vs. accidental O(n²) nested loops).
- Pair interview prep: Write five flash-card answers explaining your design choices without opening the repo—mirrors internship code walkthroughs.
Deliverables
- Source tree with tests passing in clean venv.
- README + disclosure.
- Optional:
pre-commitwithruff;pyproject.tomlentry point.
Evaluation hint: TAs grade whether you can explain the tool under questions, not line count. Prefer boring explicit logic over clever one-liners unless you fully own them.
Key Takeaways
- Tests and types are your ground truth—not model confidence or fluent comments.
- Small commits and hunk staging make AI collaboration auditable and reversible.
- Read–predict–verify scales from first-year labs to industry code review.
- Prompt with constraints (language version, deps, error behavior) to reduce garbage suggestions.
- Copilot, Cursor, and Claude differ in context and workflow—match tool to task, then verify the same way.
- Security and policy (secrets, FERPA-adjacent data, honor code) limit what you paste into cloud assistants.
- The goal is understanding that survives a whiteboard interview or a senior engineer’s “why this line?”
Resources
- GitHub Copilot documentation: https://docs.github.com/en/copilot
- Cursor documentation: https://cursor.com/docs
- Anthropic Claude documentation: https://docs.anthropic.com/
- Python
typing: https://docs.python.org/3/library/typing.html - pytest: https://docs.pytest.org/
- OWASP Top 10: https://owasp.org/www-project-top-ten/