Scaffold Week 2 assignment template (mirrors Week 1 pattern)#1
Merged
lassebenni merged 10 commits intomainfrom May 6, 2026
Merged
Scaffold Week 2 assignment template (mirrors Week 1 pattern)#1lassebenni merged 10 commits intomainfrom
lassebenni merged 10 commits intomainfrom
Conversation
Build out the full Week 2 assignment scaffold matching
HackYourFuture/data-assignment-week-1's structure: three tasks,
Codespace devcontainer, GitHub-Actions auto-grader workflow, and a
detailed test.sh with a 4-tier scoring ladder.
Repository layout:
task-1/ Cleaner Pipeline (60 pts)
data/messy_sales.csv 15-row dataset (3 invalid, 12 cleaned)
src/{config,models,transforms,pipeline}.py starter files with TODOs
tests/test_transforms.py 4 test stubs (basic, normalize,
revenue, no-mutation)
output/.gitkeep
.env.example INPUT_PATH + OUTPUT_PATH
requirements.txt python-dotenv + pytest
task-2/AI_DEBUG.md 4-section template (Error / Prompt /
Solution / Reflection) — 20 pts
task-3/.gitkeep students drop azure_proof.png — 20 pts
.hyf/test.sh auto-grader (60+20+20=100, pass=60)
.hyf/README.md auto-grade tool documentation
.github/workflows/grade-assignment.yml delegates to HYF reusable
auto-grade workflow
.devcontainer/devcontainer.json Python 3.11 image, post-create
installs requirements + prints help
README.md student-warning callout, instructor
cohort-template instructions, tasks
table, repo layout, scoring ladder
Auto-grader scoring ladder (Task 1):
10 required files exist (config / models / transforms / pipeline
/ tests / .env.example)
20 pipeline runs without crashing (.env copied from .env.example)
40 output/clean_sales.csv passes structural checks: 12 rows,
lowercased emails, title-cased product names, "Unknown" for
empty categories, revenue + vat columns with correct math
60 code engineering patterns present: @DataClass + __post_init__
in models.py, {**row, ...} spread pattern in transforms.py,
pytest tests/ green
The 40-point cap on the structural-only tier prevents an LLM-generated
5-line script that hardcodes the expected JSON from passing the
top tier without using the chapter's actual patterns.
Verified against a known-passing reference solution
(~/Documents/github/hyf/data-assignment-week-2-test): grader reports
100/100. Bare scaffold with TODOs scores 20/100 (10 files-exist +
10 AI-sections-present + 0 azure-proof) — partial credit ladder
works as designed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts: # .hyf/test.sh
The original scaffold commit (1c12e52) accidentally tracked the local Python venv used for development, leaking 1100+ files into the repo including pip dist-info, site-packages, and the typing_extensions wheel. This commit removes them via 'git rm -r --cached venv/' and extends .gitignore with the standard Python venv patterns: venv/ .venv/ task-*/venv/ task-*/.venv/ Future students who run 'python -m venv venv' inside task-1/ won't accidentally re-commit the venv even if their tooling adds it to staging. Surfaced as a followup on PR #1.
There was a problem hiding this comment.
Pull request overview
Scaffolds the Week 2 Data Track assignment template (clean pipeline refactor), including starter Python modules/data, a student-facing README, and an auto-grader script that scores the three tasks.
Changes:
- Added
task-1/scaffold (config/models/transforms/pipeline stubs), starter dataset, and placeholder pytest tests. - Implemented
.hyf/test.shauto-grader with a 60+20+20 scoring ladder and structural/introspection checks. - Added template repo docs and developer experience helpers (README update,
.gitignorevenv rules, devcontainer config).
Reviewed changes
Copilot reviewed 12 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| task-3/.gitkeep | Keeps task-3/ present in the template repo. |
| task-2/AI_DEBUG.md | Adds the AI debug report template for Task 2. |
| task-1/tests/test_transforms.py | Starter pytest file with TODO test stubs for transform functions. |
| task-1/tests/init.py | Marks tests/ as a package (template scaffolding). |
| task-1/src/transforms.py | Defines the required transform function stubs and constraints (pure/no I/O/no mutation). |
| task-1/src/pipeline.py | Adds the pipeline orchestrator stub and describes I/O boundaries. |
| task-1/src/models.py | Adds the Transaction dataclass TODO scaffold and validation requirements. |
| task-1/src/config.py | Adds dotenv-based config loader scaffold with required-variable helper TODO. |
| task-1/src/init.py | Marks src/ as a package for python -m src.pipeline. |
| task-1/requirements.txt | Adds minimal Python dependencies (python-dotenv, pytest). |
| task-1/output/.gitkeep | Keeps output/ directory present for generated CSV output. |
| task-1/data/messy_sales.csv | Adds the intentionally messy input dataset used by the assignment/grader. |
| task-1/.env.example | Adds example env vars for input/output paths. |
| README.md | Replaces placeholder README with Week 2 template instructions and scoring ladder explanation. |
| .hyf/test.sh | Implements the grading script that runs the pipeline, validates output, and performs code-structure introspection. |
| .gitignore | Adds ignores for Python virtual environments (including per-task venvs). |
| .devcontainer/devcontainer.json | Adds a Codespaces/devcontainer configuration and dependency install command. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…rminism) - task-2/AI_DEBUG.md: rename header from 'Week 2 Task 6' to 'Task 2'. The 'Task 6' came from the curriculum chapter's task numbering (where AI Debug is task 6 of 7); inside this standalone scaffold repo the directory is task-2/ and that's all a student sees. - .hyf/test.sh L103: fix the VAT rounding comment. Said '419.9958 rounded to 419.996' — that's 3-decimal rounding, but the assignment teaches 2-decimal rounding (round(x, 2) -> 420.00). The 0.01 tolerance below absorbed both, so functionality unaffected, but the comment was teaching the wrong precision to anyone reading the grader. - .hyf/test.sh L58-69: stop reading the student's .env. The grader was copying .env.example -> .env only if .env was missing, which made grading non-deterministic if a student had pointed INPUT_PATH / OUTPUT_PATH elsewhere during their own debugging. Now the grader passes the canonical paths inline via 'env INPUT_PATH=... OUTPUT_PATH=...' on the python invocation. Student's .env is neither read nor modified. Verified: empty scaffold still scores 20/100 baseline after the change.
…ellipsis, README) - .hyf/test.sh L102: actually apply the rounding-comment fix this time. Round 1 claimed to fix it but the Edit failed silently and only the .env change made it into a0403c3. Now reads '420.00 at 2 decimals; the 0.01 tolerance below absorbs either rounding precision'. - task-1/src/config.py L29: import-path TODO said 'from config import INPUT_PATH' but pipeline.py uses 'from .config import INPUT_PATH' (relative, because the pipeline runs as python -m src.pipeline). Updated TODO comment to show the relative form so students don't paste the wrong import. - task-1/src/pipeline.py L53-57: replaced the bare '...' Ellipsis placeholder with 'data' (the actual cleaned-data variable from the lines above). The Ellipsis would raise TypeError: 'ellipsis' object is not iterable with no obvious explanation for a Week 2 student. The casting TODO is now a regular code comment outside the comprehension. - README.md L82: stale grading description after a0403c3 (which stopped reading .env). Now describes what the grader actually does: injects INPUT_PATH/OUTPUT_PATH inline. Two of these (rounding-doc + README) were follow-ups to my own incomplete round-1 fix.
…nostics)
- task-1/src/transforms.py: strip the literal '{**row, ...}' from
module + clean_fields docstrings. The grader's introspection check
(grep -cE '\{\*\*' transforms.py) was always >0 because of the
scaffold docstring, so the 60-point engineered-code tier passed
even for purely-mutating implementations. Replaced with plain-English
prose ('return new dicts instead of mutating the input rows'); the
chapter teaches the {**row, ...} pattern, the grader now actually
verifies the student used it inside function bodies.
Verified: grep -cE '\{\*\*' transforms.py == 0 on the empty scaffold.
- .hyf/test.sh L22-23: stale ladder doc-comment after a0403c3.
Updated from 'after we copy .env from .env.example for the run'
to 'the grader injects INPUT_PATH/OUTPUT_PATH inline; no .env touched'.
Same stale-doc class as the round-2 README comment in 3492620.
- .hyf/test.sh L61: drop '2>/dev/null' on pip install + add a WARN
when install exits non-zero. Keeps the '|| true' fallback so the
grader doesn't hard-fail in environments where pip is locked, but
surfaces the real cause when 'pipeline failed to run' is actually
ModuleNotFoundError. Verified by running on a system without pip:
'WARN: pip install failed; pipeline may fail with ModuleNotFoundError'.
…marker) - README.md L81: add .env.example to the 10/60 required-files list. The grader's required_files array in .hyf/test.sh checks for it; README was out of sync. - task-1/src/config.py L16: drop the 'TODO 1' marker on the line that already calls load_dotenv(). A TODO marker on already-implemented code is a contradictory signal for students doing TODO-driven work. Replaced with a plain comment that explains why the call is there and points back at step 1 in the docstring (which still enumerates the conceptual flow). TODO 2 and TODO 3 stay — those mark the parts the student actually fills in.
…ut tree)
- .hyf/test.sh: capture pipeline stderr + structural-check stderr to
tempfiles instead of /dev/null. On failure, append the last 3 lines
to task1_msg so a student running the grader sees exactly which line
and which exception fired without having to re-run the pipeline
locally.
Verified by running on the empty scaffold (pipeline.py raises
NotImplementedError):
Before: 'pipeline failed to run' (opaque)
After: 'pipeline failed to run: File ".../pipeline.py", line 35,
in read_csv raise NotImplementedError NotImplementedError'
README L74's claim ('see exactly which check failed and why') is now
truthful. (Round-5 comment #2 auto-resolves.)
- README.md L48: layout tree showed
output/
clean_sales.csv # your pipeline writes here
as if the file is committed. Reality: only output/.gitkeep is
tracked; clean_sales.csv is generated at runtime. Replaced with a
single line annotating the directory:
output/ # your pipeline writes clean_sales.csv here (gitignored)
so a student browsing the repo on GitHub doesn't assume the scaffold
is broken when they don't see the file.
PR #1 round-6 review: bare 'pip install' is interpreter-ambiguous on multi-Python systems (macOS Homebrew, Linux distros with multiple py versions). The grader and pipeline all run via 'python3', so 'pip' linked to a different interpreter would install deps into the wrong site-packages and the pipeline would fail with ModuleNotFoundError even after a 'successful' install. Replaced 4 bare 'pip install' invocations with 'python3 -m pip install': - .hyf/test.sh L61: grader's requirements install - .devcontainer/devcontainer.json L12: postCreateCommand - README.md L66: setup-instructions install command - README.md L49: layout-tree comment Round-3 added a WARN diagnostic for pip install failures; this round prevents the underlying class of failure for environments where pip exists but targets the wrong interpreter.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Initial scaffold for the Week 2 assignment template (MessyCorp pipeline refactor). Mirrors the Week 1 assignment-template pattern and is wired to the curriculum at
Data Track/Week 2/week_2__11_assignment.md(PR #144 againstlassebenni/hyf-datatrack).Scope
task-1/: refactor scaffold:src/{config,models,transforms,pipeline}.py+tests/test_transforms.py+requirements.txt+.env.example+data/messy_sales.csv(15 rows of intentionally messy sales data).task-2/: AI debug report template (AI_DEBUG.md).task-3/: Azure Resource Group proof screenshot slot..hyf/test.sh: auto-grader with a 60+20+20=100 ladder, passing threshold 60. Each task climbs a documented ladder (file-presence → runnable → output-correct → code-introspection-passes) so a script that hardcodes the expected output cannot pass the introspection tier..devcontainer/+.github/: Codespaces config and a workflow that runs the grader on every push and posts the score as a PR comment.README.md: student-facing instructions.Verified locally
Empty scaffold:
Filled with the canonical Workshop 2 solution from the curriculum repo (
Data Track/Week 2/assets/exercises/workshop_2/solution/):The ladder behaves as documented.
Known followups (not in this PR)
venv/directory inherited from the original scaffold commit; should be removed and added to.gitignorein a follow-up cleanup commit.10/100baseline; actual is20/100. Will update there.Test plan
🤖 Generated with Claude Code