Skip to content

Scaffold Week 2 assignment template (mirrors Week 1 pattern)#1

Merged
lassebenni merged 10 commits intomainfrom
feat/initial-scaffold
May 6, 2026
Merged

Scaffold Week 2 assignment template (mirrors Week 1 pattern)#1
lassebenni merged 10 commits intomainfrom
feat/initial-scaffold

Conversation

@lassebenni
Copy link
Copy Markdown
Collaborator

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 against lassebenni/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:

Task 1 (Cleaner Pipeline): 10/60 — files exist but pipeline failed to run
Task 2 (AI Debug Report):  10/20 — all sections present but file looks too short to be filled in
Task 3 (Azure Proof):       0/20 — missing task-3/azure_proof.png|jpg|jpeg
Total: 20/100 — pass=false

Filled with the canonical Workshop 2 solution from the curriculum repo (Data Track/Week 2/assets/exercises/workshop_2/solution/):

Task 1 (Cleaner Pipeline): 60/60 — output and code structure both pass; tests green
Task 2 (AI Debug Report):  10/20 — all sections present but file looks too short to be filled in
Task 3 (Azure Proof):       0/20 — missing task-3/azure_proof.png|jpg|jpeg
Total: 70/100 — pass=true (passing threshold: 60)

The ladder behaves as documented.

Known followups (not in this PR)

  • The branch tracks a venv/ directory inherited from the original scaffold commit; should be removed and added to .gitignore in a follow-up cleanup commit.
  • Slide deck in PR #144 (curriculum repo) advertises a 10/100 baseline; actual is 20/100. Will update there.

Test plan

  • Empty scaffold scores 20/100 on local grader run
  • Filled scaffold scores 70/100 (proves the 60+20 = pass path)
  • Full submission with task-3 screenshot scores 100/100
  • Auto-grader workflow runs on a fork and posts score as a PR comment

🤖 Generated with Claude Code

lassebenni and others added 3 commits May 5, 2026 15:52
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>
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.
@lassebenni lassebenni requested a review from Copilot May 6, 2026 08:56
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.sh auto-grader with a 60+20+20 scoring ladder and structural/introspection checks.
  • Added template repo docs and developer experience helpers (README update, .gitignore venv 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.

Comment thread task-2/AI_DEBUG.md Outdated
Comment thread .hyf/test.sh Outdated
Comment thread .hyf/test.sh Outdated
…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.

This comment was marked as outdated.

…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.

This comment was marked as outdated.

…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'.

This comment was marked as outdated.

…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.

This comment was marked as outdated.

…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.

This comment was marked as outdated.

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.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 17 changed files in this pull request and generated 2 comments.

Comment thread README.md Outdated
Comment thread .hyf/test.sh
Grader accepts azure_proof.png|.jpg|.jpeg, README only mentioned .png.
Students saving from macOS Preview (defaults to JPEG) might convert
unnecessarily or assume their submission won't pass.

PR #1 round-7 review comment #1.
@lassebenni lassebenni merged commit b078628 into main May 6, 2026
@lassebenni lassebenni deleted the feat/initial-scaffold branch May 6, 2026 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants