Skip to content

Commit 0acd0cf

Browse files
committed
Merge remote-tracking branch 'origin/dev' into dev
2 parents f527c23 + d5c91ac commit 0acd0cf

19 files changed

Lines changed: 344 additions & 91 deletions

File tree

.codespell-ignore-words.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ solated
7878
pre-select
7979
Pre-select
8080
pre-selected
81+
pre-selecting
82+
re-using
8183
non-useful
8284
# Truncated words in JSON stats (e.g. "Paged KV cach…" for cache)
8385
cach

.gitattributes

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# =============================================================================
2+
# .gitattributes — going-forward Git LFS tracking and text/binary handling
3+
# =============================================================================
4+
#
5+
# IMPORTANT: this file affects ONLY future `git add` operations. Existing
6+
# blobs in history are NOT migrated by these patterns. A separate, coordinated
7+
# `git lfs migrate import` (Phase 2) is required to actually relocate the
8+
# ~2 GB of binaries already in `.git`. See PR #(this PR) and issues #1393,
9+
# #1175 for the migration plan.
10+
#
11+
# `.gitignore` takes precedence over LFS tracking — if a file is ignored
12+
# (e.g., `.gitignore` exempts callout-icon PDFs from the global *.pdf rule),
13+
# `.gitattributes` LFS tracking will only apply if the file is actually being
14+
# staged.
15+
16+
# -----------------------------------------------------------------------------
17+
# Distribution / publish artefacts (large, infrequently changing, binary)
18+
# -----------------------------------------------------------------------------
19+
# EPUB: zero currently tracked in HEAD; ~952 MB across 15 historical versions
20+
# in `assets/downloads/Machine-Learning-Systems.epub`. Mark for LFS so any
21+
# future re-add does not bloat .git.
22+
*.epub filter=lfs diff=lfs merge=lfs -text
23+
24+
# PDF: covers TinyTorch-Guide.pdf, 00_tinytorch.pdf, distribution PDFs.
25+
# Note: `.gitignore` excludes most PDFs by default but explicitly allows
26+
# callout-icon PDFs, mlsysim docs, paper figures, etc. Those exempted PDFs
27+
# WILL be LFS-tracked under this pattern when newly added — that's the
28+
# intended behaviour: small icon PDFs are still small as LFS pointers, and
29+
# they are infrequently changed.
30+
*.pdf filter=lfs diff=lfs merge=lfs -text
31+
32+
# -----------------------------------------------------------------------------
33+
# Audio / video (always binary, never deltas well)
34+
# -----------------------------------------------------------------------------
35+
# Two MP3 podcasts are currently tracked (~16 MB combined). Multiple sites
36+
# (book quarto, socratiQ, kits) may add more in future.
37+
*.mp3 filter=lfs diff=lfs merge=lfs -text
38+
*.wav filter=lfs diff=lfs merge=lfs -text
39+
*.m4a filter=lfs diff=lfs merge=lfs -text
40+
*.mp4 filter=lfs diff=lfs merge=lfs -text
41+
*.mov filter=lfs diff=lfs merge=lfs -text
42+
*.webm filter=lfs diff=lfs merge=lfs -text
43+
44+
# -----------------------------------------------------------------------------
45+
# Bundled JS / WASM artefacts (when ever tracked)
46+
# -----------------------------------------------------------------------------
47+
# These are typically build outputs and SHOULD be ignored via .gitignore
48+
# rather than tracked (see `book/quarto/tools/scripts/socratiQ/bundle.js`,
49+
# the historical `scripts/ai_menu/dist/bundle.js`, and the Next.js
50+
# `staffml/_next/static/chunks/*.js` blobs). However, if a bundle ever does
51+
# need to be tracked (e.g., a vendored externally-published artefact),
52+
# treat it as binary so we don't burn diff cycles.
53+
*.wasm filter=lfs diff=lfs merge=lfs -text
54+
55+
# -----------------------------------------------------------------------------
56+
# NOT added to LFS (uncertainty / mixed-size patterns) — defer to VJ
57+
# -----------------------------------------------------------------------------
58+
# *.png — repo mixes 1-5 MB cover art / kit photos with thousands of small
59+
# icon PNGs. A blanket pattern would LFS-track the small ones too.
60+
# Recommend either path-scoped patterns
61+
# (e.g. `book/quarto/assets/images/covers/**/*.png filter=lfs ...`)
62+
# or rasterizing big PNGs to a single canonical location first.
63+
# *.jpg / *.jpeg / *.gif — same mixed-size issue. The single biggest GIF is
64+
# `book/quarto/contents/vol1/introduction/images/gif/_alphafold.gif`
65+
# at 3 MB; most others are small.
66+
# *.json — `corpus.json`, `corpus-summary.json`, `search.json` are big but
67+
# they are build artefacts and already in `.gitignore`. JSON in
68+
# general should NOT be LFS-tracked (it's text and diffs well).
69+
70+
# -----------------------------------------------------------------------------
71+
# Text-handling normalization
72+
# -----------------------------------------------------------------------------
73+
# Tell git to auto-normalize line endings on text files. Binary patterns
74+
# above already opt out via `-text`.
75+
* text=auto eol=lf
76+
77+
# Shell scripts and Makefiles must keep LF on Windows checkouts.
78+
*.sh text eol=lf
79+
Makefile text eol=lf
80+
81+
# Avoid CRLF translation for Windows-native batch files.
82+
*.bat text eol=crlf
83+
*.cmd text eol=crlf

.gitignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,3 +342,22 @@ interviews/paper/svg_structure.txt
342342
# Pre-commit / CI workflows generate it on demand; not tracked in repo.
343343
interviews/vault/corpus.json
344344
interviews/staffml/src/data/corpus.json
345+
346+
# SocratiQ bundle — build artefact produced by `socratiq/` Vite build
347+
# (`npm --prefix socratiq run build:vite`), which copies the output into
348+
# `book/quarto/tools/scripts/socratiQ/bundle.js`. The mirror at
349+
# `book/tools/scripts/socratiQ/bundle.js` is a symlink to that file. The
350+
# bundle is ~7 MB and has accumulated ~57 MB across 7 historical versions.
351+
# Going forward, the bundle should be regenerated rather than re-committed.
352+
# (This rule does NOT untrack the existing tracked bundle.js — that cleanup
353+
# is a separate, coordinated change. It only stops *new* drops from being
354+
# added by accident.)
355+
book/quarto/tools/scripts/socratiQ/bundle.js
356+
book/tools/scripts/socratiQ/bundle.js
357+
# Generic bundle.js anywhere under scripts/ai_menu/dist/ (legacy build path
358+
# from issue #1175 — no longer in HEAD but defensively excluded).
359+
scripts/ai_menu/dist/bundle.js
360+
scripts/ai_menu/dist/*.bundle.js
361+
362+
# vault-cli check output — dump from `vault check` runs, regenerated on demand
363+
interviews/vault-cli/check_results.json

CONTRIBUTING.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,42 @@ Not sure which one applies? Open a
2929
[Discussion](https://github.com/harvard-edge/cs249r_book/discussions) and we'll
3030
help route it.
3131

32+
## Common gotchas first-time contributors hit
33+
34+
These are the things that aren't obvious from reading any single sub-project's
35+
README. Each links to the canonical doc rather than restating it.
36+
37+
* **TinyTorch uses the `tito` CLI for everything.** Module status, tests,
38+
exports, environment health all flow through `tito` (`tito --version`,
39+
`tito system health`, `tito module status`, `tito module test NN`). See
40+
[`tinytorch/CONTRIBUTING.md`](tinytorch/CONTRIBUTING.md) for the full
41+
command list. If `tito` isn't on your PATH after
42+
`pip install -e tinytorch/`, re-activate your venv.
43+
* **TinyTorch source edits need an export step.** When you change a file
44+
under `tinytorch/src/`, the in-package version under `tinytorch/tinytorch/`
45+
is regenerated by `tito src export` (see
46+
[`tinytorch/CONTRIBUTING.md`](tinytorch/CONTRIBUTING.md), "Module
47+
Development"). `tinytorch/tinytorch/*` is gitignored — the source of
48+
truth is `src/`.
49+
* **Co-Labs run in the browser via Pyodide / WebAssembly.** Imports must be
50+
Pyodide-compatible (no compiled-only packages without a wheel) and every
51+
Marimo cell that produces a UI element must `return` it so the dataflow
52+
routes it onward — that's release invariant #4 in
53+
[`labs/PROTOCOL.md`](labs/PROTOCOL.md). The lab test suite enforces both.
54+
* **Don't commit large binaries.** Distribution PDFs, EPUBs, podcast MP3s,
55+
and JS bundles balloon `.git` (see issues
56+
[#1393](https://github.com/harvard-edge/cs249r_book/issues/1393) and
57+
[#1175](https://github.com/harvard-edge/cs249r_book/issues/1175)). The
58+
root `.gitattributes` is set up so future EPUB / PDF / MP3 / MP4 / WAV /
59+
WASM additions land in Git LFS automatically. Generated artefacts
60+
(`bundle.js`, `corpus.json`, search indexes) are gitignored — regenerate
61+
them locally rather than committing.
62+
* **Where each area lives** — the table above is the authoritative map.
63+
At a glance: `book/` for the textbook, `tinytorch/` for the framework,
64+
`labs/` for browser labs, `kits/` for hardware recipes, `mlsysim/` for
65+
the simulator, `instructors/` for teaching materials, `slides/` for
66+
per-chapter decks, `interviews/` for StaffML.
67+
3268
## Universal policies (apply to every project)
3369

3470
These conventions hold across the whole monorepo. The per-project guides

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,8 +667,8 @@ Thanks goes to these wonderful people who have contributed to making this resour
667667
<tr>
668668
<td align="center" valign="top" width="14.29%"><a href="https://github.com/profvjreddi"><img src="https://avatars.githubusercontent.com/profvjreddi?v=4?s=50" width="50px;" alt="Vijay Janapa Reddi"/><br /><sub><b>Vijay Janapa Reddi</b></sub></a><br />🧑‍💻 🎨 ✍️ 🧠 </td>
669669
<td align="center" valign="top" width="14.29%"><a href="https://github.com/asgalon"><img src="https://avatars.githubusercontent.com/u/45242704?v=4?v=4?s=50" width="50px;" alt="Peter Koellner"/><br /><sub><b>Peter Koellner</b></sub></a><br />🪲 ✍️</td>
670+
<td align="center" valign="top" width="14.29%"><a href="https://github.com/Shashank-Tripathi-07"><img src="https://avatars.githubusercontent.com/u/178375647?v=4?v=4?s=50" width="50px;" alt="Rocky"/><br /><sub><b>Rocky</b></sub></a><br />🪲 🧑‍💻</td>
670671
<td align="center" valign="top" width="14.29%"><a href="https://github.com/hzeljko"><img src="https://avatars.githubusercontent.com/hzeljko?v=4?s=50" width="50px;" alt="Zeljko Hrcek"/><br /><sub><b>Zeljko Hrcek</b></sub></a><br />🧑‍💻</td>
671-
<td align="center" valign="top" width="14.29%"><a href="https://github.com/Shashank-Tripathi-07"><img src="https://avatars.githubusercontent.com/u/178375647?v=4?v=4?s=50" width="50px;" alt="Rocky"/><br /><sub><b>Rocky</b></sub></a><br />🧑‍💻</td>
672672
</tr>
673673
</tbody>
674674
</table>
@@ -775,6 +775,7 @@ Thanks goes to these wonderful people who have contributed to making this resour
775775
<tbody>
776776
<tr>
777777
<td align="center" valign="top" width="14.29%"><a href="https://github.com/profvjreddi"><img src="https://avatars.githubusercontent.com/profvjreddi?v=4?s=50" width="50px;" alt="Vijay Janapa Reddi"/><br /><sub><b>Vijay Janapa Reddi</b></sub></a><br />🧑‍💻 🎨 ✍️</td>
778+
<td align="center" valign="top" width="14.29%"><a href="https://github.com/Shashank-Tripathi-07"><img src="https://avatars.githubusercontent.com/u/178375647?v=4?v=4?s=50" width="50px;" alt="Rocky"/><br /><sub><b>Rocky</b></sub></a><br />🧑‍💻 ✍️ 🔎</td>
778779
<td align="center" valign="top" width="14.29%"><a href="https://github.com/farhan523"><img src="https://avatars.githubusercontent.com/u/62025759?v=4?v=4?s=50" width="50px;" alt="Farhan Asghar"/><br /><sub><b>Farhan Asghar</b></sub></a><br />🪲 🧑‍💻</td>
779780
</tr>
780781
</tbody>

instructors/.all-contributorsrc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@
3333
"bug",
3434
"code"
3535
]
36+
},
37+
{
38+
"login": "Shashank-Tripathi-07",
39+
"name": "Rocky",
40+
"avatar_url": "https://avatars.githubusercontent.com/u/178375647?v=4",
41+
"profile": "https://github.com/Shashank-Tripathi-07",
42+
"contributions": [
43+
"code",
44+
"doc",
45+
"review"
46+
]
3647
}
3748
]
3849
}

instructors/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ Thanks to these wonderful people who have helped build the Instructor Site!
109109
<tbody>
110110
<tr>
111111
<td align="center" valign="top" width="14.28%"><a href="https://github.com/profvjreddi"><img src="https://avatars.githubusercontent.com/profvjreddi?v=4?s=80" width="80px;" alt="Vijay Janapa Reddi"/><br /><sub><b>Vijay Janapa Reddi</b></sub></a><br />🧑‍💻 🎨 ✍️</td>
112+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Shashank-Tripathi-07"><img src="https://avatars.githubusercontent.com/u/178375647?v=4?v=4?s=80" width="80px;" alt="Rocky"/><br /><sub><b>Rocky</b></sub></a><br />🧑‍💻 ✍️ 🔎</td>
112113
<td align="center" valign="top" width="14.28%"><a href="https://github.com/farhan523"><img src="https://avatars.githubusercontent.com/u/62025759?v=4?v=4?s=80" width="80px;" alt="Farhan Asghar"/><br /><sub><b>Farhan Asghar</b></sub></a><br />🪲 🧑‍💻</td>
113114
</tr>
114115
</tbody>

instructors/foundations-syllabus.qmd

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ By Week 8, students should have a working TinyTorch that can: create tensors, ap
162162
| Component | Assignment |
163163
|:---|:---|
164164
| **Read** | [Model Compression](https://mlsysbook.ai/vol1/model_compression.html) |
165-
| **Lab** | [Lab 09](https://mlsysbook.ai/labs/vol1/lab_09_data_selection.html): Quantization (INT8/INT4) |
165+
| **Lab** | [Lab 09](https://mlsysbook.ai/labs/vol1/lab_09_data_selection.html): The Data Selection Paradox |
166166
| **Build** | [TinyTorch Module 08: Training](https://mlsysbook.ai/tinytorch/modules/08_training_ABOUT.html) |
167167
| **Due** | Module 07 notebook + Lab 09 Decision Log |
168168

@@ -178,7 +178,7 @@ Lab 09 is where students viscerally experience the accuracy-efficiency tradeoff.
178178
| Component | Assignment |
179179
|:---|:---|
180180
| **Read** | [Hardware Acceleration](https://mlsysbook.ai/vol1/hw_acceleration.html) |
181-
| **Lab** | [Lab 10](https://mlsysbook.ai/labs/vol1/lab_10_model_compress.html): The Roofline Model |
181+
| **Lab** | [Lab 10](https://mlsysbook.ai/labs/vol1/lab_10_model_compress.html): The Compression Paradox |
182182
| **Build** | TinyTorch Module 08: Training (continued) |
183183
| **Due** | Module 08 notebook + Lab 10 Decision Log |
184184

@@ -189,7 +189,7 @@ Lab 09 is where students viscerally experience the accuracy-efficiency tradeoff.
189189
| Component | Assignment |
190190
|:---|:---|
191191
| **Read** | [Benchmarking](https://mlsysbook.ai/vol1/benchmarking.html) |
192-
| **Lab** | [Lab 11](https://mlsysbook.ai/labs/vol1/lab_11_hw_accel.html): Benchmarking Methodology |
192+
| **Lab** | [Lab 11](https://mlsysbook.ai/labs/vol1/lab_11_hw_accel.html): The Hardware Roofline |
193193
| **Build** | *No new module — catch-up week* |
194194
| **Due** | Lab 11 Decision Log |
195195

@@ -206,7 +206,7 @@ Lab 09 is where students viscerally experience the accuracy-efficiency tradeoff.
206206
| Component | Assignment |
207207
|:---|:---|
208208
| **Read** | [Model Serving](https://mlsysbook.ai/vol1/serving.html) |
209-
| **Lab** | [Lab 12](https://mlsysbook.ai/labs/vol1/lab_12_perf_bench.html): Tail Latency (P99) |
209+
| **Lab** | [Lab 12](https://mlsysbook.ai/labs/vol1/lab_12_perf_bench.html): The Benchmarking Trap |
210210
| **Build** | *Capstone prep* |
211211
| **Due** | Lab 12 Decision Log |
212212

@@ -217,7 +217,7 @@ Lab 09 is where students viscerally experience the accuracy-efficiency tradeoff.
217217
| Component | Assignment |
218218
|:---|:---|
219219
| **Read** | [ML Operations](https://mlsysbook.ai/vol1/ops.html) |
220-
| **Lab** | [Lab 13](https://mlsysbook.ai/labs/vol1/lab_13_model_serving.html): Drift Detection |
220+
| **Lab** | [Lab 13](https://mlsysbook.ai/labs/vol1/lab_13_model_serving.html): The Tail Latency Trap |
221221
| **Build** | *Capstone prep* |
222222
| **Due** | Lab 13 Decision Log |
223223

@@ -228,7 +228,7 @@ Lab 09 is where students viscerally experience the accuracy-efficiency tradeoff.
228228
| Component | Assignment |
229229
|:---|:---|
230230
| **Read** | [Responsible Engineering](https://mlsysbook.ai/vol1/responsible_engr.html) |
231-
| **Lab** | [Lab 14](https://mlsysbook.ai/labs/vol1/lab_14_ml_ops.html): Fairness and Efficiency |
231+
| **Lab** | [Lab 14](https://mlsysbook.ai/labs/vol1/lab_14_ml_ops.html): The Silent Degradation Problem |
232232
| **Build** | *Capstone work* |
233233
| **Due** | Lab 14 Decision Log + Capstone draft |
234234

@@ -239,7 +239,7 @@ Lab 09 is where students viscerally experience the accuracy-efficiency tradeoff.
239239
| Component | Assignment |
240240
|:---|:---|
241241
| **Read** | [Conclusion](https://mlsysbook.ai/vol1/conclusion.html) |
242-
| **Lab** | [Lab 15](https://mlsysbook.ai/labs/vol1/lab_15_responsible_engr.html): Capstone Integration |
242+
| **Lab** | [Lab 15](https://mlsysbook.ai/labs/vol1/lab_15_responsible_engr.html): No Free Fairness |
243243
| **Capstone** | AI Olympics Competition |
244244
| **Due** | Final submission + 1,000-word design report |
245245

interviews/staffml/src/app/gauntlet/page.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,10 @@ export default function GauntletPage() {
202202
// worker responses come back, swap the questions state to the hydrated
203203
// copies. Until then the UI shows summaries (empty scenario/details).
204204
Promise.all(selected.map(q => getQuestionFullDetail(q.id))).then(results => {
205-
const hydrated = results.filter((q): q is Question => q !== undefined);
206-
if (hydrated.length === selected.length) setQuestions(hydrated);
205+
// Fall back to the original summary for any question the Worker couldn't hydrate
206+
// rather than silently discarding the entire batch when even one fetch fails.
207+
const merged = selected.map((s, i) => results[i] ?? s);
208+
setQuestions(merged);
207209
});
208210
}, [selectedTrack, selectedLevel, selectedDuration]);
209211

interviews/staffml/src/app/practice/page.tsx

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,22 @@ function PracticePage() {
393393
setNapkinResult(null);
394394
}, [mounted, selectedTrack, selectedLevel, selectedArea, selectedZone, napkinOnly, chainsOnly, visualOnly]);
395395

396+
const pickRandom = useCallback((fromPool?: Question[]) => {
397+
// Track skip if there was a current question that wasn't scored
398+
if (current && !showAnswer) {
399+
track({ type: 'question_skipped', topic: current.topic, level: current.level });
400+
}
401+
const p = fromPool || pool;
402+
if (p.length === 0) return;
403+
const idx = Math.floor(Math.random() * p.length);
404+
setCurrent(p[idx]);
405+
questionShownAt.current = Date.now();
406+
setShowAnswer(false);
407+
setUserAnswer("");
408+
setNapkinResult(null);
409+
setRubricItems([]);
410+
}, [pool, current, showAnswer]);
411+
396412
// Keyboard shortcuts: Enter to reveal, 1-4 for scoring, N to skip
397413
useEffect(() => {
398414
const handleKeyDown = (e: KeyboardEvent) => {
@@ -413,23 +429,7 @@ function PracticePage() {
413429
};
414430
window.addEventListener('keydown', handleKeyDown);
415431
return () => window.removeEventListener('keydown', handleKeyDown);
416-
}, [showAnswer, current]);
417-
418-
const pickRandom = useCallback((fromPool?: Question[]) => {
419-
// Track skip if there was a current question that wasn't scored
420-
if (current && !showAnswer) {
421-
track({ type: 'question_skipped', topic: current.topic, level: current.level });
422-
}
423-
const p = fromPool || pool;
424-
if (p.length === 0) return;
425-
const idx = Math.floor(Math.random() * p.length);
426-
setCurrent(p[idx]);
427-
questionShownAt.current = Date.now();
428-
setShowAnswer(false);
429-
setUserAnswer("");
430-
setNapkinResult(null);
431-
setRubricItems([]);
432-
}, [pool, current, showAnswer]);
432+
}, [showAnswer, current, pickRandom]);
433433

434434
// Submit-gradient guard: intercept reveals that look like
435435
// "didn't really try." The restructured layout puts the Reveal
@@ -578,7 +578,7 @@ function PracticePage() {
578578
setReviewMode(false);
579579
}
580580
pickRandom();
581-
}, [reviewMode, pool]);
581+
}, [reviewMode, pool, pickRandom]);
582582

583583
if (!mounted) {
584584
return (

0 commit comments

Comments
 (0)